diff --git a/.gitignore b/.gitignore index 7799d0529..e49a7a35b 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,7 @@ cpp/tests/results/matchsgfs2/games.sgfs cpp/data/ versions/ -cpp/build +cpp/build* cpp/out export_model_cuda.sh @@ -92,3 +92,5 @@ cpp/build.ninja cpp/KataGoSwift.* cpp/include/KataGoSwift/KataGoSwift-swift.h cpp/external/katagocoreml/proto/ + +.claude \ No newline at end of file diff --git a/Compiling.md b/Compiling.md index c601ceff0..01fba73c3 100644 --- a/Compiling.md +++ b/Compiling.md @@ -100,6 +100,7 @@ As also mentioned in the instructions below but repeated here for visibility, if * If using the OpenCL backend, a modern GPU that supports OpenCL 1.2 or greater, or else something like [this](https://software.intel.com/en-us/opencl-sdk) for CPU. But if using CPU, Eigen should be better. * If using the CUDA backend, CUDA 11 or later and a compatible version of CUDNN based on your CUDA version (https://developer.nvidia.com/cuda-toolkit) (https://developer.nvidia.com/cudnn) and a GPU capable of supporting them. I'm unsure how version compatibility works with CUDA, there's a good chance that later versions than these work just as well, but they have not been tested. * If using the TensorRT backend, in addition to a compatible CUDA Toolkit (https://developer.nvidia.com/cuda-toolkit), you also need TensorRT (https://developer.nvidia.com/tensorrt) that is at least version 8.5. + * If using the RyzenAI backend, an AMD Ryzen AI processor with its NPU enabled, AMD's NPU driver, and the [XRT SDK for Windows](https://github.com/Xilinx/XRT). Nothing else - the NPU kernels ship with KataGo. See the RyzenAI notes below. * If using the Eigen backend, Eigen3, version 3.3.x. (http://eigen.tuxfamily.org/index.php?title=Main_Page#Download). * zlib. Easy way to build zlib on Windows is to use vcpkg. Run in Powershell: * git clone https://github.com/microsoft/vcpkg.git @@ -146,6 +147,24 @@ As also mentioned in the instructions below but repeated here for visibility, if * For MinGW it's recommended to configure the project in the following ways: * Use the default MinGW toolchain in [CLion IDE](https://www.jetbrains.com/clion/) (free for Non-Commercial use) * Use [MSYS2](https://www.msys2.org/) MinGW toolchain. Befor configuring, install gcc compiler using pacman package manager: `pacman -S mingw-w64-x86_64-gcc` + * **RyzenAI backend (Windows):** + * Runs the neural net on the NPU built into AMD Ryzen AI processors (XDNA1 as in Phoenix/Hawk Point, XDNA2 as in Strix). The compiled NPU kernels are committed to this repository, so there is no tuning step, no model conversion, and nothing to install beyond the two requirements below. + * Requirements: + * AMD's NPU driver, and the NPU enabled in the BIOS. `katago benchmark` reports which NPU it found, or says none was found. + * The [XRT SDK for Windows](https://github.com/Xilinx/XRT). CMake looks in `%XILINX_XRT%` and then `C:\Xilinx\XRT`; pass `-DXRT_ROOT=` if it lives elsewhere. + * Visual Studio Build Tools with the "Desktop development with C++" workload, and zlib (conda and vcpkg both ship one). + * Build. CMake locates the C++ toolchain, the XRT SDK and zlib itself, so an ordinary shell is enough - a Developer Command Prompt is *not* required: + ``` + cd cpp + mkdir build + cd build + cmake .. -G Ninja -DUSE_BACKEND=RYZENAI -DCMAKE_BUILD_TYPE=Release + cmake --build . --parallel + ``` + `ninja` works in place of `cmake --build .` if you have it on your PATH. If CMake cannot find something it names what and where to get it; `-DZLIB_ROOT=...` and `-DXRT_RUNTIME_DLL_DIR=...` override the search. + * The build directory runs as-is: `katago.exe`, the XRT runtime DLLs beside it, and the NPU kernels in a `ryzenai` subdirectory. Copy all three together if you move it. + * **Precision:** on XDNA2 the default is block floating point, which is faster; `ryzenaiDtype = bf16` in the config selects the more accurate format instead. XDNA1 only has bf16. Either way the NPU is not computing in fp32, so its outputs differ slightly from the CPU backends - enough to pick differently between two nearly-equal moves, not enough to matter for strength. + * **Regenerating the NPU kernels** - only needed for a network shape that has no kernel yet, which is rare: the shipped set covers every reduction dimension up to 6912. See [python/ryzenai_kernels/README.md](python/ryzenai_kernels/README.md). * Done! You should now have a compiled `katago.exe` executable in your working directory. * Note: You may need to copy the ".dll" files corresponding to the various ".lib" (".a") files you compiled with into the directory containing katago.exe. * MinGW has different dlls. If you use pacman, the necessary dlls (`libbz2-1.dll`, `libzip.dll`, `libzstd.dll`, `liblzma-5.dll`) should be copied from MinGW bin directory (like `C:\msys64\mingw64\bin`). @@ -158,7 +177,7 @@ As also mentioned in the instructions below but repeated here for visibility, if * The ROCm (MIOpen) backend supports Windows via [AMD TheRock](https://github.com/ROCm/TheRock) (tested with TheRock 7.13 / ROCm 7.13, RX 7900 XTX / gfx1100), including transformer/attention models (model version 17+) and the optional Composable Kernel (CK) fused-attention fast path. * **Prerequisites:** * Download [AMD TheRock](https://github.com/ROCm/TheRock) and extract it to e.g. `C:\TheRock\build`, adjusting the paths below if you extract elsewhere. - * Install **Visual Studio Build Tools or Community** with the "Desktop development with C++" workload, for the MSVC toolchain and Windows SDK the HIP compiler needs. A **v143 toolset (MSVC 14.3x or 14.4x)** must be among the installed toolsets - newer toolsets alone (14.5x+) are not accepted by the HIP clang compatibility check. If more than one is installed side by side, `CMakeLists.txt` automatically probes them at configure time and picks a compatible one itself (see "Fully automatic" below), no manual toolset selection needed. + * Install **Visual Studio Build Tools or Community** with the "Desktop development with C++" workload, for the MSVC toolchain and Windows SDK the HIP compiler needs. If several toolsets are installed side by side, `CMakeLists.txt` probes them at configure time - newest first - and picks the first one the HIP compiler actually accepts (see "Fully automatic" below), no manual toolset selection needed. Note that a very new MSVC STL can be ahead of the clang bundled with TheRock; if configure reports that no installed toolset works, add an older one such as **MSVC v143 (14.3x/14.4x)** from the Visual Studio Installer's "Individual Components" tab. * Install [Ninja](https://ninja-build.org) build tool: `winget install Ninja-build.Ninja`. * Set the following **system environment variables** (via System Properties -> Advanced -> Environment Variables): ``` @@ -186,9 +205,9 @@ As also mentioned in the instructions below but repeated here for visibility, if Windows-specific setup automatically at configure/build time: * **MSVC toolset selection:** if more than one MSVC toolset is installed side by side, a newer one can conflict with TheRock's bundled clang (newer MSVC STL headers are not yet - compatible with it). `CMakeLists.txt` finds the installed v143-family toolsets via - `vswhere` and probes each with a real compile until one works, with no user action - needed. + compatible with it). `CMakeLists.txt` enumerates every installed toolset via + `vswhere` and probes them newest-first with a real compile until one works, with + no user action needed. * **zlib:** TheRock's Windows package ships `zlib.h` but (as of 7.13) no longer ships a linkable `.lib`. `CMakeLists.txt` automatically bootstraps a local [vcpkg](https://github.com/microsoft/vcpkg) clone under `/deps/vcpkg` (this diff --git a/README.md b/README.md index f34a1628c..518f731a2 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ - [GUIs](#guis) - [Windows and Linux](#windows-and-linux) - [MacOS](#macos) - - [OpenCL vs CUDA vs TensorRT vs ROCm vs Eigen](#opencl-vs-cuda-vs-tensorrt-vs-rocm-vs-eigen) + - [OpenCL vs CUDA vs TensorRT vs ROCm vs RyzenAI vs Eigen](#opencl-vs-cuda-vs-tensorrt-vs-rocm-vs-ryzenai-vs-eigen) - [How To Use](#how-to-use) - [Human-style Play and Analysis](#human-style-play-and-analysis) - [Other Commands:](#other-commands) @@ -88,8 +88,8 @@ The community also provides KataGo packages for [Homebrew](https://brew.sh) on M Use `brew install katago`. The latest config files and networks are installed in KataGo's `share` directory. Find them via `brew list --verbose katago`. A basic way to run katago will be `katago gtp -config $(brew list --verbose katago | grep 'gtp.*\.cfg') -model $(brew list --verbose katago | grep .gz | head -1)`. You should choose the Network according to the release notes here and customize the provided example config as with every other way of installing KataGo. -### OpenCL vs CUDA vs TensorRT vs ROCm vs Eigen -KataGo has five backends, OpenCL (GPU), CUDA (GPU), TensorRT (GPU), ROCm (GPU), and Eigen (CPU). (On macOS there is also a Metal backend, most easily obtained via homebrew - see above.) +### OpenCL vs CUDA vs TensorRT vs ROCm vs RyzenAI vs Eigen +KataGo has six backends, OpenCL (GPU), CUDA (GPU), TensorRT (GPU), ROCm (GPU), RyzenAI (AMD NPU), and Eigen (CPU). (On macOS there is also a Metal backend, most easily obtained via homebrew - see above.) As of v1.17, KataGo supports transformer neural nets, which are generally much stronger for the same compute cost and which the main training run is switching to. Transformer models are more demanding on the GPU backend than the older convolutional nets, so the backend recommendations below matter more for them - in particular OpenCL is noticeably slower on transformers, and on NVIDIA the CUDNN and TensorRT versions make a large difference. @@ -100,12 +100,14 @@ The quick summary is: * Use Eigen without AVX2 if your CPU is old or on a low-end device that doesn't support AVX2. * The CUDA+CUDNN backend can also work well for NVIDIA GPUs. It has faster startup than TensorRT and is competitive on transformers if using CUDNN >= 9.8.0, though TensorRT 10.16 is often still slightly faster. * The ROCm backend can work for AMD GPUs with ROCm+MIOpen installed, and is much faster than OpenCL on AMD datacenter (CDNA) GPUs. + * Use RyzenAI on a Ryzen AI laptop, if you would rather run on its NPU than on its integrated GPU or CPU. More in detail: * OpenCL is a general GPU backend should be able to run with any GPUs or accelerators that support [OpenCL](https://en.wikipedia.org/wiki/OpenCL), including NVIDIA GPUs, AMD GPUs, as well CPU-based OpenCL implementations or things like Intel Integrated Graphics. This is the most general GPU version of KataGo and doesn't require a complicated install like CUDA does, so is most likely to work out of the box as long as you have a fairly modern GPU. **However, it also need to take some time when run for the very first time to tune itself.** For many systems, this will take 5-30 seconds, but on a few older/slower systems, may take many minutes or longer. Also, the quality of OpenCL implementations is sometimes inconsistent, particularly for Intel Integrated Graphics and for AMD GPUs that are older than several years, so it might not work for very old machines, as well as specific buggy newer AMD GPUs, see also [Issues with specific GPUs or GPU drivers](#issues-with-specific-gpus-or-gpu-drivers). OpenCL is not as optimized as the NVIDIA-specific backends and will generally be slower, particularly for transformer models. * CUDA is a GPU backend specific to NVIDIA GPUs (it will not work with AMD or Intel or any other GPUs) and requires installing [CUDA](https://developer.nvidia.com/cuda-zone) and [CUDNN](https://developer.nvidia.com/cudnn) and a modern NVIDIA GPU. For older convolutional nets, on many GPUs the OpenCL implementation can match or beat NVIDIA's own CUDA/CUDNN, with the exception of top-end NVIDIA GPUs that support FP16 and tensor cores. For transformer nets, CUDA+CUDNN clearly outperforms OpenCL, but you should use CUDNN >= 9.8.0 if at all possible - the older CUDNN 8.9.7 is a LOT slower on transformer models. Compared to TensorRT, CUDA+CUDNN has faster startup times and is often only slightly slower (and occasionally faster) on transformers. * TensorRT is similar to CUDA, but uses NVIDIA's TensorRT framework to run the neural network with more optimized kernels. For modern NVIDIA GPUs it should work whenever CUDA does, and will usually be the fastest backend, though it has much longer startup times on every launch. As of v1.17.0, TensorRT versions older than 10 are no longer supported. For transformer models, recent versions like CUDA 13 + TensorRT 10.16 are best, while older TensorRT versions can be outperformed by CUDA+CUDNN. * ROCm is a GPU backend specific to AMD GPUs (it will not work with NVIDIA or Intel or any other GPUs) and requires installing [ROCm](https://rocm.docs.amd.com) and [MIOpen](https://rocm.docs.amd.com/projects/MIOpen) and a modern AMD GPU. It supports both **Linux** (via official ROCm packages, ROCm 6.4+) and **Windows** (via [AMD TheRock](https://github.com/ROCm/TheRock) builds). Performance relative to OpenCL depends on the GPU. On AMD's datacenter accelerators (CDNA), ROCm is much faster than OpenCL: measured on an MI300X at roughly 2.5x for convolutional nets and 6-12x for transformers. On consumer (RDNA) GPUs the two are closer and either may win depending on the GPU and driver, so if you want the best choice, run KataGo's benchmark with both. Transformer/attention-based neural nets (model version 17+) are supported on all AMD GPUs, and get an additional fused-attention speedup on CDNA and RDNA3/RDNA3.5/RDNA4 GPUs when AMD's Composable Kernel library is also installed (see [Compiling.md](Compiling.md)). + * RyzenAI is a backend for the *NPU* built into AMD Ryzen AI laptop processors (XDNA1 as in Phoenix/Hawk Point, XDNA2 as in Strix). It will not work with anything else - not AMD GPUs, and not older Ryzen chips without an NPU. It needs only AMD's NPU driver and the [XRT runtime](https://github.com/Xilinx/XRT); the compiled NPU kernels ship with KataGo, so there is no tuning step and no per-model setup. It reads `.bin.gz` models directly like every other backend. On a Strix laptop it runs roughly 5-11x faster than the Eigen CPU backend on the same machine, with the larger nets gaining the most, and it leaves the CPU almost entirely free for the search itself. Whether it beats that laptop's integrated GPU under OpenCL depends on the model and the machine, so run KataGo's benchmark with both if you want the best choice. Accuracy note: the NPU computes in bfloat16 or block floating point rather than fp32, which shifts the network's outputs slightly - enough to change the engine's choice between two moves it considers nearly equal, not enough to affect playing strength. See [Compiling.md](Compiling.md) for build instructions, and `ryzenaiDtype` in the example config to trade a little speed for more accuracy. * Eigen is a *CPU* backend that should work widely *without* needing a GPU or fancy drivers. Use this if you don't have a good GPU or really any GPU at all. It will be quite significantly slower than OpenCL or CUDA, but on a good CPU can still often get 10 to 20 playouts per second if using the smaller (15 or 20) block neural nets. Eigen can also be compiled with AVX2 and FMA support, which can provide a big performance boost for Intel and AMD CPUs from the last few years. However, it will not run at all on older CPUs (and possibly even some recent but low-power modern CPUs) that don't support these fancy vector instructions. For **any** implementation, it's recommended that you also tune the number of threads used if you care about optimal performance, as it can make a factor of 2-3 difference in the speed. See "Tuning for Performance" below. However, if you mostly just want to get it working, then the default untuned settings should also be still reasonable. @@ -181,6 +183,27 @@ The most important parameter to optimize for KataGo's performance is the number Secondarily, you can also read over the parameters in your GTP config (`default_gtp.cfg` or `gtp_example.cfg` or `configs/gtp_example.cfg`, etc). A lot of other settings are described in there that you can set to adjust KataGo's resource usage, or choose which GPUs to use. You can also adjust things like KataGo's resign threshold, pondering behavior or utility function. Most parameters are documented directly inline in the [example config file](cpp/configs/gtp_example.cfg). Many can also be interactively set when generating a config via the `genconfig` command described above. +#### RyzenAI config parameters + +All of these are optional - the defaults are what you want unless you are measuring something. Add them to whichever config you run with. + +| Parameter | Values | Default | What it does | +| --- | --- | --- | --- | +| `ryzenaiDtype` | `auto`, `bf16`, `bfp16` | `auto` | Numeric format for the NPU kernels. `auto` picks block floating point on XDNA2 and bf16 on XDNA1, which is the only format XDNA1 has. `bf16` is the more accurate of the two and costs roughly 10% throughput; set it explicitly if you would rather have the precision. | +| `ryzenaiMaxColumns` | 0-64 | `4` | How many of the NPU's columns one kernel may use. More is not automatically better: a small net gets *slower* with more columns, because each distinct kernel is its own hardware context and the driver ends up switching between them. Large nets do benefit. Measure with `katago benchmark` before changing it. | +| `ryzenaiForceNpuOnly` | bool | `false` | Refuse to fall back to the CPU. Normally a layer with no matching kernel quietly runs on the CPU instead, which is correct but slower; this turns that into a hard failure, which is what you want when verifying that the NPU is really being used. | +| `ryzenaiArtifactDir` | path | next to the executable | Where the `.xclbin` kernels live. Pointing it at a nonexistent directory forces the whole network onto the CPU reference path, which is the simplest way to compare NPU output against CPU output. | +| `ryzenaiVerboseDispatch` | bool | `false` | Log where the time went: host-side packing, NPU dispatch, unpacking, and the operators still running on the CPU. Also reports any kernel that was wanted but missing. Start here when performance is not what you expect. | +| `ryzenaiShapeReport` | bool | `false` | Log every matrix shape the loaded model asks for. Needed only when generating kernels for a new network - see [Compiling.md](Compiling.md). | +| `ryzenaiForceK` | -1 to 65536 | `-1` | Collapse every layer onto one kernel by padding their reduction dimensions up to this value, trading wasted arithmetic for fewer context switches. `-1` lets KataGo decide per model, which is almost always right. | +| `ryzenaiSelfTest` | bool | `false` | Run a built-in matrix-multiply check against the NPU at startup. | +| `ryzenaiDeviceToUse` | int | `0` | Which NPU, on a machine with more than one. `ryzenaiDeviceToUseThread0`, `...Thread1` and so on assign devices per neural net thread, exactly as the equivalent OpenCL and CUDA settings do. | + +Two things worth knowing beyond the parameters: + + * **Threads matter more here than the settings above.** The NPU pays a fixed cost per dispatch, and KataGo amortizes it by batching evaluations from several search threads into one. Going from `numSearchThreads = 1` to `16` measured about 1.9x more evaluations per second on the same hardware - a bigger win than anything in the table. `katago benchmark` will suggest a value for your machine. + * **The NPU does not compute in fp32**, so its policy and value outputs differ slightly from the CPU backends. The difference is small enough that the top moves come out the same, but large enough to flip the engine's choice between two moves it considers nearly equal. If you need bit-reproducibility across machines, use a CPU backend. + ### Common Questions and Issues This section summarizes a number of common questions and issues when running KataGo. diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 3cc803444..7598d9980 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -137,15 +137,32 @@ function(katago_win_apply_vcvarsall vcvarsall_bat vcvars_ver) if(NOT _rc EQUAL 0 OR NOT EXISTS "${_out_file}") return() endif() - # Read line-by-line via file(STRINGS) rather than splitting the raw output ourselves - INCLUDE/ - # LIB/PATH are themselves semicolon-separated, which would corrupt a naive string(REPLACE "\n" ";" - # ...) split. file(STRINGS) keeps each real line, with its embedded semicolons, as one entry. - file(STRINGS "${_out_file}" _env_lines) - foreach(_line IN LISTS _env_lines) + # Walk the dump one line at a time with plain string operations, NOT via a cmake list (which is + # what file(STRINGS) hands back). Two properties of this output make list handling wrong: + # INCLUDE/LIB/PATH are themselves semicolon-separated, and Windows values routinely end in a + # backslash (VSINSTALLDIR, WindowsSdkBinPath, ...). A line ending in "\" turns the list + # separator that follows it into an escaped ";" when the list is expanded, silently gluing the + # next variable onto this one's value (e.g. VSINSTALLDIR ending up as + # "...\BuildTools;windir=C:\Windows") and losing that next variable entirely. A corrupt + # VSINSTALLDIR in turn breaks any *subsequent* vcvarsall call, whose -vcvars_ver check resolves + # against it ("Version '...' is not valid; directory does not exist"), which is exactly what + # probing more than one toolset in a single configure run does. + file(READ "${_out_file}" _env_raw) + string(REPLACE "\r\n" "\n" _env_raw "${_env_raw}") + while(NOT _env_raw STREQUAL "") + string(FIND "${_env_raw}" "\n" _nl) + if(_nl EQUAL -1) + set(_line "${_env_raw}") + set(_env_raw "") + else() + string(SUBSTRING "${_env_raw}" 0 ${_nl} _line) + math(EXPR _nl_next "${_nl} + 1") + string(SUBSTRING "${_env_raw}" ${_nl_next} -1 _env_raw) + endif() if(_line MATCHES "^([A-Za-z_][A-Za-z0-9_().]*)=(.*)$") set(ENV{${CMAKE_MATCH_1}} "${CMAKE_MATCH_2}") endif() - endforeach() + endwhile() endfunction() # Helper: with the given HIP compiler and whatever environment is currently active, try compiling a @@ -184,22 +201,23 @@ function(katago_win_pathlist_to_flags pathlist flagprefix out_var) set(${out_var} "${_flags}" PARENT_SCOPE) endfunction() -# Helper: find an MSVC "v143" toolset (possibly one of several 14.3x/14.4x versions installed -# side-by-side under one or more VS installs) whose STL doesn't conflict with the HIP compiler's -# own CUDA/HIP math forward-declare headers, apply the vcvarsall.bat environment for it (so the -# rest of THIS configure run - the HIP arch probing below, and project()'s own HIP compiler ABI -# test - see it), and also bake the resulting INCLUDE/LIB paths into cached compiler/linker flags -# so a later, separate `ninja` invocation (which does NOT inherit this configure run's environment -# - see katago_win_apply_vcvarsall's comment) keeps working too. +# Helper: find an MSVC toolset (possibly one of several versions installed side-by-side under one +# or more VS installs) whose STL doesn't conflict with the HIP compiler's own CUDA/HIP math +# forward-declare headers, apply the vcvarsall.bat environment for it (so the rest of THIS +# configure run - the HIP arch probing below, and project()'s own HIP compiler ABI test - see it), +# and also bake the resulting INCLUDE/LIB paths into cached compiler/linker flags so a later, +# separate `ninja` invocation (which does NOT inherit this configure run's environment - see +# katago_win_apply_vcvarsall's comment) keeps working too. # -# Deliberately pinned to the v143 toolset family (MSVC 14.3x/14.4x) rather than probing every -# installed toolset regardless of version: a newer MSVC STL (seen with a VS "18" preview-channel -# toolset, MSVC 14.51+, i.e. the next "v144" family) declares math functions like isgreater/isless -# in a way that conflicts with clang's forward declarations for CUDA/HIP device overloads ("device -# function cannot overload host device function"), because that clang version predates the STL's -# newly-added declarations. v143 is the toolset known to work with TheRock's clang. Probe within -# the v143 family (oldest first) rather than hardcoding one exact version, since multiple v143 -# point releases can be installed side by side and this needs one that's actually present. +# Every installed toolset is a candidate, probed NEWEST FIRST, and the compile probe - not a +# hardcoded version range - decides which one gets used. The conflict this guards against is real: +# some MSVC STL versions (first seen with a VS "18" preview-channel toolset, MSVC 14.51, i.e. the +# "v144" family) declare math functions like isgreater/isless in a way that clashes with clang's +# forward declarations for CUDA/HIP device overloads ("device function cannot overload host device +# function"), when that clang predates the STL's newly-added declarations. But that is a property +# of the specific STL/clang pair in front of us, not of the toolset family, so newer TheRock +# builds are free to start accepting newer toolsets without an edit here - they just get picked +# up. If the newest toolset fails the probe, the next-newest is tried, on down to the oldest. function(katago_win_autoselect_msvc_toolset hip_compiler) katago_win_find_vswhere(_vswhere) if(NOT _vswhere) @@ -226,11 +244,6 @@ function(katago_win_autoselect_msvc_toolset hip_compiler) foreach(_t IN LISTS _tool_dirs) if(IS_DIRECTORY "${_t}" AND EXISTS "${_t}/include/cmath") get_filename_component(_ver "${_t}" NAME) - # v143 toolset versions are 14.3x/14.4x (the next-generation "v144" toolset, seen with - # VS 18 preview builds, starts at 14.5x and is the one known to conflict - see above). - if(NOT _ver MATCHES "^14\\.[34][0-9]\\.") - continue() - endif() set(_vcvarsall "${_install_path}/VC/Auxiliary/Build/vcvarsall.bat") if(EXISTS "${_vcvarsall}") list(APPEND _toolsets "${_ver}|${_vcvarsall}") @@ -240,12 +253,28 @@ function(katago_win_autoselect_msvc_toolset hip_compiler) endforeach() if(NOT _toolsets) - message(FATAL_ERROR "No installed MSVC v143 toolset (14.3x/14.4x) found. Open the Visual Studio Installer, choose \"Modify\" on your VS installation, go to \"Individual Components\", and install \"MSVC v143 - VS 2022 C++ x64/x86 build tools\" (a newer toolset alone, e.g. a VS 18 preview's v144, is not compatible with TheRock's bundled clang).") + message(FATAL_ERROR "No installed MSVC toolset found under any Visual Studio installation. Open the Visual Studio Installer, choose \"Modify\" on your VS installation, go to \"Individual Components\", and install an \"MSVC ... C++ x64/x86 build tools\" component.") endif() list(REMOVE_DUPLICATES _toolsets) - list(SORT _toolsets COMPARE NATURAL ORDER ASCENDING) + # Newest first: prefer the most recent toolset installed, falling back to older ones only if the + # probe below rejects it. + list(SORT _toolsets COMPARE NATURAL ORDER DESCENDING) + + # vcvarsall.bat PREPENDS to these rather than replacing them, so probing a second toolset in the + # same cmake process would otherwise leave the rejected toolset's directories trailing behind the + # accepted one's - and those leftovers would get baked into the cached flags below. Snapshot the + # pre-vcvars values and restore them before each attempt so every probe starts from the same + # clean environment. + # Held in one variable per name rather than a list: these values are themselves + # semicolon-separated, which a cmake list would happily shred. + foreach(_env_var PATH INCLUDE LIB LIBPATH) + set(_orig_env_${_env_var} "$ENV{${_env_var}}") + endforeach() foreach(_entry IN LISTS _toolsets) + foreach(_env_var PATH INCLUDE LIB LIBPATH) + set(ENV{${_env_var}} "${_orig_env_${_env_var}}") + endforeach() string(REPLACE "|" ";" _entry_list "${_entry}") list(GET _entry_list 0 _ver) list(GET _entry_list 1 _vcvarsall) @@ -292,7 +321,7 @@ function(katago_win_autoselect_msvc_toolset hip_compiler) message(STATUS "MSVC toolset ${_ver} conflicts with the HIP compiler's CUDA/HIP math headers; trying another") endif() endforeach() - message(FATAL_ERROR "None of the installed MSVC v143 toolset(s) (14.3x/14.4x) compiled cleanly against TheRock's HIP compiler. This indicates a problem beyond the usual v143-vs-newer-toolset conflict this check is meant to catch - please report this along with the MSVC/TheRock versions involved.") + message(FATAL_ERROR "None of the installed MSVC toolsets compiled cleanly against TheRock's HIP compiler. A newer MSVC STL can conflict with an older bundled clang (\"device function cannot overload host device function\"); if every installed toolset is affected, install an older one - e.g. \"MSVC v143 - VS 2022 C++ x64/x86 build tools\" from the Visual Studio Installer's \"Individual Components\" tab - or use a newer TheRock distribution.") endfunction() # Normalize case here too (it is normalized again later next to the cache definition): the @@ -300,6 +329,86 @@ endfunction() # e.g. -DUSE_BACKEND=rocm would otherwise silently skip all the ROCm pre-project setup. string(TOUPPER "${USE_BACKEND}" USE_BACKEND) +# The RyzenAI backend compiles with cl.exe, so unlike the ROCm path above it +# needs no toolset probing and no version pin - just the environment vcvarsall +# would set, so that configuring with Ninja works from an ordinary shell instead +# of only from a Developer Command Prompt. Reuses the helpers defined above. +# +# CMAKE_HOST_WIN32 rather than WIN32: the latter is a result of platform +# detection inside project(), so it is still undefined here. The guard asks +# whether the environment is usable rather than whether a variable happens to +# exist, because a stray empty VCToolsInstallDir would otherwise skip the +# bootstrap and leave the build with no compiler at all. +if(USE_BACKEND STREQUAL "RYZENAI" AND CMAKE_HOST_WIN32 AND NOT CMAKE_CXX_COMPILER) + set(_katago_vctools "$ENV{VCToolsInstallDir}") + set(_katago_include "$ENV{INCLUDE}") + string(STRIP "${_katago_vctools}" _katago_vctools) + string(STRIP "${_katago_include}" _katago_include) + if(_katago_vctools STREQUAL "" OR _katago_include STREQUAL "") + katago_win_find_vswhere(_katago_vswhere) + if(_katago_vswhere) + execute_process( + COMMAND "${_katago_vswhere}" -all -products * -property installationPath + OUTPUT_VARIABLE _katago_vs_raw OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + string(REPLACE "\r\n" "\n" _katago_vs_raw "${_katago_vs_raw}") + string(REPLACE "\n" ";" _katago_vs_paths "${_katago_vs_raw}") + set(_katago_best_ver "") + set(_katago_best_bat "") + foreach(_p IN LISTS _katago_vs_paths) + if(_p STREQUAL "") + continue() + endif() + file(TO_CMAKE_PATH "${_p}" _p) + if(NOT EXISTS "${_p}/VC/Auxiliary/Build/vcvarsall.bat") + continue() + endif() + # Version comes from the toolset directory name; require its headers to + # be present so a partially-installed toolset is not selected. Compare + # as versions, not strings: list(SORT) mis-orders 14.9 against 14.40. + file(GLOB _katago_tool_dirs "${_p}/VC/Tools/MSVC/*") + foreach(_t IN LISTS _katago_tool_dirs) + if(IS_DIRECTORY "${_t}" AND EXISTS "${_t}/include/cmath") + get_filename_component(_ver "${_t}" NAME) + if(_ver MATCHES "^[0-9]+\\.[0-9]+" + AND (_katago_best_ver STREQUAL "" OR _ver VERSION_GREATER _katago_best_ver)) + set(_katago_best_ver "${_ver}") + set(_katago_best_bat "${_p}/VC/Auxiliary/Build/vcvarsall.bat") + endif() + endif() + endforeach() + endforeach() + if(_katago_best_ver STREQUAL "") + message(WARNING "KataGo: no Visual Studio C++ toolchain found via vswhere. Install the " + "\"Desktop development with C++\" workload, or configure from a Developer " + "Command Prompt.") + else() + katago_win_apply_vcvarsall("${_katago_best_bat}" "${_katago_best_ver}") + message(STATUS "KataGo: using MSVC toolset ${_katago_best_ver} (found via vswhere)") + # The environment applied above lasts only for this configure run. A + # later, separate `ninja` is a sibling process that inherits none of it, + # so cl.exe would be found by its baked-in full path and then fail on + # . Bake the resolved INCLUDE/LIB into flags after project(). + katago_win_pathlist_to_flags("$ENV{INCLUDE}" "/I" _katago_msvc_incflags) + katago_win_pathlist_to_flags("$ENV{LIB}" "/LIBPATH:" _katago_msvc_libflags) + # Visual Studio bundles Ninja, but only on the IDE's private PATH. + if(CMAKE_GENERATOR MATCHES "Ninja" AND NOT CMAKE_MAKE_PROGRAM) + find_program(_katago_ninja ninja) + if(NOT _katago_ninja) + get_filename_component(_katago_vs_root "${_katago_best_bat}" DIRECTORY) + get_filename_component(_katago_vs_root "${_katago_vs_root}/../../.." ABSOLUTE) + set(_katago_bundled_ninja + "${_katago_vs_root}/Common7/IDE/CommonExtensions/Microsoft/CMake/Ninja/ninja.exe") + if(EXISTS "${_katago_bundled_ninja}") + set(CMAKE_MAKE_PROGRAM "${_katago_bundled_ninja}" CACHE FILEPATH "" FORCE) + message(STATUS "KataGo: using Ninja bundled with Visual Studio") + endif() + endif() + endif() + endif() + endif() + endif() +endif() + if(USE_BACKEND STREQUAL "METAL") project(katago LANGUAGES CXX Swift) elseif(USE_BACKEND STREQUAL "ROCM") @@ -514,6 +623,17 @@ else() project(katago) endif() +# See the bootstrap block above: these carry the auto-detected toolchain's header and library +# search paths into the generated build files, so building later from a plain shell works. +if(_katago_msvc_incflags) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}${_katago_msvc_incflags}" CACHE STRING "" FORCE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}${_katago_msvc_incflags}" CACHE STRING "" FORCE) + foreach(_lk EXE SHARED MODULE) + set(CMAKE_${_lk}_LINKER_FLAGS "${CMAKE_${_lk}_LINKER_FLAGS}${_katago_msvc_libflags}" + CACHE STRING "" FORCE) + endforeach() +endif() + set(CMAKE_CXX_STANDARD 17) if(NOT CMAKE_CONFIGURATION_TYPES) @@ -553,7 +673,7 @@ endif() set(BUILD_DISTRIBUTED 0 CACHE BOOL "Build with http support for contributing to distributed training") set(USE_BACKEND CACHE STRING "Neural net backend") string(TOUPPER "${USE_BACKEND}" USE_BACKEND) -set_property(CACHE USE_BACKEND PROPERTY STRINGS "" CUDA TENSORRT OPENCL EIGEN METAL ONNX ROCM) +set_property(CACHE USE_BACKEND PROPERTY STRINGS "" CUDA TENSORRT OPENCL EIGEN METAL ONNX ROCM RYZENAI) set(USE_TCMALLOC 0 CACHE BOOL "Use TCMalloc") set(NO_GIT_REVISION 0 CACHE BOOL "Disable embedding the git revision into the compiled exe") @@ -787,6 +907,19 @@ elseif(USE_BACKEND STREQUAL "EIGEN") set(NEURALNET_BACKEND_SOURCES neuralnet/eigenbackend.cpp ) +elseif(USE_BACKEND STREQUAL "RYZENAI") + message(STATUS "-DUSE_BACKEND=RYZENAI, using AMD Ryzen AI NPU (XDNA/XDNA2) backend.") + set(NEURALNET_BACKEND_SOURCES + neuralnet/ryzenaibackend.cpp + neuralnet/ryzenaidevice.cpp + neuralnet/ryzenaikernel.cpp + neuralnet/ryzenaireference.cpp + neuralnet/ryzenaisequence.cpp + neuralnet/ryzenaishapes.cpp + neuralnet/ryzenaimatmul.cpp + ) +elseif(USE_BACKEND STREQUAL "") + message(WARNING "${ColorBoldRed}WARNING: Using dummy neural net backend, intended for non-neural-net testing only, will fail on any code path requiring a neural net. To use neural net, specify -DUSE_BACKEND=CUDA or -DUSE_BACKEND=TENSORRT or -DUSE_BACKEND=OPENCL or -DUSE_BACKEND=EIGEN or -DUSE_BACKEND=RYZENAI to compile with the respective backend.${ColorReset}") elseif(USE_BACKEND STREQUAL "ONNX") message(STATUS "-DUSE_BACKEND=ONNX, using ONNX Runtime backend.") set(NEURALNET_BACKEND_SOURCES @@ -1587,6 +1720,96 @@ elseif(USE_BACKEND STREQUAL "EIGEN") message(STATUS "Found Eigen3 at ${EIGEN3_INCLUDE_DIRS}") endif() endif() +elseif(USE_BACKEND STREQUAL "RYZENAI") + target_compile_definitions(katago PRIVATE USE_RYZENAI_BACKEND) + message(STATUS "RyzenAI backend: talks to the NPU directly through XRT.") + message(STATUS " It does NOT require the AMD Ryzen AI Software SDK, ONNX Runtime, or Python.") + message(STATUS " Build time needs the XRT SDK; run time needs only the NPU driver.") + + # ---- XRT SDK discovery ---- + # Nothing here hardcodes a path or a version. Resolution order: + # 1. -DXRT_ROOT=... given on the command line + # 2. the XILINX_XRT environment variable (set by XRT's own setup scripts on + # Linux, and by the Windows XRT SDK install step) + # 3. CMake's normal search paths + set(XRT_ROOT "" CACHE PATH "Root of the XRT SDK. Falls back to the XILINX_XRT environment variable.") + # Consult both every configure. Seeding the cache entry from the environment + # instead would stick on whatever the first configure saw, so installing the + # SDK afterwards would not be picked up without wiping the build directory. + set(_katago_xrt_hints "") + if(XRT_ROOT) + list(APPEND _katago_xrt_hints "${XRT_ROOT}") + endif() + if(DEFINED ENV{XILINX_XRT} AND NOT "$ENV{XILINX_XRT}" STREQUAL "") + list(APPEND _katago_xrt_hints "$ENV{XILINX_XRT}") + endif() + find_path(XRT_INCLUDE_DIR + NAMES xrt/xrt_device.h + HINTS ${_katago_xrt_hints} + PATH_SUFFIXES include + DOC "Directory containing xrt/xrt_device.h" + ) + find_library(XRT_COREUTIL_LIBRARY + NAMES xrt_coreutil + HINTS ${_katago_xrt_hints} + PATH_SUFFIXES lib lib64 + DOC "The xrt_coreutil library" + ) + if(NOT XRT_INCLUDE_DIR OR NOT XRT_COREUTIL_LIBRARY) + message(FATAL_ERROR "${ColorBoldRed}The XRT SDK was not found. Install it and either set the XILINX_XRT environment variable to its root or pass -DXRT_ROOT=. On Windows, download xrt_windows_sdk.zip from the Xilinx/XRT releases and extract its xrt_sdk/xrt directory; on Linux, install the XRT packages (typically /opt/xilinx/xrt).${ColorReset}") + endif() + message(STATUS " XRT include dir: ${XRT_INCLUDE_DIR}") + message(STATUS " XRT library: ${XRT_COREUTIL_LIBRARY}") + target_include_directories(katago SYSTEM PRIVATE "${XRT_INCLUDE_DIR}") + target_link_libraries(katago "${XRT_COREUTIL_LIBRARY}") + + # XRT's headers select std::any vs boost::any on __cplusplus. MSVC reports + # 199711L there unless told otherwise, which sends xrt/detail/any.h looking for + # a Boost that we do not ship. Set per-target so the compiler defaults CMake + # supplies (notably /EHsc) are left intact. + target_compile_options(katago PRIVATE $<$:/Zc:__cplusplus>) + + # ---- NPU kernel binaries (xclbin) ---- + # Shipped as build artifacts next to the executable, in a "ryzenai" subdir. + # The backend resolves them relative to the executable at run time, so a + # deployed install is just exe + dlls + this directory. + set(RYZENAI_ARTIFACT_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/ryzenai_artifacts") + add_custom_command(TARGET katago POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "$/ryzenai" + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${RYZENAI_ARTIFACT_SRC_DIR}" "$/ryzenai" + COMMENT "Copying RyzenAI NPU kernel artifacts next to katago" + ) + + if(WIN32) + # The XRT runtime DLLs ship with the NPU driver rather than with the SDK, so + # they are picked up from the Windows driver store. Located by globbing on + # top of %SystemRoot%, so neither a path nor a driver version is hardcoded. + # Override with -DXRT_RUNTIME_DLL_DIR= if the driver lives elsewhere. + set(XRT_RUNTIME_DLL_DIR "" CACHE PATH "Directory containing xrt_coreutil.dll. Auto-detected from the NPU driver store if empty.") + if(NOT XRT_RUNTIME_DLL_DIR) + file(GLOB _katago_xrt_driver_dirs + "$ENV{SystemRoot}/System32/DriverStore/FileRepository/*/xrt_coreutil.dll") + if(_katago_xrt_driver_dirs) + # Several driver revisions can coexist in the store; take the newest. + list(SORT _katago_xrt_driver_dirs COMPARE FILE_BASENAME ORDER DESCENDING) + list(GET _katago_xrt_driver_dirs 0 _katago_xrt_dll) + get_filename_component(XRT_RUNTIME_DLL_DIR "${_katago_xrt_dll}" DIRECTORY) + endif() + endif() + if(XRT_RUNTIME_DLL_DIR) + message(STATUS " XRT runtime DLLs: ${XRT_RUNTIME_DLL_DIR}") + file(GLOB _katago_xrt_runtime_dlls "${XRT_RUNTIME_DLL_DIR}/xrt_*.dll") + foreach(_katago_xrt_dll IN LISTS _katago_xrt_runtime_dlls) + add_custom_command(TARGET katago POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${_katago_xrt_dll}" "$" + ) + endforeach() + else() + message(WARNING "${ColorBoldRed}Could not locate xrt_coreutil.dll in the driver store. katago will need it on PATH at run time, or pass -DXRT_RUNTIME_DLL_DIR=.${ColorReset}") + endif() + endif() elseif(USE_BACKEND STREQUAL "ONNX") target_compile_definitions(katago PRIVATE USE_ONNX_BACKEND) @@ -1743,6 +1966,48 @@ if(WIN32 AND ZLIB_LIBRARY) endif() endif() +# Last resort before giving up: a zlib from a toolchain that is already on the +# machine but does not advertise itself. conda ships one, so does vcpkg. This +# runs after the auto-fetch logic above, so it only fires when that was disabled +# or found nothing, and an explicit -DZLIB_ROOT= still wins over all of it. +if(CMAKE_HOST_WIN32 AND NOT ZLIB_ROOT AND NOT ZLIB_LIBRARY) + set(_katago_zlib_roots "") + if(DEFINED ENV{CONDA_PREFIX}) + file(TO_CMAKE_PATH "$ENV{CONDA_PREFIX}" _p) + list(APPEND _katago_zlib_roots "${_p}/Library") + endif() + if(DEFINED ENV{VCPKG_ROOT}) + file(TO_CMAKE_PATH "$ENV{VCPKG_ROOT}" _p) + list(APPEND _katago_zlib_roots "${_p}/installed/x64-windows") + endif() + if(DEFINED ENV{USERPROFILE}) + # A base conda install is not "activated", so it exports no CONDA_PREFIX; + # its default location under the user profile is the only thing to go on. + file(TO_CMAKE_PATH "$ENV{USERPROFILE}" _home) + foreach(_dist miniconda3 anaconda3 miniforge3 mambaforge) + list(APPEND _katago_zlib_roots "${_home}/${_dist}/Library") + endforeach() + endif() + foreach(_root IN LISTS _katago_zlib_roots) + if(EXISTS "${_root}/include/zlib.h") + # Prefer the import library for the DLL over the static one, to match how + # the rest of KataGo's dependencies are linked here. + foreach(_cand zdll.lib zlib.lib z.lib) + if(EXISTS "${_root}/lib/${_cand}") + set(ZLIB_ROOT "${_root}" CACHE PATH "Root of a zlib install" FORCE) + set(ZLIB_INCLUDE_DIR "${_root}/include" CACHE PATH "" FORCE) + set(ZLIB_LIBRARY "${_root}/lib/${_cand}" CACHE FILEPATH "" FORCE) + message(STATUS "KataGo: using zlib from ${_root}") + break() + endif() + endforeach() + endif() + if(ZLIB_ROOT) + break() + endif() + endforeach() +endif() + find_package(ZLIB) if(ZLIB_FOUND) include_directories(${ZLIB_INCLUDE_DIRS}) diff --git a/cpp/configs/gtp_example.cfg b/cpp/configs/gtp_example.cfg index 1b8982138..e96b362fb 100644 --- a/cpp/configs/gtp_example.cfg +++ b/cpp/configs/gtp_example.cfg @@ -665,6 +665,70 @@ searchFactorWhenWinningThreshold = 0.95 # Default: numSearchThreads # numEigenThreadsPerModel = X +# ------------------------------ +# RyzenAI (AMD NPU) settings +# ------------------------------ +# These only apply when using the RyzenAI version of KataGo (USE_BACKEND=RYZENAI). +# +# This backend talks to the NPU directly through XRT. You do NOT need to install +# the AMD Ryzen AI Software SDK, ONNX Runtime, or Python - at runtime only the +# NPU driver is required. + +# Directory containing the NPU kernel artifacts (*.xclbin). If unset, defaults +# to a "ryzenai" subdirectory next to the katago executable. +# ryzenaiArtifactDir = C:/path/to/ryzenai/artifacts + +# Numeric format requested for NPU kernels: auto, bf16, or bfp16. +# +# auto - bfp16 on XDNA2 (Strix and later), bf16 on XDNA1. This is the default. +# bfp16 - block floating point. Faster, and XDNA2 only. +# bf16 - more accurate, and the only format XDNA1 has. +# +# A single bfp16 matmul carries roughly 3% relative error against float32 where +# bf16 carries ~2e-5, but that is input quantisation and the accumulator is +# float32 either way, so it does not compound the way the per-matmul figure +# suggests: measured end to end over a whole evaluation, bfp16 lands within +# about 1.3-2x of bf16's deviation from the CPU reference, and the policy's top +# ten moves come out the same. Set bf16 explicitly if you would rather have the +# accuracy than the speed. +# ryzenaiDtype = auto + +# How many of the NPU's columns one kernel may use. More is not automatically +# better: each distinct kernel is its own hardware context, and a small net ends +# up losing more to context switching than it gains from the extra width. Large +# nets do benefit. Measure with `katago benchmark` before changing this. +# ryzenaiMaxColumns = 4 + +# Set to true to fail hard if no NPU kernel artifacts are found, instead of +# falling back to the CPU reference forward path. Useful for confirming that the +# NPU really is being used, since the fallback is silent and correct - just slow. +# ryzenaiForceNpuOnly = false + +# Set to true to log where each evaluation's time went (host-side packing, NPU +# dispatch, unpacking, and the operators still on the CPU), plus any kernel that +# was wanted but missing. Start here when performance is not what you expect. +# ryzenaiVerboseDispatch = false + +# Set to true to log every matrix shape this model asks for. Needed only when +# generating kernels for a network that has none yet - see Compiling.md. +# ryzenaiShapeReport = false + +# Collapse every layer onto one kernel by padding reduction dimensions up to this +# value, trading wasted arithmetic for fewer context switches. -1 lets KataGo +# decide per model, which is almost always right. +# ryzenaiForceK = -1 + +# Set to true to run a built-in matrix-multiply check against the NPU at startup. +# ryzenaiSelfTest = false + +# For one NPU: optionally uncomment and change this if the device to use is guessed incorrectly. +# ryzenaiDeviceToUse = 0 + +# For multiple threads/devices: uncomment these and replace X and Y with the device ids. +# (AND also set numNNServerThreadsPerModel above) +# ryzenaiDeviceToUseThread0 = X +# ryzenaiDeviceToUseThread1 = Y + # =========================================================================== # Root move selection and biases # =========================================================================== diff --git a/cpp/external/ryzenai_artifacts/README.md b/cpp/external/ryzenai_artifacts/README.md new file mode 100644 index 000000000..53473ceb7 --- /dev/null +++ b/cpp/external/ryzenai_artifacts/README.md @@ -0,0 +1,34 @@ +# RyzenAI NPU kernel artifacts + +Compiled AI Engine kernel binaries for the RyzenAI backend. Everything here is a +build product of the kernel sources in `../kernels/`, committed so that neither +end users nor people compiling KataGo need the AIE toolchain. + +CMake copies this whole directory next to `katago` as `ryzenai/` at build time, +and the backend resolves it relative to the running executable, so a deployed +install is just the executable, the XRT runtime DLLs, and this directory. + +## Layout + +``` +manifest.json ABI contract shared with cpp/neuralnet/ryzenai/manifest.h +bf16/*.xclbin bfloat16 kernels +``` + +## Status + +M2 first kernel landed: `bf16/gemm_bf16_M{M}K{K}N{N}.xclbin` + `.insts.bin` +for (M,K,N) in {(384,384,384), (384,512,512), (384,768,768)} — single-core +bf16×bf16→fp32 GEMM (64×64×64 tiles via mem tile), built by +`../kernels/build_kernels.py` from `../kernels/gemm_bf16.py`, verified on +hardware against numpy. These are per-shape AOT artifacts: M/K/N are baked +into each `.insts.bin`. The shape-independent form (runtime-generated +instruction stream per the "What an xclbin is parameterized by" section +below) is the M3 goal; `manifest.json` pins the ABI either way. + +## What an xclbin is parameterized by + +`(target device, core program, dataflow topology, compile-time tile sizes)` — +**not** by tensor shape. M/K/N, layer count and batch size all live in the +runtime instruction stream, so changing model, board size or batch size does +not require a different xclbin. diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1024.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1024.insts.bin new file mode 100644 index 000000000..71d072e58 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1024.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1024.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1024.xclbin new file mode 100644 index 000000000..71071aeea Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1024.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1088.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1088.insts.bin new file mode 100644 index 000000000..975f5e755 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1088.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1088.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1088.xclbin new file mode 100644 index 000000000..ac7b26c04 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1088.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1152.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1152.insts.bin new file mode 100644 index 000000000..607afdceb Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1152.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1152.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1152.xclbin new file mode 100644 index 000000000..9c7d8430f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1152.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1216.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1216.insts.bin new file mode 100644 index 000000000..058509492 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1216.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1216.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1216.xclbin new file mode 100644 index 000000000..96b4ef8f8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1216.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K128.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K128.insts.bin new file mode 100644 index 000000000..cb2d1c030 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K128.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K128.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K128.xclbin new file mode 100644 index 000000000..986462c3b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K128.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1280.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1280.insts.bin new file mode 100644 index 000000000..ee181535b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1280.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1280.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1280.xclbin new file mode 100644 index 000000000..9c18dd20f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1280.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1344.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1344.insts.bin new file mode 100644 index 000000000..b72f20c5f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1344.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1344.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1344.xclbin new file mode 100644 index 000000000..e5a836569 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1344.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1408.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1408.insts.bin new file mode 100644 index 000000000..a6a10b0d5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1408.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1408.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1408.xclbin new file mode 100644 index 000000000..852d75aa0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1408.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1472.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1472.insts.bin new file mode 100644 index 000000000..b1197ebc9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1472.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1472.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1472.xclbin new file mode 100644 index 000000000..5aa967853 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1472.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1536.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1536.insts.bin new file mode 100644 index 000000000..f840c13e2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1536.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1536.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1536.xclbin new file mode 100644 index 000000000..3bd132f76 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1536.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1728.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1728.insts.bin new file mode 100644 index 000000000..7ccdc3d77 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1728.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1728.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1728.xclbin new file mode 100644 index 000000000..e858e5674 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K1728.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K192.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K192.insts.bin new file mode 100644 index 000000000..80f71c7b5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K192.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K192.xclbin new file mode 100644 index 000000000..dd502c6b4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K2304.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K2304.insts.bin new file mode 100644 index 000000000..1868d70d8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K2304.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K2304.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K2304.xclbin new file mode 100644 index 000000000..d7da02d54 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K2304.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K256.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K256.insts.bin new file mode 100644 index 000000000..233493597 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K256.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K256.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K256.xclbin new file mode 100644 index 000000000..30ecaf4d8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K256.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K2880.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K2880.insts.bin new file mode 100644 index 000000000..543f08d18 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K2880.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K2880.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K2880.xclbin new file mode 100644 index 000000000..00adb8a7f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K2880.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K320.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K320.insts.bin new file mode 100644 index 000000000..d3da630d5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K320.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K320.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K320.xclbin new file mode 100644 index 000000000..0b0b9a6f7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K320.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K3456.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K3456.insts.bin new file mode 100644 index 000000000..25c6c244c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K3456.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K3456.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K3456.xclbin new file mode 100644 index 000000000..0e4a1ad97 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K3456.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K384.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K384.insts.bin new file mode 100644 index 000000000..271f6d3ac Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K384.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K384.xclbin new file mode 100644 index 000000000..b9f880ea3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K4032.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K4032.insts.bin new file mode 100644 index 000000000..954df43c1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K4032.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K4032.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K4032.xclbin new file mode 100644 index 000000000..a7de5fce1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K4032.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K448.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K448.insts.bin new file mode 100644 index 000000000..4cea74c18 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K448.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K448.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K448.xclbin new file mode 100644 index 000000000..0707f3e46 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K448.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K4608.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K4608.insts.bin new file mode 100644 index 000000000..d6e7641ee Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K4608.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K4608.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K4608.xclbin new file mode 100644 index 000000000..55a138db2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K4608.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K512.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K512.insts.bin new file mode 100644 index 000000000..db416b319 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K512.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K512.xclbin new file mode 100644 index 000000000..c58a4085a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K5184.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K5184.insts.bin new file mode 100644 index 000000000..23e8e4ed8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K5184.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K5184.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K5184.xclbin new file mode 100644 index 000000000..78c066dcb Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K5184.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K576.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K576.insts.bin new file mode 100644 index 000000000..28b503e98 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K576.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K576.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K576.xclbin new file mode 100644 index 000000000..2e39deb5e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K576.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K5760.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K5760.insts.bin new file mode 100644 index 000000000..951456cf7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K5760.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K5760.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K5760.xclbin new file mode 100644 index 000000000..ff1ab2393 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K5760.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K6336.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K6336.insts.bin new file mode 100644 index 000000000..e194995f2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K6336.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K6336.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K6336.xclbin new file mode 100644 index 000000000..e401d9ab6 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K6336.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K64.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K64.insts.bin new file mode 100644 index 000000000..7974b11df Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K64.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K64.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K64.xclbin new file mode 100644 index 000000000..dc9ced24a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K64.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K640.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K640.insts.bin new file mode 100644 index 000000000..be203bdd9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K640.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K640.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K640.xclbin new file mode 100644 index 000000000..490303911 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K640.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K6912.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K6912.insts.bin new file mode 100644 index 000000000..8f47a3626 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K6912.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K6912.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K6912.xclbin new file mode 100644 index 000000000..76954ac8d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K6912.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K704.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K704.insts.bin new file mode 100644 index 000000000..9de1533a3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K704.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K704.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K704.xclbin new file mode 100644 index 000000000..771265592 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K704.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K768.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K768.insts.bin new file mode 100644 index 000000000..ab0ad45d4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K768.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K768.xclbin new file mode 100644 index 000000000..5e449c44f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K832.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K832.insts.bin new file mode 100644 index 000000000..7f904f8cd Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K832.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K832.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K832.xclbin new file mode 100644 index 000000000..cbfa75f3f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K832.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K896.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K896.insts.bin new file mode 100644 index 000000000..027e3f99d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K896.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K896.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K896.xclbin new file mode 100644 index 000000000..e4682c6db Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K896.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K960.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K960.insts.bin new file mode 100644 index 000000000..a939cbed3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K960.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K960.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K960.xclbin new file mode 100644 index 000000000..de2f9ba90 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_1col/gemm_bf16_K960.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1024.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1024.insts.bin new file mode 100644 index 000000000..7dd5a285e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1024.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1024.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1024.xclbin new file mode 100644 index 000000000..549258322 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1024.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1088.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1088.insts.bin new file mode 100644 index 000000000..64919bdc4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1088.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1088.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1088.xclbin new file mode 100644 index 000000000..82482b6f3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1088.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1152.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1152.insts.bin new file mode 100644 index 000000000..2dfe888ee Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1152.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1152.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1152.xclbin new file mode 100644 index 000000000..023e3e46b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1152.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1216.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1216.insts.bin new file mode 100644 index 000000000..4ca1d83af Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1216.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1216.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1216.xclbin new file mode 100644 index 000000000..e65df9b33 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1216.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K128.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K128.insts.bin new file mode 100644 index 000000000..4e350c1cb Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K128.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K128.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K128.xclbin new file mode 100644 index 000000000..226a1e464 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K128.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1280.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1280.insts.bin new file mode 100644 index 000000000..b92cbd029 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1280.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1280.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1280.xclbin new file mode 100644 index 000000000..f3b19679f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1280.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1344.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1344.insts.bin new file mode 100644 index 000000000..4fdae56fe Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1344.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1344.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1344.xclbin new file mode 100644 index 000000000..9b32c8867 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1344.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1408.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1408.insts.bin new file mode 100644 index 000000000..e44e05f1a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1408.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1408.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1408.xclbin new file mode 100644 index 000000000..727c9bd05 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1408.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1472.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1472.insts.bin new file mode 100644 index 000000000..2ff8741e2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1472.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1472.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1472.xclbin new file mode 100644 index 000000000..90ee2ed42 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1472.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1536.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1536.insts.bin new file mode 100644 index 000000000..97676fc97 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1536.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1536.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1536.xclbin new file mode 100644 index 000000000..c8d202895 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1536.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1728.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1728.insts.bin new file mode 100644 index 000000000..edf03be9f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1728.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1728.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1728.xclbin new file mode 100644 index 000000000..77c4d6fe7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K1728.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K192.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K192.insts.bin new file mode 100644 index 000000000..a2b68ea5c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K192.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K192.xclbin new file mode 100644 index 000000000..b9cbf3dc1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K2304.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K2304.insts.bin new file mode 100644 index 000000000..0958e1037 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K2304.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K2304.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K2304.xclbin new file mode 100644 index 000000000..216b2bd41 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K2304.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K256.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K256.insts.bin new file mode 100644 index 000000000..2c07be337 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K256.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K256.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K256.xclbin new file mode 100644 index 000000000..b196fce9c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K256.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K2880.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K2880.insts.bin new file mode 100644 index 000000000..a1575e496 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K2880.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K2880.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K2880.xclbin new file mode 100644 index 000000000..6d34e13a3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K2880.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K320.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K320.insts.bin new file mode 100644 index 000000000..552346d0f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K320.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K320.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K320.xclbin new file mode 100644 index 000000000..a3260adde Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K320.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K3456.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K3456.insts.bin new file mode 100644 index 000000000..7db53b3ad Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K3456.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K3456.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K3456.xclbin new file mode 100644 index 000000000..ab51684e4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K3456.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K384.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K384.insts.bin new file mode 100644 index 000000000..b747772de Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K384.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K384.xclbin new file mode 100644 index 000000000..6066790af Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K4032.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K4032.insts.bin new file mode 100644 index 000000000..3f01c4bef Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K4032.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K4032.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K4032.xclbin new file mode 100644 index 000000000..eeb7f6daf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K4032.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K448.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K448.insts.bin new file mode 100644 index 000000000..5bbc2c803 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K448.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K448.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K448.xclbin new file mode 100644 index 000000000..d9a9e83af Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K448.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K4608.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K4608.insts.bin new file mode 100644 index 000000000..72fc6873f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K4608.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K4608.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K4608.xclbin new file mode 100644 index 000000000..82061ce92 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K4608.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K512.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K512.insts.bin new file mode 100644 index 000000000..dd5cf038e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K512.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K512.xclbin new file mode 100644 index 000000000..ae38647fc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K5184.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K5184.insts.bin new file mode 100644 index 000000000..bff8949ff Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K5184.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K5184.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K5184.xclbin new file mode 100644 index 000000000..b991d4c5f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K5184.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K576.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K576.insts.bin new file mode 100644 index 000000000..319a9e207 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K576.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K576.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K576.xclbin new file mode 100644 index 000000000..290227ceb Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K576.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K5760.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K5760.insts.bin new file mode 100644 index 000000000..ae66b1363 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K5760.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K5760.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K5760.xclbin new file mode 100644 index 000000000..09f77c538 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K5760.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K6336.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K6336.insts.bin new file mode 100644 index 000000000..2332d84cf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K6336.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K6336.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K6336.xclbin new file mode 100644 index 000000000..d2e2d527e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K6336.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K64.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K64.insts.bin new file mode 100644 index 000000000..7dda4f963 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K64.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K64.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K64.xclbin new file mode 100644 index 000000000..954934e57 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K64.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K640.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K640.insts.bin new file mode 100644 index 000000000..959d1568e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K640.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K640.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K640.xclbin new file mode 100644 index 000000000..6d5556d88 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K640.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K6912.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K6912.insts.bin new file mode 100644 index 000000000..02a4b9562 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K6912.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K6912.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K6912.xclbin new file mode 100644 index 000000000..51585b665 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K6912.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K704.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K704.insts.bin new file mode 100644 index 000000000..d623b6a4f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K704.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K704.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K704.xclbin new file mode 100644 index 000000000..c77c0202d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K704.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K768.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K768.insts.bin new file mode 100644 index 000000000..6068f4df2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K768.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K768.xclbin new file mode 100644 index 000000000..1226e1200 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K832.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K832.insts.bin new file mode 100644 index 000000000..e8ddb40e6 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K832.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K832.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K832.xclbin new file mode 100644 index 000000000..8dc04f930 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K832.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K896.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K896.insts.bin new file mode 100644 index 000000000..bd2d3d8e5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K896.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K896.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K896.xclbin new file mode 100644 index 000000000..96cf55e65 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K896.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K960.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K960.insts.bin new file mode 100644 index 000000000..f1a875a38 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K960.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K960.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K960.xclbin new file mode 100644 index 000000000..a973a6a6b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_2col/gemm_bf16_K960.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1024.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1024.insts.bin new file mode 100644 index 000000000..ae028dfd4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1024.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1024.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1024.xclbin new file mode 100644 index 000000000..fec15a4ca Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1024.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1088.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1088.insts.bin new file mode 100644 index 000000000..9ec8e5e75 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1088.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1088.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1088.xclbin new file mode 100644 index 000000000..0f6f303e0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1088.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1152.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1152.insts.bin new file mode 100644 index 000000000..83e2f2911 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1152.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1152.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1152.xclbin new file mode 100644 index 000000000..c118af420 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1152.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1216.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1216.insts.bin new file mode 100644 index 000000000..56bd566b7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1216.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1216.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1216.xclbin new file mode 100644 index 000000000..8af22be77 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1216.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K128.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K128.insts.bin new file mode 100644 index 000000000..6a4f107c4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K128.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K128.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K128.xclbin new file mode 100644 index 000000000..c480a8979 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K128.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1280.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1280.insts.bin new file mode 100644 index 000000000..124175f63 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1280.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1280.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1280.xclbin new file mode 100644 index 000000000..0b2d1ee73 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1280.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1344.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1344.insts.bin new file mode 100644 index 000000000..344244434 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1344.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1344.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1344.xclbin new file mode 100644 index 000000000..d4c844ce8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1344.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1408.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1408.insts.bin new file mode 100644 index 000000000..09dcc26cf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1408.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1408.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1408.xclbin new file mode 100644 index 000000000..59122cbb0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1408.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1472.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1472.insts.bin new file mode 100644 index 000000000..9de67a383 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1472.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1472.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1472.xclbin new file mode 100644 index 000000000..c4872da85 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1472.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1536.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1536.insts.bin new file mode 100644 index 000000000..29d01dc08 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1536.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1536.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1536.xclbin new file mode 100644 index 000000000..79bbe933f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1536.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1728.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1728.insts.bin new file mode 100644 index 000000000..32dcb0507 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1728.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1728.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1728.xclbin new file mode 100644 index 000000000..fde3b53c3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K1728.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K192.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K192.insts.bin new file mode 100644 index 000000000..6cf5e1370 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K192.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K192.xclbin new file mode 100644 index 000000000..d0152de2f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K2304.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K2304.insts.bin new file mode 100644 index 000000000..20ea25141 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K2304.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K2304.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K2304.xclbin new file mode 100644 index 000000000..5a9a5b9be Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K2304.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K256.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K256.insts.bin new file mode 100644 index 000000000..603eed122 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K256.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K256.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K256.xclbin new file mode 100644 index 000000000..694d9a860 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K256.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K2880.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K2880.insts.bin new file mode 100644 index 000000000..8c64fb14b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K2880.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K2880.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K2880.xclbin new file mode 100644 index 000000000..050862bfd Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K2880.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K320.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K320.insts.bin new file mode 100644 index 000000000..9171ffd94 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K320.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K320.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K320.xclbin new file mode 100644 index 000000000..0dc745826 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K320.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K3456.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K3456.insts.bin new file mode 100644 index 000000000..182565c16 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K3456.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K3456.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K3456.xclbin new file mode 100644 index 000000000..000ea1720 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K3456.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K384.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K384.insts.bin new file mode 100644 index 000000000..5df33ed48 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K384.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K384.xclbin new file mode 100644 index 000000000..0fac40f4a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K4032.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K4032.insts.bin new file mode 100644 index 000000000..83ce6fb05 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K4032.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K4032.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K4032.xclbin new file mode 100644 index 000000000..5c26d00cc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K4032.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K448.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K448.insts.bin new file mode 100644 index 000000000..9ba9c37ab Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K448.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K448.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K448.xclbin new file mode 100644 index 000000000..425364a3a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K448.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K4608.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K4608.insts.bin new file mode 100644 index 000000000..5f17c4a0e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K4608.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K4608.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K4608.xclbin new file mode 100644 index 000000000..ad1f715a5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K4608.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K512.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K512.insts.bin new file mode 100644 index 000000000..c2c6a3f69 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K512.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K512.xclbin new file mode 100644 index 000000000..69bc587a5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K5184.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K5184.insts.bin new file mode 100644 index 000000000..cb70f5a63 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K5184.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K5184.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K5184.xclbin new file mode 100644 index 000000000..3672e1bb6 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K5184.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K576.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K576.insts.bin new file mode 100644 index 000000000..edf667f4f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K576.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K576.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K576.xclbin new file mode 100644 index 000000000..1533f35c6 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K576.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K5760.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K5760.insts.bin new file mode 100644 index 000000000..127df17c6 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K5760.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K5760.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K5760.xclbin new file mode 100644 index 000000000..6ab1d1b63 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K5760.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K6336.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K6336.insts.bin new file mode 100644 index 000000000..e1ab5b16b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K6336.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K6336.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K6336.xclbin new file mode 100644 index 000000000..3a40d95b7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K6336.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K64.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K64.insts.bin new file mode 100644 index 000000000..293e1005e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K64.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K64.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K64.xclbin new file mode 100644 index 000000000..8b02fd6ed Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K64.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K640.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K640.insts.bin new file mode 100644 index 000000000..b0ace521d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K640.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K640.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K640.xclbin new file mode 100644 index 000000000..f2a834ab4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K640.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K6912.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K6912.insts.bin new file mode 100644 index 000000000..1e16f1958 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K6912.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K6912.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K6912.xclbin new file mode 100644 index 000000000..08746a939 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K6912.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K704.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K704.insts.bin new file mode 100644 index 000000000..eb96e8810 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K704.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K704.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K704.xclbin new file mode 100644 index 000000000..922e53637 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K704.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K768.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K768.insts.bin new file mode 100644 index 000000000..6360cc38b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K768.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K768.xclbin new file mode 100644 index 000000000..68664b042 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K832.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K832.insts.bin new file mode 100644 index 000000000..eda8c8c63 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K832.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K832.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K832.xclbin new file mode 100644 index 000000000..fc6f78f6b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K832.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K896.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K896.insts.bin new file mode 100644 index 000000000..f6cf51a68 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K896.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K896.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K896.xclbin new file mode 100644 index 000000000..d9d6329a1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K896.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K960.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K960.insts.bin new file mode 100644 index 000000000..c17fa8fa9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K960.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K960.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K960.xclbin new file mode 100644 index 000000000..3645a1000 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu1_4col/gemm_bf16_K960.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1024.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1024.insts.bin new file mode 100644 index 000000000..350653420 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1024.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1024.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1024.xclbin new file mode 100644 index 000000000..24eb75d36 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1024.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1088.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1088.insts.bin new file mode 100644 index 000000000..827007b80 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1088.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1088.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1088.xclbin new file mode 100644 index 000000000..9bfdb266a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1088.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1152.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1152.insts.bin new file mode 100644 index 000000000..611b1d73e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1152.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1152.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1152.xclbin new file mode 100644 index 000000000..ec051451a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1152.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1216.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1216.insts.bin new file mode 100644 index 000000000..3dd5cb105 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1216.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1216.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1216.xclbin new file mode 100644 index 000000000..663d0a143 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1216.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K128.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K128.insts.bin new file mode 100644 index 000000000..25b377b3a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K128.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K128.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K128.xclbin new file mode 100644 index 000000000..a8a7735ed Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K128.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1280.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1280.insts.bin new file mode 100644 index 000000000..9c0d93e21 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1280.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1280.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1280.xclbin new file mode 100644 index 000000000..6552795c4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1280.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1344.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1344.insts.bin new file mode 100644 index 000000000..6b76ab7e4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1344.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1344.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1344.xclbin new file mode 100644 index 000000000..e208f6802 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1344.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1408.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1408.insts.bin new file mode 100644 index 000000000..b22bf81fc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1408.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1408.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1408.xclbin new file mode 100644 index 000000000..a103edb14 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1408.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1472.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1472.insts.bin new file mode 100644 index 000000000..c653c311c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1472.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1472.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1472.xclbin new file mode 100644 index 000000000..54156a2d2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1472.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1536.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1536.insts.bin new file mode 100644 index 000000000..180f2aa73 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1536.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1536.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1536.xclbin new file mode 100644 index 000000000..9f8fade36 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1536.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1728.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1728.insts.bin new file mode 100644 index 000000000..280777836 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1728.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1728.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1728.xclbin new file mode 100644 index 000000000..1c11b4d71 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K1728.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K192.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K192.insts.bin new file mode 100644 index 000000000..54c9870b5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K192.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K192.xclbin new file mode 100644 index 000000000..d6fa926a5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K2304.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K2304.insts.bin new file mode 100644 index 000000000..f66f5e6cf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K2304.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K2304.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K2304.xclbin new file mode 100644 index 000000000..dfc1c189a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K2304.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K256.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K256.insts.bin new file mode 100644 index 000000000..f394da966 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K256.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K256.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K256.xclbin new file mode 100644 index 000000000..4985b4f28 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K256.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K2880.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K2880.insts.bin new file mode 100644 index 000000000..e73a6d81b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K2880.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K2880.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K2880.xclbin new file mode 100644 index 000000000..914a2072b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K2880.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K320.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K320.insts.bin new file mode 100644 index 000000000..892f903ba Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K320.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K320.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K320.xclbin new file mode 100644 index 000000000..48f7f87df Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K320.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K3456.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K3456.insts.bin new file mode 100644 index 000000000..8a9c13938 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K3456.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K3456.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K3456.xclbin new file mode 100644 index 000000000..c24d0bafc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K3456.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K384.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K384.insts.bin new file mode 100644 index 000000000..1110a1cf1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K384.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K384.xclbin new file mode 100644 index 000000000..3219c40eb Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K4032.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K4032.insts.bin new file mode 100644 index 000000000..8afab021e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K4032.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K4032.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K4032.xclbin new file mode 100644 index 000000000..ff604b84c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K4032.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K448.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K448.insts.bin new file mode 100644 index 000000000..facd35956 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K448.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K448.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K448.xclbin new file mode 100644 index 000000000..6e09e74bd Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K448.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K4608.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K4608.insts.bin new file mode 100644 index 000000000..a5070232a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K4608.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K4608.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K4608.xclbin new file mode 100644 index 000000000..dca21a2b9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K4608.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K512.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K512.insts.bin new file mode 100644 index 000000000..75eb7c84f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K512.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K512.xclbin new file mode 100644 index 000000000..9a2f2f49e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K5184.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K5184.insts.bin new file mode 100644 index 000000000..0aa903c7c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K5184.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K5184.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K5184.xclbin new file mode 100644 index 000000000..bb6565b31 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K5184.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K576.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K576.insts.bin new file mode 100644 index 000000000..bf6a90ca5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K576.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K576.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K576.xclbin new file mode 100644 index 000000000..40c99dfc9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K576.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K5760.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K5760.insts.bin new file mode 100644 index 000000000..e395cbcd7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K5760.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K5760.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K5760.xclbin new file mode 100644 index 000000000..ca9655d32 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K5760.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K6336.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K6336.insts.bin new file mode 100644 index 000000000..1b0f11f5c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K6336.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K6336.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K6336.xclbin new file mode 100644 index 000000000..35b0d8fd4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K6336.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K64.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K64.insts.bin new file mode 100644 index 000000000..0e81bc25d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K64.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K64.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K64.xclbin new file mode 100644 index 000000000..bf361d2e2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K64.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K640.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K640.insts.bin new file mode 100644 index 000000000..d37991e08 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K640.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K640.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K640.xclbin new file mode 100644 index 000000000..4d8ac966c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K640.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K6912.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K6912.insts.bin new file mode 100644 index 000000000..25ad11d32 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K6912.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K6912.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K6912.xclbin new file mode 100644 index 000000000..a443ee072 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K6912.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K704.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K704.insts.bin new file mode 100644 index 000000000..6ede7cbf1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K704.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K704.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K704.xclbin new file mode 100644 index 000000000..d5826cc3d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K704.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K768.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K768.insts.bin new file mode 100644 index 000000000..9e5a4b13e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K768.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K768.xclbin new file mode 100644 index 000000000..20e2a20fe Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K832.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K832.insts.bin new file mode 100644 index 000000000..665e9a7a6 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K832.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K832.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K832.xclbin new file mode 100644 index 000000000..41743c68d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K832.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K896.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K896.insts.bin new file mode 100644 index 000000000..2e24981a2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K896.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K896.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K896.xclbin new file mode 100644 index 000000000..9d5b2d6c7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K896.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K960.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K960.insts.bin new file mode 100644 index 000000000..21319011a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K960.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K960.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K960.xclbin new file mode 100644 index 000000000..a1e9eb3af Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col/gemm_bf16_K960.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K1152.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K1152.insts.bin new file mode 100644 index 000000000..611b1d73e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K1152.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K1152.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K1152.xclbin new file mode 100644 index 000000000..0d1eab8e7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K1152.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K512.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K512.insts.bin new file mode 100644 index 000000000..75eb7c84f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K512.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K512.xclbin new file mode 100644 index 000000000..b7876e8c2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K768.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K768.insts.bin new file mode 100644 index 000000000..9e5a4b13e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K768.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K768.xclbin new file mode 100644 index 000000000..1db412111 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_1col_swiglu/gemm_swiglu_bf16_K768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1024.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1024.insts.bin new file mode 100644 index 000000000..1c8ebd22a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1024.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1024.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1024.xclbin new file mode 100644 index 000000000..af7f075a6 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1024.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1088.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1088.insts.bin new file mode 100644 index 000000000..09582183f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1088.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1088.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1088.xclbin new file mode 100644 index 000000000..42d88c801 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1088.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1152.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1152.insts.bin new file mode 100644 index 000000000..e1df7f0b9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1152.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1152.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1152.xclbin new file mode 100644 index 000000000..a28852ab1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1152.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1216.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1216.insts.bin new file mode 100644 index 000000000..d037496e7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1216.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1216.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1216.xclbin new file mode 100644 index 000000000..c9c5c72a8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1216.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K128.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K128.insts.bin new file mode 100644 index 000000000..d61a8e023 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K128.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K128.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K128.xclbin new file mode 100644 index 000000000..8109762b9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K128.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1280.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1280.insts.bin new file mode 100644 index 000000000..d7fa3ef71 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1280.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1280.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1280.xclbin new file mode 100644 index 000000000..1958736f5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1280.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1344.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1344.insts.bin new file mode 100644 index 000000000..1310f06cf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1344.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1344.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1344.xclbin new file mode 100644 index 000000000..4a38901a0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1344.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1408.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1408.insts.bin new file mode 100644 index 000000000..ae9ba043f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1408.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1408.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1408.xclbin new file mode 100644 index 000000000..c29b7c4ab Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1408.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1472.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1472.insts.bin new file mode 100644 index 000000000..5349aeb58 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1472.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1472.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1472.xclbin new file mode 100644 index 000000000..debfab175 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1472.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1536.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1536.insts.bin new file mode 100644 index 000000000..cefaa62dd Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1536.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1536.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1536.xclbin new file mode 100644 index 000000000..3c1bd980a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1536.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1728.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1728.insts.bin new file mode 100644 index 000000000..670051ecc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1728.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1728.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1728.xclbin new file mode 100644 index 000000000..9f4594aa6 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K1728.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K192.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K192.insts.bin new file mode 100644 index 000000000..6ef2decc8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K192.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K192.xclbin new file mode 100644 index 000000000..d581f483f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K2304.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K2304.insts.bin new file mode 100644 index 000000000..aec8a5cf0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K2304.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K2304.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K2304.xclbin new file mode 100644 index 000000000..837c597db Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K2304.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K256.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K256.insts.bin new file mode 100644 index 000000000..2ff3ce579 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K256.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K256.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K256.xclbin new file mode 100644 index 000000000..bdd4038c9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K256.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K2880.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K2880.insts.bin new file mode 100644 index 000000000..60293f635 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K2880.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K2880.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K2880.xclbin new file mode 100644 index 000000000..2e1c8d354 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K2880.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K320.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K320.insts.bin new file mode 100644 index 000000000..02f0cd023 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K320.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K320.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K320.xclbin new file mode 100644 index 000000000..b1b05e7fb Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K320.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K3456.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K3456.insts.bin new file mode 100644 index 000000000..94652c549 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K3456.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K3456.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K3456.xclbin new file mode 100644 index 000000000..b55055b9b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K3456.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K384.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K384.insts.bin new file mode 100644 index 000000000..c87b1ef7b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K384.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K384.xclbin new file mode 100644 index 000000000..2acb64a73 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K4032.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K4032.insts.bin new file mode 100644 index 000000000..aaecb8e0d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K4032.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K4032.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K4032.xclbin new file mode 100644 index 000000000..2c4056204 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K4032.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K448.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K448.insts.bin new file mode 100644 index 000000000..e2976167f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K448.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K448.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K448.xclbin new file mode 100644 index 000000000..83732f503 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K448.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K4608.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K4608.insts.bin new file mode 100644 index 000000000..26b0965ae Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K4608.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K4608.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K4608.xclbin new file mode 100644 index 000000000..2eeeb4721 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K4608.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K512.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K512.insts.bin new file mode 100644 index 000000000..919b80042 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K512.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K512.xclbin new file mode 100644 index 000000000..08e2106b2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K5184.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K5184.insts.bin new file mode 100644 index 000000000..dc6113afc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K5184.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K5184.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K5184.xclbin new file mode 100644 index 000000000..5aec5f41a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K5184.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K576.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K576.insts.bin new file mode 100644 index 000000000..787e7ea19 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K576.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K576.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K576.xclbin new file mode 100644 index 000000000..6574b285e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K576.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K5760.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K5760.insts.bin new file mode 100644 index 000000000..3a68c9056 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K5760.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K5760.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K5760.xclbin new file mode 100644 index 000000000..e23b02d84 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K5760.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K6336.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K6336.insts.bin new file mode 100644 index 000000000..7e2edcb9b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K6336.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K6336.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K6336.xclbin new file mode 100644 index 000000000..948bd307e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K6336.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K64.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K64.insts.bin new file mode 100644 index 000000000..217f3e399 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K64.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K64.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K64.xclbin new file mode 100644 index 000000000..844bb43b4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K64.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K640.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K640.insts.bin new file mode 100644 index 000000000..099cb6f93 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K640.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K640.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K640.xclbin new file mode 100644 index 000000000..1b379ffe8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K640.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K6912.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K6912.insts.bin new file mode 100644 index 000000000..fed5bed84 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K6912.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K6912.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K6912.xclbin new file mode 100644 index 000000000..39bf82cb1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K6912.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K704.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K704.insts.bin new file mode 100644 index 000000000..c430f70cd Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K704.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K704.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K704.xclbin new file mode 100644 index 000000000..2c3d9b4f2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K704.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K768.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K768.insts.bin new file mode 100644 index 000000000..b8917db47 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K768.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K768.xclbin new file mode 100644 index 000000000..de9f0bf9b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K832.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K832.insts.bin new file mode 100644 index 000000000..85ba2471a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K832.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K832.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K832.xclbin new file mode 100644 index 000000000..9f844f884 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K832.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K896.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K896.insts.bin new file mode 100644 index 000000000..1e3c76cf3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K896.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K896.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K896.xclbin new file mode 100644 index 000000000..51c228e7f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K896.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K960.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K960.insts.bin new file mode 100644 index 000000000..05dce0e33 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K960.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K960.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K960.xclbin new file mode 100644 index 000000000..29acfb28e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col/gemm_bf16_K960.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K1152.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K1152.insts.bin new file mode 100644 index 000000000..e1df7f0b9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K1152.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K1152.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K1152.xclbin new file mode 100644 index 000000000..bc962b619 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K1152.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K512.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K512.insts.bin new file mode 100644 index 000000000..919b80042 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K512.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K512.xclbin new file mode 100644 index 000000000..07da3b5ee Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K768.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K768.insts.bin new file mode 100644 index 000000000..b8917db47 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K768.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K768.xclbin new file mode 100644 index 000000000..a98cf9066 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_2col_swiglu/gemm_swiglu_bf16_K768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1024.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1024.insts.bin new file mode 100644 index 000000000..5cbfe311b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1024.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1024.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1024.xclbin new file mode 100644 index 000000000..a79d41ba9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1024.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1088.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1088.insts.bin new file mode 100644 index 000000000..41743a80d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1088.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1088.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1088.xclbin new file mode 100644 index 000000000..3956ee5f1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1088.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1152.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1152.insts.bin new file mode 100644 index 000000000..33045e378 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1152.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1152.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1152.xclbin new file mode 100644 index 000000000..a1c5c4689 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1152.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1216.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1216.insts.bin new file mode 100644 index 000000000..0614a3f88 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1216.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1216.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1216.xclbin new file mode 100644 index 000000000..b2f7580cd Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1216.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K128.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K128.insts.bin new file mode 100644 index 000000000..5fa273b74 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K128.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K128.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K128.xclbin new file mode 100644 index 000000000..4c86d6747 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K128.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1280.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1280.insts.bin new file mode 100644 index 000000000..8242a1319 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1280.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1280.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1280.xclbin new file mode 100644 index 000000000..c2f27f319 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1280.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1344.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1344.insts.bin new file mode 100644 index 000000000..ba0f2578a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1344.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1344.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1344.xclbin new file mode 100644 index 000000000..d6426d6bc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1344.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1408.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1408.insts.bin new file mode 100644 index 000000000..976a5d663 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1408.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1408.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1408.xclbin new file mode 100644 index 000000000..41771c2cf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1408.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1472.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1472.insts.bin new file mode 100644 index 000000000..ee438bb65 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1472.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1472.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1472.xclbin new file mode 100644 index 000000000..01bc1bf90 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1472.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1536.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1536.insts.bin new file mode 100644 index 000000000..b0d62fdc5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1536.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1536.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1536.xclbin new file mode 100644 index 000000000..8bacafbcb Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1536.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1728.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1728.insts.bin new file mode 100644 index 000000000..dd34d9bf4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1728.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1728.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1728.xclbin new file mode 100644 index 000000000..d6e80a0c9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K1728.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K192.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K192.insts.bin new file mode 100644 index 000000000..736fe8c84 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K192.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K192.xclbin new file mode 100644 index 000000000..933df1c3b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K2304.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K2304.insts.bin new file mode 100644 index 000000000..8f6965981 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K2304.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K2304.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K2304.xclbin new file mode 100644 index 000000000..3996c5b8b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K2304.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K256.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K256.insts.bin new file mode 100644 index 000000000..cafec2c34 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K256.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K256.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K256.xclbin new file mode 100644 index 000000000..86e5b6bea Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K256.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K2880.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K2880.insts.bin new file mode 100644 index 000000000..dead816e0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K2880.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K2880.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K2880.xclbin new file mode 100644 index 000000000..6e9155e81 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K2880.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K320.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K320.insts.bin new file mode 100644 index 000000000..a50f9880f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K320.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K320.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K320.xclbin new file mode 100644 index 000000000..ba74776fc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K320.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K3456.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K3456.insts.bin new file mode 100644 index 000000000..860cf18c5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K3456.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K3456.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K3456.xclbin new file mode 100644 index 000000000..a65983c62 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K3456.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K384.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K384.insts.bin new file mode 100644 index 000000000..fa403ad1a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K384.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K384.xclbin new file mode 100644 index 000000000..b642dd7f3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K4032.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K4032.insts.bin new file mode 100644 index 000000000..b55077e01 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K4032.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K4032.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K4032.xclbin new file mode 100644 index 000000000..3c7caf322 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K4032.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K448.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K448.insts.bin new file mode 100644 index 000000000..e11d8b40e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K448.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K448.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K448.xclbin new file mode 100644 index 000000000..f3f176886 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K448.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K4608.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K4608.insts.bin new file mode 100644 index 000000000..aee8534a9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K4608.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K4608.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K4608.xclbin new file mode 100644 index 000000000..909228840 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K4608.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K512.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K512.insts.bin new file mode 100644 index 000000000..d6995a53c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K512.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K512.xclbin new file mode 100644 index 000000000..63d9f0073 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K5184.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K5184.insts.bin new file mode 100644 index 000000000..55a0999d5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K5184.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K5184.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K5184.xclbin new file mode 100644 index 000000000..3d1b747d7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K5184.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K576.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K576.insts.bin new file mode 100644 index 000000000..58832296b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K576.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K576.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K576.xclbin new file mode 100644 index 000000000..1e06296cc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K576.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K5760.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K5760.insts.bin new file mode 100644 index 000000000..1f0b1713e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K5760.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K5760.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K5760.xclbin new file mode 100644 index 000000000..457f226aa Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K5760.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K6336.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K6336.insts.bin new file mode 100644 index 000000000..d52329b17 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K6336.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K6336.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K6336.xclbin new file mode 100644 index 000000000..5bdb7008b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K6336.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K64.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K64.insts.bin new file mode 100644 index 000000000..9cb6c916e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K64.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K64.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K64.xclbin new file mode 100644 index 000000000..657218707 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K64.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K640.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K640.insts.bin new file mode 100644 index 000000000..8ebccc887 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K640.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K640.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K640.xclbin new file mode 100644 index 000000000..9a5664dac Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K640.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K6912.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K6912.insts.bin new file mode 100644 index 000000000..8bf0e5df3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K6912.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K6912.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K6912.xclbin new file mode 100644 index 000000000..d8af62ce3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K6912.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K704.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K704.insts.bin new file mode 100644 index 000000000..5376402b8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K704.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K704.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K704.xclbin new file mode 100644 index 000000000..1c0a354e0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K704.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K768.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K768.insts.bin new file mode 100644 index 000000000..9921028c0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K768.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K768.xclbin new file mode 100644 index 000000000..b89283a61 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K832.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K832.insts.bin new file mode 100644 index 000000000..f873753c0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K832.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K832.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K832.xclbin new file mode 100644 index 000000000..921576992 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K832.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K896.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K896.insts.bin new file mode 100644 index 000000000..45d5ddd89 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K896.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K896.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K896.xclbin new file mode 100644 index 000000000..297bd44a0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K896.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K960.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K960.insts.bin new file mode 100644 index 000000000..07303920c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K960.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K960.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K960.xclbin new file mode 100644 index 000000000..b4fe52400 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col/gemm_bf16_K960.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K1152.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K1152.insts.bin new file mode 100644 index 000000000..33045e378 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K1152.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K1152.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K1152.xclbin new file mode 100644 index 000000000..089ec7bff Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K1152.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K512.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K512.insts.bin new file mode 100644 index 000000000..d6995a53c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K512.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K512.xclbin new file mode 100644 index 000000000..c7c85eaa5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K768.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K768.insts.bin new file mode 100644 index 000000000..9921028c0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K768.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K768.xclbin new file mode 100644 index 000000000..e945efee8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_4col_swiglu/gemm_swiglu_bf16_K768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1024.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1024.insts.bin new file mode 100644 index 000000000..b53ab1817 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1024.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1024.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1024.xclbin new file mode 100644 index 000000000..2d5bcdac4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1024.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1088.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1088.insts.bin new file mode 100644 index 000000000..da0edb6a8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1088.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1088.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1088.xclbin new file mode 100644 index 000000000..a84ff261f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1088.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1152.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1152.insts.bin new file mode 100644 index 000000000..096bf56a1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1152.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1152.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1152.xclbin new file mode 100644 index 000000000..fc91029da Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1152.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1216.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1216.insts.bin new file mode 100644 index 000000000..65ee30f41 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1216.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1216.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1216.xclbin new file mode 100644 index 000000000..a55636bd0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1216.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K128.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K128.insts.bin new file mode 100644 index 000000000..a2f77098d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K128.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K128.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K128.xclbin new file mode 100644 index 000000000..9562788b0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K128.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1280.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1280.insts.bin new file mode 100644 index 000000000..9be50fc01 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1280.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1280.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1280.xclbin new file mode 100644 index 000000000..bce2e1ac2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1280.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1344.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1344.insts.bin new file mode 100644 index 000000000..05d4e0835 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1344.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1344.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1344.xclbin new file mode 100644 index 000000000..6f266698a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1344.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1408.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1408.insts.bin new file mode 100644 index 000000000..aed546861 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1408.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1408.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1408.xclbin new file mode 100644 index 000000000..3fd8e30d3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1408.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1472.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1472.insts.bin new file mode 100644 index 000000000..f8f9236b5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1472.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1472.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1472.xclbin new file mode 100644 index 000000000..39dc4093f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1472.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1536.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1536.insts.bin new file mode 100644 index 000000000..0636bfa39 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1536.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1536.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1536.xclbin new file mode 100644 index 000000000..49c01c4a2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1536.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1728.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1728.insts.bin new file mode 100644 index 000000000..cad7daadf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1728.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1728.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1728.xclbin new file mode 100644 index 000000000..6a2f3fd40 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K1728.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K192.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K192.insts.bin new file mode 100644 index 000000000..528819524 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K192.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K192.xclbin new file mode 100644 index 000000000..89fda5b80 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K2304.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K2304.insts.bin new file mode 100644 index 000000000..eed41f925 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K2304.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K2304.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K2304.xclbin new file mode 100644 index 000000000..29ac688c7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K2304.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K256.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K256.insts.bin new file mode 100644 index 000000000..f034f1538 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K256.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K256.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K256.xclbin new file mode 100644 index 000000000..e0f485730 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K256.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K2880.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K2880.insts.bin new file mode 100644 index 000000000..717bbcd8a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K2880.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K2880.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K2880.xclbin new file mode 100644 index 000000000..184506fcc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K2880.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K320.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K320.insts.bin new file mode 100644 index 000000000..cc6bec853 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K320.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K320.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K320.xclbin new file mode 100644 index 000000000..2dc5c5d20 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K320.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K3456.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K3456.insts.bin new file mode 100644 index 000000000..698019297 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K3456.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K3456.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K3456.xclbin new file mode 100644 index 000000000..ddd739e50 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K3456.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K384.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K384.insts.bin new file mode 100644 index 000000000..ffeb6e2ec Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K384.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K384.xclbin new file mode 100644 index 000000000..a57cf7253 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K4032.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K4032.insts.bin new file mode 100644 index 000000000..9fcd1454b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K4032.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K4032.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K4032.xclbin new file mode 100644 index 000000000..da09b255a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K4032.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K448.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K448.insts.bin new file mode 100644 index 000000000..9e16732f5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K448.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K448.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K448.xclbin new file mode 100644 index 000000000..4b10c2258 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K448.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K4608.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K4608.insts.bin new file mode 100644 index 000000000..1078908ae Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K4608.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K4608.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K4608.xclbin new file mode 100644 index 000000000..5359b3288 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K4608.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K512.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K512.insts.bin new file mode 100644 index 000000000..0c0ba6388 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K512.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K512.xclbin new file mode 100644 index 000000000..3dcaf1208 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K5184.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K5184.insts.bin new file mode 100644 index 000000000..7811a3a55 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K5184.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K5184.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K5184.xclbin new file mode 100644 index 000000000..82b12fa6c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K5184.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K576.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K576.insts.bin new file mode 100644 index 000000000..44b553df4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K576.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K576.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K576.xclbin new file mode 100644 index 000000000..f8d38b062 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K576.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K5760.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K5760.insts.bin new file mode 100644 index 000000000..3fec8bb87 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K5760.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K5760.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K5760.xclbin new file mode 100644 index 000000000..219f5f7f7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K5760.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K6336.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K6336.insts.bin new file mode 100644 index 000000000..208ddbd43 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K6336.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K6336.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K6336.xclbin new file mode 100644 index 000000000..d3ec154d6 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K6336.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K64.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K64.insts.bin new file mode 100644 index 000000000..1d146405f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K64.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K64.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K64.xclbin new file mode 100644 index 000000000..821fdf536 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K64.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K640.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K640.insts.bin new file mode 100644 index 000000000..7e5083706 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K640.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K640.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K640.xclbin new file mode 100644 index 000000000..34770edfd Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K640.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K6912.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K6912.insts.bin new file mode 100644 index 000000000..59b7466b3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K6912.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K6912.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K6912.xclbin new file mode 100644 index 000000000..b660c986d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K6912.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K704.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K704.insts.bin new file mode 100644 index 000000000..4f678d507 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K704.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K704.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K704.xclbin new file mode 100644 index 000000000..cf725f97c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K704.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K768.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K768.insts.bin new file mode 100644 index 000000000..36ea56081 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K768.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K768.xclbin new file mode 100644 index 000000000..0b4461285 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K832.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K832.insts.bin new file mode 100644 index 000000000..35e4d746c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K832.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K832.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K832.xclbin new file mode 100644 index 000000000..aeacf8cbe Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K832.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K896.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K896.insts.bin new file mode 100644 index 000000000..c29e6b961 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K896.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K896.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K896.xclbin new file mode 100644 index 000000000..54e4bb9a3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K896.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K960.insts.bin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K960.insts.bin new file mode 100644 index 000000000..7f9deb905 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K960.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K960.xclbin b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K960.xclbin new file mode 100644 index 000000000..dcf774dd6 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bf16/npu2_8col/gemm_bf16_K960.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1024.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1024.insts.bin new file mode 100644 index 000000000..350653420 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1024.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1024.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1024.xclbin new file mode 100644 index 000000000..66d6aa1b0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1024.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1088.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1088.insts.bin new file mode 100644 index 000000000..827007b80 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1088.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1088.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1088.xclbin new file mode 100644 index 000000000..be6276a30 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1088.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1152.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1152.insts.bin new file mode 100644 index 000000000..611b1d73e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1152.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1152.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1152.xclbin new file mode 100644 index 000000000..739f58143 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1152.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1216.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1216.insts.bin new file mode 100644 index 000000000..3dd5cb105 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1216.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1216.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1216.xclbin new file mode 100644 index 000000000..106d53b17 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1216.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K128.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K128.insts.bin new file mode 100644 index 000000000..25b377b3a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K128.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K128.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K128.xclbin new file mode 100644 index 000000000..fe60b5397 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K128.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1280.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1280.insts.bin new file mode 100644 index 000000000..9c0d93e21 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1280.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1280.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1280.xclbin new file mode 100644 index 000000000..43c481647 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1280.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1344.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1344.insts.bin new file mode 100644 index 000000000..6b76ab7e4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1344.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1344.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1344.xclbin new file mode 100644 index 000000000..b9922f2c8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1344.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1408.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1408.insts.bin new file mode 100644 index 000000000..b22bf81fc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1408.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1408.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1408.xclbin new file mode 100644 index 000000000..ba9ebc084 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1408.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1472.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1472.insts.bin new file mode 100644 index 000000000..c653c311c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1472.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1472.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1472.xclbin new file mode 100644 index 000000000..844037fdd Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1472.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1536.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1536.insts.bin new file mode 100644 index 000000000..180f2aa73 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1536.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1536.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1536.xclbin new file mode 100644 index 000000000..991af3b7e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1536.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1728.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1728.insts.bin new file mode 100644 index 000000000..280777836 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1728.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1728.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1728.xclbin new file mode 100644 index 000000000..738db4c60 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K1728.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K192.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K192.insts.bin new file mode 100644 index 000000000..54c9870b5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K192.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K192.xclbin new file mode 100644 index 000000000..2e0cf5091 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K2304.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K2304.insts.bin new file mode 100644 index 000000000..f66f5e6cf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K2304.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K2304.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K2304.xclbin new file mode 100644 index 000000000..c502e8d6a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K2304.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K256.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K256.insts.bin new file mode 100644 index 000000000..f394da966 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K256.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K256.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K256.xclbin new file mode 100644 index 000000000..b25337265 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K256.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K2880.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K2880.insts.bin new file mode 100644 index 000000000..e73a6d81b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K2880.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K2880.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K2880.xclbin new file mode 100644 index 000000000..100dbd7c4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K2880.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K320.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K320.insts.bin new file mode 100644 index 000000000..892f903ba Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K320.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K320.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K320.xclbin new file mode 100644 index 000000000..f50aab83e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K320.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K3456.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K3456.insts.bin new file mode 100644 index 000000000..8a9c13938 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K3456.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K3456.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K3456.xclbin new file mode 100644 index 000000000..7764fe05f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K3456.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K384.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K384.insts.bin new file mode 100644 index 000000000..1110a1cf1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K384.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K384.xclbin new file mode 100644 index 000000000..d19ecc422 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K4032.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K4032.insts.bin new file mode 100644 index 000000000..8afab021e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K4032.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K4032.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K4032.xclbin new file mode 100644 index 000000000..eb9a895f3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K4032.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K448.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K448.insts.bin new file mode 100644 index 000000000..facd35956 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K448.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K448.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K448.xclbin new file mode 100644 index 000000000..112e9b66e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K448.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K4608.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K4608.insts.bin new file mode 100644 index 000000000..a5070232a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K4608.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K4608.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K4608.xclbin new file mode 100644 index 000000000..222379dbe Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K4608.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K512.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K512.insts.bin new file mode 100644 index 000000000..75eb7c84f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K512.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K512.xclbin new file mode 100644 index 000000000..6b5a57e3d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K5184.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K5184.insts.bin new file mode 100644 index 000000000..0aa903c7c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K5184.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K5184.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K5184.xclbin new file mode 100644 index 000000000..3d6ae8df9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K5184.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K576.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K576.insts.bin new file mode 100644 index 000000000..bf6a90ca5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K576.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K576.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K576.xclbin new file mode 100644 index 000000000..1bad4bba1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K576.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K5760.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K5760.insts.bin new file mode 100644 index 000000000..e395cbcd7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K5760.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K5760.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K5760.xclbin new file mode 100644 index 000000000..8f75bd527 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K5760.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K6336.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K6336.insts.bin new file mode 100644 index 000000000..1b0f11f5c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K6336.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K6336.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K6336.xclbin new file mode 100644 index 000000000..b02726175 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K6336.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K64.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K64.insts.bin new file mode 100644 index 000000000..0e81bc25d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K64.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K64.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K64.xclbin new file mode 100644 index 000000000..0a5c8300e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K64.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K640.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K640.insts.bin new file mode 100644 index 000000000..d37991e08 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K640.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K640.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K640.xclbin new file mode 100644 index 000000000..60c4f93c6 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K640.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K6912.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K6912.insts.bin new file mode 100644 index 000000000..25ad11d32 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K6912.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K6912.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K6912.xclbin new file mode 100644 index 000000000..6d3be9867 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K6912.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K704.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K704.insts.bin new file mode 100644 index 000000000..6ede7cbf1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K704.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K704.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K704.xclbin new file mode 100644 index 000000000..9b1b077d5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K704.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K768.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K768.insts.bin new file mode 100644 index 000000000..9e5a4b13e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K768.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K768.xclbin new file mode 100644 index 000000000..2320b275a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K832.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K832.insts.bin new file mode 100644 index 000000000..665e9a7a6 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K832.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K832.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K832.xclbin new file mode 100644 index 000000000..7fde63275 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K832.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K896.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K896.insts.bin new file mode 100644 index 000000000..2e24981a2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K896.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K896.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K896.xclbin new file mode 100644 index 000000000..72c59610a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K896.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K960.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K960.insts.bin new file mode 100644 index 000000000..21319011a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K960.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K960.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K960.xclbin new file mode 100644 index 000000000..d49886968 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_1col/gemm_bf16_K960.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1024.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1024.insts.bin new file mode 100644 index 000000000..1c8ebd22a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1024.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1024.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1024.xclbin new file mode 100644 index 000000000..174f9af97 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1024.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1088.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1088.insts.bin new file mode 100644 index 000000000..09582183f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1088.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1088.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1088.xclbin new file mode 100644 index 000000000..1d2fcbfb9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1088.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1152.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1152.insts.bin new file mode 100644 index 000000000..e1df7f0b9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1152.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1152.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1152.xclbin new file mode 100644 index 000000000..b49bf1380 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1152.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1216.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1216.insts.bin new file mode 100644 index 000000000..d037496e7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1216.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1216.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1216.xclbin new file mode 100644 index 000000000..7c0281c3c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1216.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K128.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K128.insts.bin new file mode 100644 index 000000000..d61a8e023 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K128.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K128.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K128.xclbin new file mode 100644 index 000000000..e6bd84a0c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K128.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1280.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1280.insts.bin new file mode 100644 index 000000000..d7fa3ef71 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1280.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1280.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1280.xclbin new file mode 100644 index 000000000..4d1745f5a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1280.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1344.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1344.insts.bin new file mode 100644 index 000000000..1310f06cf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1344.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1344.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1344.xclbin new file mode 100644 index 000000000..58aa65a49 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1344.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1408.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1408.insts.bin new file mode 100644 index 000000000..ae9ba043f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1408.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1408.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1408.xclbin new file mode 100644 index 000000000..db612767c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1408.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1472.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1472.insts.bin new file mode 100644 index 000000000..5349aeb58 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1472.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1472.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1472.xclbin new file mode 100644 index 000000000..43ca43de4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1472.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1536.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1536.insts.bin new file mode 100644 index 000000000..cefaa62dd Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1536.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1536.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1536.xclbin new file mode 100644 index 000000000..fe44f9b17 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1536.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1728.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1728.insts.bin new file mode 100644 index 000000000..670051ecc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1728.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1728.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1728.xclbin new file mode 100644 index 000000000..3fd0296a6 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K1728.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K192.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K192.insts.bin new file mode 100644 index 000000000..6ef2decc8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K192.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K192.xclbin new file mode 100644 index 000000000..25735f678 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K2304.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K2304.insts.bin new file mode 100644 index 000000000..aec8a5cf0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K2304.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K2304.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K2304.xclbin new file mode 100644 index 000000000..6a9185aab Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K2304.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K256.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K256.insts.bin new file mode 100644 index 000000000..2ff3ce579 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K256.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K256.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K256.xclbin new file mode 100644 index 000000000..bd445a772 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K256.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K2880.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K2880.insts.bin new file mode 100644 index 000000000..60293f635 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K2880.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K2880.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K2880.xclbin new file mode 100644 index 000000000..379f8147d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K2880.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K320.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K320.insts.bin new file mode 100644 index 000000000..02f0cd023 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K320.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K320.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K320.xclbin new file mode 100644 index 000000000..d21293b25 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K320.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K3456.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K3456.insts.bin new file mode 100644 index 000000000..94652c549 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K3456.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K3456.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K3456.xclbin new file mode 100644 index 000000000..ad2c5dd4e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K3456.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K384.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K384.insts.bin new file mode 100644 index 000000000..c87b1ef7b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K384.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K384.xclbin new file mode 100644 index 000000000..8b08cba86 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K4032.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K4032.insts.bin new file mode 100644 index 000000000..aaecb8e0d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K4032.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K4032.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K4032.xclbin new file mode 100644 index 000000000..642533c88 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K4032.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K448.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K448.insts.bin new file mode 100644 index 000000000..e2976167f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K448.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K448.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K448.xclbin new file mode 100644 index 000000000..759d780f0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K448.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K4608.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K4608.insts.bin new file mode 100644 index 000000000..26b0965ae Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K4608.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K4608.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K4608.xclbin new file mode 100644 index 000000000..fe28b3688 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K4608.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K512.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K512.insts.bin new file mode 100644 index 000000000..919b80042 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K512.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K512.xclbin new file mode 100644 index 000000000..a9f19d972 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K5184.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K5184.insts.bin new file mode 100644 index 000000000..dc6113afc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K5184.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K5184.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K5184.xclbin new file mode 100644 index 000000000..7e59f5cee Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K5184.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K576.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K576.insts.bin new file mode 100644 index 000000000..787e7ea19 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K576.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K576.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K576.xclbin new file mode 100644 index 000000000..6cc983455 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K576.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K5760.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K5760.insts.bin new file mode 100644 index 000000000..3a68c9056 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K5760.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K5760.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K5760.xclbin new file mode 100644 index 000000000..2b0aae58d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K5760.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K6336.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K6336.insts.bin new file mode 100644 index 000000000..7e2edcb9b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K6336.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K6336.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K6336.xclbin new file mode 100644 index 000000000..b7310a60f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K6336.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K64.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K64.insts.bin new file mode 100644 index 000000000..217f3e399 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K64.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K64.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K64.xclbin new file mode 100644 index 000000000..26dc9125d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K64.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K640.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K640.insts.bin new file mode 100644 index 000000000..099cb6f93 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K640.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K640.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K640.xclbin new file mode 100644 index 000000000..bd2c93303 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K640.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K6912.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K6912.insts.bin new file mode 100644 index 000000000..fed5bed84 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K6912.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K6912.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K6912.xclbin new file mode 100644 index 000000000..114b742fb Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K6912.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K704.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K704.insts.bin new file mode 100644 index 000000000..c430f70cd Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K704.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K704.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K704.xclbin new file mode 100644 index 000000000..9bcc64781 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K704.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K768.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K768.insts.bin new file mode 100644 index 000000000..b8917db47 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K768.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K768.xclbin new file mode 100644 index 000000000..8e3889b14 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K832.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K832.insts.bin new file mode 100644 index 000000000..85ba2471a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K832.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K832.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K832.xclbin new file mode 100644 index 000000000..bb1a0a07e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K832.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K896.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K896.insts.bin new file mode 100644 index 000000000..1e3c76cf3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K896.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K896.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K896.xclbin new file mode 100644 index 000000000..ef1562796 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K896.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K960.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K960.insts.bin new file mode 100644 index 000000000..05dce0e33 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K960.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K960.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K960.xclbin new file mode 100644 index 000000000..d03703942 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_2col/gemm_bf16_K960.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1024.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1024.insts.bin new file mode 100644 index 000000000..5cbfe311b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1024.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1024.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1024.xclbin new file mode 100644 index 000000000..3bb93a774 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1024.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1088.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1088.insts.bin new file mode 100644 index 000000000..41743a80d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1088.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1088.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1088.xclbin new file mode 100644 index 000000000..5dcd0bcf0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1088.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1152.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1152.insts.bin new file mode 100644 index 000000000..33045e378 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1152.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1152.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1152.xclbin new file mode 100644 index 000000000..e39843806 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1152.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1216.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1216.insts.bin new file mode 100644 index 000000000..0614a3f88 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1216.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1216.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1216.xclbin new file mode 100644 index 000000000..9efc0a1e1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1216.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K128.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K128.insts.bin new file mode 100644 index 000000000..5fa273b74 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K128.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K128.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K128.xclbin new file mode 100644 index 000000000..6d7dd74ff Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K128.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1280.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1280.insts.bin new file mode 100644 index 000000000..8242a1319 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1280.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1280.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1280.xclbin new file mode 100644 index 000000000..e32e488db Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1280.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1344.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1344.insts.bin new file mode 100644 index 000000000..ba0f2578a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1344.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1344.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1344.xclbin new file mode 100644 index 000000000..908186557 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1344.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1408.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1408.insts.bin new file mode 100644 index 000000000..976a5d663 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1408.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1408.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1408.xclbin new file mode 100644 index 000000000..0731d1837 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1408.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1472.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1472.insts.bin new file mode 100644 index 000000000..ee438bb65 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1472.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1472.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1472.xclbin new file mode 100644 index 000000000..ed03992e4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1472.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1536.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1536.insts.bin new file mode 100644 index 000000000..b0d62fdc5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1536.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1536.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1536.xclbin new file mode 100644 index 000000000..f8d42946f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1536.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1728.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1728.insts.bin new file mode 100644 index 000000000..dd34d9bf4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1728.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1728.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1728.xclbin new file mode 100644 index 000000000..c4922c5e2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K1728.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K192.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K192.insts.bin new file mode 100644 index 000000000..736fe8c84 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K192.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K192.xclbin new file mode 100644 index 000000000..0b7a5bab4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K2304.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K2304.insts.bin new file mode 100644 index 000000000..8f6965981 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K2304.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K2304.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K2304.xclbin new file mode 100644 index 000000000..eb8a8b373 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K2304.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K256.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K256.insts.bin new file mode 100644 index 000000000..cafec2c34 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K256.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K256.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K256.xclbin new file mode 100644 index 000000000..74a4297ea Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K256.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K2880.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K2880.insts.bin new file mode 100644 index 000000000..dead816e0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K2880.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K2880.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K2880.xclbin new file mode 100644 index 000000000..5b0d4cc38 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K2880.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K320.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K320.insts.bin new file mode 100644 index 000000000..a50f9880f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K320.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K320.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K320.xclbin new file mode 100644 index 000000000..f86ee83c8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K320.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K3456.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K3456.insts.bin new file mode 100644 index 000000000..860cf18c5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K3456.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K3456.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K3456.xclbin new file mode 100644 index 000000000..57cce138f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K3456.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K384.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K384.insts.bin new file mode 100644 index 000000000..fa403ad1a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K384.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K384.xclbin new file mode 100644 index 000000000..699c5ab5d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K4032.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K4032.insts.bin new file mode 100644 index 000000000..b55077e01 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K4032.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K4032.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K4032.xclbin new file mode 100644 index 000000000..2b2b53282 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K4032.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K448.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K448.insts.bin new file mode 100644 index 000000000..e11d8b40e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K448.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K448.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K448.xclbin new file mode 100644 index 000000000..af2f81486 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K448.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K4608.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K4608.insts.bin new file mode 100644 index 000000000..aee8534a9 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K4608.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K4608.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K4608.xclbin new file mode 100644 index 000000000..1d8e276bc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K4608.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K512.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K512.insts.bin new file mode 100644 index 000000000..d6995a53c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K512.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K512.xclbin new file mode 100644 index 000000000..1b2da991e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K5184.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K5184.insts.bin new file mode 100644 index 000000000..55a0999d5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K5184.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K5184.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K5184.xclbin new file mode 100644 index 000000000..e7919b64d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K5184.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K576.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K576.insts.bin new file mode 100644 index 000000000..58832296b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K576.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K576.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K576.xclbin new file mode 100644 index 000000000..d9435ba4d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K576.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K5760.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K5760.insts.bin new file mode 100644 index 000000000..1f0b1713e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K5760.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K5760.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K5760.xclbin new file mode 100644 index 000000000..62ea5267b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K5760.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K6336.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K6336.insts.bin new file mode 100644 index 000000000..d52329b17 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K6336.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K6336.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K6336.xclbin new file mode 100644 index 000000000..b08ac7a2d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K6336.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K64.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K64.insts.bin new file mode 100644 index 000000000..9cb6c916e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K64.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K64.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K64.xclbin new file mode 100644 index 000000000..02f4a4fbf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K64.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K640.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K640.insts.bin new file mode 100644 index 000000000..8ebccc887 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K640.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K640.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K640.xclbin new file mode 100644 index 000000000..ea96c931c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K640.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K6912.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K6912.insts.bin new file mode 100644 index 000000000..8bf0e5df3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K6912.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K6912.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K6912.xclbin new file mode 100644 index 000000000..f0de94e69 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K6912.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K704.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K704.insts.bin new file mode 100644 index 000000000..5376402b8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K704.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K704.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K704.xclbin new file mode 100644 index 000000000..34dbaafaa Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K704.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K768.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K768.insts.bin new file mode 100644 index 000000000..9921028c0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K768.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K768.xclbin new file mode 100644 index 000000000..5a992c56e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K832.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K832.insts.bin new file mode 100644 index 000000000..f873753c0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K832.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K832.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K832.xclbin new file mode 100644 index 000000000..5d6a238c7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K832.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K896.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K896.insts.bin new file mode 100644 index 000000000..45d5ddd89 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K896.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K896.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K896.xclbin new file mode 100644 index 000000000..44301ec54 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K896.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K960.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K960.insts.bin new file mode 100644 index 000000000..07303920c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K960.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K960.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K960.xclbin new file mode 100644 index 000000000..895066635 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_4col/gemm_bf16_K960.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1024.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1024.insts.bin new file mode 100644 index 000000000..b53ab1817 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1024.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1024.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1024.xclbin new file mode 100644 index 000000000..674d9ec65 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1024.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1088.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1088.insts.bin new file mode 100644 index 000000000..da0edb6a8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1088.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1088.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1088.xclbin new file mode 100644 index 000000000..1fb42addc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1088.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1152.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1152.insts.bin new file mode 100644 index 000000000..096bf56a1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1152.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1152.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1152.xclbin new file mode 100644 index 000000000..0348bb5f6 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1152.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1216.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1216.insts.bin new file mode 100644 index 000000000..65ee30f41 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1216.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1216.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1216.xclbin new file mode 100644 index 000000000..ccf4dcf69 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1216.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K128.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K128.insts.bin new file mode 100644 index 000000000..a2f77098d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K128.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K128.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K128.xclbin new file mode 100644 index 000000000..d69fed509 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K128.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1280.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1280.insts.bin new file mode 100644 index 000000000..9be50fc01 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1280.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1280.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1280.xclbin new file mode 100644 index 000000000..918029b2a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1280.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1344.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1344.insts.bin new file mode 100644 index 000000000..05d4e0835 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1344.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1344.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1344.xclbin new file mode 100644 index 000000000..c161c1381 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1344.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1408.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1408.insts.bin new file mode 100644 index 000000000..aed546861 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1408.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1408.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1408.xclbin new file mode 100644 index 000000000..9be10f268 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1408.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1472.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1472.insts.bin new file mode 100644 index 000000000..f8f9236b5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1472.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1472.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1472.xclbin new file mode 100644 index 000000000..64bfefcf8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1472.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1536.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1536.insts.bin new file mode 100644 index 000000000..0636bfa39 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1536.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1536.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1536.xclbin new file mode 100644 index 000000000..41b521471 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1536.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1728.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1728.insts.bin new file mode 100644 index 000000000..cad7daadf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1728.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1728.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1728.xclbin new file mode 100644 index 000000000..2609490ed Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K1728.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K192.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K192.insts.bin new file mode 100644 index 000000000..528819524 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K192.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K192.xclbin new file mode 100644 index 000000000..f39b848bf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K2304.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K2304.insts.bin new file mode 100644 index 000000000..eed41f925 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K2304.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K2304.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K2304.xclbin new file mode 100644 index 000000000..bd544ca74 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K2304.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K256.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K256.insts.bin new file mode 100644 index 000000000..f034f1538 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K256.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K256.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K256.xclbin new file mode 100644 index 000000000..e8d6015df Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K256.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K2880.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K2880.insts.bin new file mode 100644 index 000000000..717bbcd8a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K2880.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K2880.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K2880.xclbin new file mode 100644 index 000000000..20df41330 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K2880.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K320.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K320.insts.bin new file mode 100644 index 000000000..cc6bec853 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K320.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K320.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K320.xclbin new file mode 100644 index 000000000..d49df87a5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K320.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K3456.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K3456.insts.bin new file mode 100644 index 000000000..698019297 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K3456.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K3456.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K3456.xclbin new file mode 100644 index 000000000..7b84e78c1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K3456.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K384.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K384.insts.bin new file mode 100644 index 000000000..ffeb6e2ec Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K384.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K384.xclbin new file mode 100644 index 000000000..7b5a79266 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K4032.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K4032.insts.bin new file mode 100644 index 000000000..9fcd1454b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K4032.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K4032.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K4032.xclbin new file mode 100644 index 000000000..263edd088 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K4032.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K448.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K448.insts.bin new file mode 100644 index 000000000..9e16732f5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K448.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K448.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K448.xclbin new file mode 100644 index 000000000..0b4a43b53 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K448.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K4608.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K4608.insts.bin new file mode 100644 index 000000000..1078908ae Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K4608.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K4608.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K4608.xclbin new file mode 100644 index 000000000..3eb4a0b15 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K4608.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K512.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K512.insts.bin new file mode 100644 index 000000000..0c0ba6388 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K512.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K512.xclbin new file mode 100644 index 000000000..ab2476dbc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K5184.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K5184.insts.bin new file mode 100644 index 000000000..7811a3a55 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K5184.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K5184.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K5184.xclbin new file mode 100644 index 000000000..250fc9f6a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K5184.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K576.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K576.insts.bin new file mode 100644 index 000000000..44b553df4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K576.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K576.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K576.xclbin new file mode 100644 index 000000000..1ad0ff55f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K576.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K5760.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K5760.insts.bin new file mode 100644 index 000000000..3fec8bb87 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K5760.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K5760.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K5760.xclbin new file mode 100644 index 000000000..40b05d9b3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K5760.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K6336.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K6336.insts.bin new file mode 100644 index 000000000..208ddbd43 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K6336.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K6336.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K6336.xclbin new file mode 100644 index 000000000..2f0b58a85 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K6336.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K64.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K64.insts.bin new file mode 100644 index 000000000..1d146405f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K64.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K64.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K64.xclbin new file mode 100644 index 000000000..8f206f898 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K64.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K640.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K640.insts.bin new file mode 100644 index 000000000..7e5083706 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K640.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K640.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K640.xclbin new file mode 100644 index 000000000..10ce2bc8a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K640.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K6912.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K6912.insts.bin new file mode 100644 index 000000000..59b7466b3 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K6912.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K6912.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K6912.xclbin new file mode 100644 index 000000000..b92d525b1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K6912.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K704.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K704.insts.bin new file mode 100644 index 000000000..4f678d507 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K704.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K704.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K704.xclbin new file mode 100644 index 000000000..435228c44 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K704.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K768.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K768.insts.bin new file mode 100644 index 000000000..36ea56081 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K768.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K768.xclbin new file mode 100644 index 000000000..5e87043e4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K832.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K832.insts.bin new file mode 100644 index 000000000..35e4d746c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K832.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K832.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K832.xclbin new file mode 100644 index 000000000..bc7238a4a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K832.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K896.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K896.insts.bin new file mode 100644 index 000000000..c29e6b961 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K896.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K896.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K896.xclbin new file mode 100644 index 000000000..ac5ee2906 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K896.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K960.insts.bin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K960.insts.bin new file mode 100644 index 000000000..7f9deb905 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K960.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K960.xclbin b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K960.xclbin new file mode 100644 index 000000000..a19732d82 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/bfp16/npu2_8col/gemm_bf16_K960.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/grid.json b/cpp/external/ryzenai_artifacts/grid.json new file mode 100644 index 000000000..4d1aa7a4c --- /dev/null +++ b/cpp/external/ryzenai_artifacts/grid.json @@ -0,0 +1,5991 @@ +{ + "grid_version": 1, + "generated_by": "python/ryzenai_kernels/build_grid.py", + "note": "An xclbin depends only on (dtype, arch, n_aie_cols, K, tile). M and N are carried by the instruction stream, which sequence.cpp generates at run time, so compiled_at is provenance only and imposes no constraint on dispatch.", + "artifacts": [ + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 64, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K64.xclbin", + "xclbin_bytes": 25352, + "xclbin_sha256": "7c969f34b6fd4073543535cc5bd8b89d537e896d7b56f0e47fb3ed4cd746ab8c", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K64.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 128, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K128.xclbin", + "xclbin_bytes": 24776, + "xclbin_sha256": "eb9f1c6462381a22b24d46d70b189c9f8e3857b008c32fd88030168e54940b07", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K128.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 192, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K192.xclbin", + "xclbin_bytes": 23560, + "xclbin_sha256": "45757df712f937fbf4ff8b399c0414954e55296560e017b47c4303c2fb3dfe4f", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K192.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 256, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K256.xclbin", + "xclbin_bytes": 24328, + "xclbin_sha256": "c334af214fe8dde1d1b8e5f81e4e2054da3003b3ea0eb891188c1d034f3e3772", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K256.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 320, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K320.xclbin", + "xclbin_bytes": 25096, + "xclbin_sha256": "03ca1327e93a36a740479529a016621d7a2081e313271e5ee9b1395ffee951ea", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K320.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 384, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K384.xclbin", + "xclbin_bytes": 25864, + "xclbin_sha256": "62337215efbe1cb12c418e2d83f48bf16b234b8243a0626b384738210f960468", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K384.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 448, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K448.xclbin", + "xclbin_bytes": 26632, + "xclbin_sha256": "fa0fe57d4d518804400d60b9055cdb7ef488b8f1fa3be1e724866f9ccc776d58", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K448.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 512, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K512.xclbin", + "xclbin_bytes": 36104, + "xclbin_sha256": "61aa1696207da39c5e50237479101e5c3fdf5ab93146b8f03dcd89aad742973b", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K512.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 576, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K576.xclbin", + "xclbin_bytes": 32776, + "xclbin_sha256": "c9f04c212c62bbb3a2c1717710620657e438fa1cef3c4eba8bcaf3e0a85b1d34", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K576.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 640, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K640.xclbin", + "xclbin_bytes": 29896, + "xclbin_sha256": "c1c243f3f9a1bd06650684dbf4411d18e0274abd49fc87ff4aed6d099abf7391", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K640.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 704, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K704.xclbin", + "xclbin_bytes": 36616, + "xclbin_sha256": "f55254eb8ffad2c3bd0857e4fae26f9fe95d08366d2099912feef96f9421ab69", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K704.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 768, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K768.xclbin", + "xclbin_bytes": 36104, + "xclbin_sha256": "ab4a63fbd020f03533ba5980be353e11f74f35d0f2f2275d65f61a547edfa303", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K768.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 832, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K832.xclbin", + "xclbin_bytes": 35976, + "xclbin_sha256": "9d4f24d14bcf822aab91ce85752f24721d147003c18bdeece8688e7d7f56c39e", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K832.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 896, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K896.xclbin", + "xclbin_bytes": 29896, + "xclbin_sha256": "a850384e185434d62b46cd34e7cd8124bb9bd053d7b9328300654754b5d7a97b", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K896.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 960, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K960.xclbin", + "xclbin_bytes": 32776, + "xclbin_sha256": "d3e8cce386bec42daf6e8abbb3f356f67eaffe7a85baf82061192c7e6a303d6a", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K960.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 1024, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K1024.xclbin", + "xclbin_bytes": 36104, + "xclbin_sha256": "52829de6e37be5d857e206eba73bb3704b5ea090e0337758f60d156efdbb2b07", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K1024.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 1088, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K1088.xclbin", + "xclbin_bytes": 35976, + "xclbin_sha256": "9246e6e3f094f358b3505311e0ec98a58e2b7c00d38b38b9d6558c4638097ff0", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K1088.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 1152, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K1152.xclbin", + "xclbin_bytes": 32776, + "xclbin_sha256": "1d2a4f95fdedea7917d77671a667659edabc8b32044c115b3c576adb1ab088a5", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K1152.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 1216, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K1216.xclbin", + "xclbin_bytes": 36616, + "xclbin_sha256": "9987e61e67c86a3e23989403bfd538696b1c49254b06e3c689031f4bb24b622e", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K1216.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 1280, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K1280.xclbin", + "xclbin_bytes": 36104, + "xclbin_sha256": "cb6ae6307f951dd387fe394f870bb0e405deb58d3f5403e34397ed28d993e34f", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K1280.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 1344, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K1344.xclbin", + "xclbin_bytes": 32776, + "xclbin_sha256": "c8e1afc2af7d95f9a53a8774a36f7279d304e84d2d8150347e140a439ccd5e91", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K1344.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 1408, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K1408.xclbin", + "xclbin_bytes": 29896, + "xclbin_sha256": "e8a8c800a23d779467f1bef7b6d471cf00134dddceeab481f758112b03b085a9", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K1408.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 1472, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K1472.xclbin", + "xclbin_bytes": 36616, + "xclbin_sha256": "4d7f15310e4cd70181a5ba2287b12a8d2a1e76b8871b79150dd985177876b62a", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K1472.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 1536, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K1536.xclbin", + "xclbin_bytes": 36104, + "xclbin_sha256": "11f489c75e18bc82f833ba5a64988d0bb5b28f8243f32639965beea2c78a2ef2", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K1536.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 1728, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K1728.xclbin", + "xclbin_bytes": 32776, + "xclbin_sha256": "f5fd1871a7ed7363211c3f40f27652254fa983eca71fcf2f02090b294035d335", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K1728.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 2304, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K2304.xclbin", + "xclbin_bytes": 36104, + "xclbin_sha256": "6c42a4b2886e851b45dc635e4fa7cd84fd6f652787bbfe7cdf0660937b7a7934", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K2304.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 2880, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K2880.xclbin", + "xclbin_bytes": 32776, + "xclbin_sha256": "e918681710cd34c5888b59eeb32bf7169a6404f976839b03d18df8d2c1647545", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K2880.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 3456, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K3456.xclbin", + "xclbin_bytes": 32776, + "xclbin_sha256": "fa4ca0b4da846d0eb8bf16bb0f9524a58022a3d9e4629364562e227d648c5038", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K3456.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 4032, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K4032.xclbin", + "xclbin_bytes": 32776, + "xclbin_sha256": "fe09ef7ab254dc87ea40500774e59ffc905713f3a1210eecefdbfcc2e7a501f0", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K4032.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 4608, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K4608.xclbin", + "xclbin_bytes": 36104, + "xclbin_sha256": "778907658262107fd8f258f2a014f9f4daeda74f450a1ef4a53628b72d35955b", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K4608.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 5184, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K5184.xclbin", + "xclbin_bytes": 32776, + "xclbin_sha256": "b705d650b22dbf086e63528f4b8bae3d8824b9f445de53ce6d564a06dff739ba", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K5184.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 5760, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K5760.xclbin", + "xclbin_bytes": 32776, + "xclbin_sha256": "519041fbda3ae57e2ed71fc37e174f4c92a80f4c158807d29283474cd233396c", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K5760.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 6336, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K6336.xclbin", + "xclbin_bytes": 32776, + "xclbin_sha256": "7917f4746e698fcbad5eff28906767fee21cfd3285c42298484f981106de784c", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K6336.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 1, + "K": 6912, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_1col/gemm_bf16_K6912.xclbin", + "xclbin_bytes": 36104, + "xclbin_sha256": "0d40fdc41f333b2a066248dc6e307fab5c82a0f2c5b522d0607aa7a9d6bfee40", + "insts_golden": "bf16/npu1_1col/gemm_bf16_K6912.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 64, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K64.xclbin", + "xclbin_bytes": 42888, + "xclbin_sha256": "5b332c3214a4036238c5a07e31870f46fb40afd2370c7c53e2919506c2318d27", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K64.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 128, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K128.xclbin", + "xclbin_bytes": 41736, + "xclbin_sha256": "3eb70884e0f2b1ea6a2ca898827c5023610482c354544a9e91d95ceef0d47ed4", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K128.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 192, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K192.xclbin", + "xclbin_bytes": 39304, + "xclbin_sha256": "51ce027cbb472b4539e6a2edf606b4a16c22e4e819938dbe19a29dd72c90f49d", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K192.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 256, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K256.xclbin", + "xclbin_bytes": 40840, + "xclbin_sha256": "74f99246ff3a45dfb30f12082b13bdda532206242f32756a5de588883112d385", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K256.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 320, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K320.xclbin", + "xclbin_bytes": 42376, + "xclbin_sha256": "cb14e2a10bb90475da949a3249f115b2eac73ad6c67b4e9c3da108bbd2e5b205", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K320.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 384, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K384.xclbin", + "xclbin_bytes": 43912, + "xclbin_sha256": "a03e9672692fd1b95fd369c8375e8cab037aa8d6e6a7b6ead8eb2385399f42f6", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K384.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 448, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K448.xclbin", + "xclbin_bytes": 45448, + "xclbin_sha256": "b034f1973b3804cbbe7f7e1ecaeb2ead8ea20628387df3b3c44d337777f2e16c", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K448.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 512, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K512.xclbin", + "xclbin_bytes": 64392, + "xclbin_sha256": "ad44da70bf4970a7d2b48233d982af65187d777d851027cca5d6ed0fa079a5d4", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K512.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 576, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K576.xclbin", + "xclbin_bytes": 57736, + "xclbin_sha256": "cfb8b606d1f38ae4ddc43f04e5c92b25a6e635a9a0f5745677f53bd66618fe14", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K576.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 640, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K640.xclbin", + "xclbin_bytes": 51976, + "xclbin_sha256": "498303d10d0a46c43600ee821c5c7bf1f68e29e8e47425d6ab7115c1a55567a0", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K640.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 704, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K704.xclbin", + "xclbin_bytes": 65416, + "xclbin_sha256": "833ee4e1afae81e04c5387d2f14da21166154e6fb17d1f6fa3978e6f7b834198", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K704.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 768, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K768.xclbin", + "xclbin_bytes": 64392, + "xclbin_sha256": "0fa6eae1c482f0450abdb22fd2a35ce00b734205c48d7f7a7f4ed9684d4478e2", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K768.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 832, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K832.xclbin", + "xclbin_bytes": 64136, + "xclbin_sha256": "990d28e7242ecaf4ed02abe7040e0498eda3d8532cfccff7f8ac6a90beb306ca", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K832.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 896, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K896.xclbin", + "xclbin_bytes": 51976, + "xclbin_sha256": "20d02ae5dd9440a05e99c6285ad9906f74fb4dd6874e0b847bcb458e3a0ea075", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K896.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 960, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K960.xclbin", + "xclbin_bytes": 57736, + "xclbin_sha256": "69ccc59afcf8a1ea244260457cff38e956b9aded292da8d19ae8f0a300f9c710", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K960.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 1024, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K1024.xclbin", + "xclbin_bytes": 64392, + "xclbin_sha256": "389465d465c1a15dfea1641e376601782452fa4a6dc85c8b5d7d0b8f9e3ca8e3", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K1024.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 1088, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K1088.xclbin", + "xclbin_bytes": 64136, + "xclbin_sha256": "7d07ae03fedbe305e610c567ab2b9977eb133bc81566957e79fff5c912898bd2", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K1088.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 1152, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K1152.xclbin", + "xclbin_bytes": 57736, + "xclbin_sha256": "5e25b3acd78b45a925545ba3215aded0f413a1447d477cc4c8d22a08153675a7", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K1152.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 1216, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K1216.xclbin", + "xclbin_bytes": 65416, + "xclbin_sha256": "f13a4bc86520edb1de85a2cf53a2ee301745031139336e71b8a27c312a222f2b", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K1216.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 1280, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K1280.xclbin", + "xclbin_bytes": 64392, + "xclbin_sha256": "3b872db2707e866ad747a2dd01feaf01db6ee4f1c4cfc5b917e22d62bf20bfe7", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K1280.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 1344, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K1344.xclbin", + "xclbin_bytes": 57736, + "xclbin_sha256": "55c56d76ce1e27eeefe33c773ba2776c4637e2f310971a027ffeaea3f66651e3", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K1344.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 1408, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K1408.xclbin", + "xclbin_bytes": 51976, + "xclbin_sha256": "1ad0a7ffdeaa6767cd89f6a17f5f93acfbd6228a53d85e490db760b6fe618615", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K1408.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 1472, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K1472.xclbin", + "xclbin_bytes": 65416, + "xclbin_sha256": "6c27471444672a9702cacbbd91e9043f72c0edac968130f30dc5b57ff47d13b8", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K1472.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 1536, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K1536.xclbin", + "xclbin_bytes": 64392, + "xclbin_sha256": "1d4b9501e380e3e97fe9d51b385c8aece716ace1f3530007679a28a147a5bf06", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K1536.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 1728, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K1728.xclbin", + "xclbin_bytes": 57736, + "xclbin_sha256": "4a0dbb55d0461214ef8ae4f63e2740977c2ecae33cca5a0a17936bc4c3ee01f1", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K1728.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 2304, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K2304.xclbin", + "xclbin_bytes": 64392, + "xclbin_sha256": "d83a9b52d7d3ece51e736fdb7e14334f442304a34990ead4c3a37ec34f24f70f", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K2304.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 2880, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K2880.xclbin", + "xclbin_bytes": 57736, + "xclbin_sha256": "df5a47675abad7e4fab4d323b1906852b7a6ff5be329e4e4aa6eeef794ed3eac", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K2880.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 3456, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K3456.xclbin", + "xclbin_bytes": 57736, + "xclbin_sha256": "decc1dddae857180a2901207249194e4b5a32edc8a18f4229f9691880995709f", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K3456.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 4032, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K4032.xclbin", + "xclbin_bytes": 57736, + "xclbin_sha256": "e7d0a21426805ee7ada99a523c1243d84ca3ce74f56efe69d43a88e8987f97bc", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K4032.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 4608, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K4608.xclbin", + "xclbin_bytes": 64392, + "xclbin_sha256": "725ceb63599929dfa84c4cdff249da1dea9f0bb233d2cbb47d70a6d786f5899a", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K4608.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 5184, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K5184.xclbin", + "xclbin_bytes": 57736, + "xclbin_sha256": "557d93053a0d4c07aa3bd67da28efb440d37f0750d384152e501b466557598bf", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K5184.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 5760, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K5760.xclbin", + "xclbin_bytes": 57736, + "xclbin_sha256": "54d9fb3e866b00457a97c4fc0db3f8d3bc2da0348d6d928165ab7e60f7be1bb3", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K5760.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 6336, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K6336.xclbin", + "xclbin_bytes": 57736, + "xclbin_sha256": "cee452c7a7595d9594053bd7e545eccb5bc5ba370cf49abca8b2ba0934cacd0e", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K6336.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 2, + "K": 6912, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_2col/gemm_bf16_K6912.xclbin", + "xclbin_bytes": 64392, + "xclbin_sha256": "ed1c9c92a5ee107710077a51cf02ae0447b693dd6a065706bba2c32a11874344", + "insts_golden": "bf16/npu1_2col/gemm_bf16_K6912.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 64, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K64.xclbin", + "xclbin_bytes": 78366, + "xclbin_sha256": "003a016e289889bacbef273f76cbadb389c50e66be2bc7fd090e48d6f215314e", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K64.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 128, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K128.xclbin", + "xclbin_bytes": 76062, + "xclbin_sha256": "ff0decef376d05b68e80a362bedec423afbf078a16a2de35a858e526fc431213", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K128.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 192, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K192.xclbin", + "xclbin_bytes": 71197, + "xclbin_sha256": "ec78ae484cdf1ef4d0caa11184c7fe1e90ee80ba4386d847854f8742e0f99b21", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K192.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 256, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K256.xclbin", + "xclbin_bytes": 74270, + "xclbin_sha256": "2bd5e1d582128447a6bf6ffbee067ee985b28e8208fd469d05c0c88f9c810fc5", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K256.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 320, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K320.xclbin", + "xclbin_bytes": 77342, + "xclbin_sha256": "e211855cc4b732c59ed2fea1ef23adf33d603340f3ac7c8b213c111f35242faa", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K320.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 384, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K384.xclbin", + "xclbin_bytes": 80414, + "xclbin_sha256": "20d55b6f562badbdc9f91d2a21e010a79e495490eb772d07d2c20d81d363cfa5", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K384.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 448, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K448.xclbin", + "xclbin_bytes": 83486, + "xclbin_sha256": "37c688366e679927165d4e398a05de63988a1344cf9a7aec8409ef21b1284620", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K448.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 512, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K512.xclbin", + "xclbin_bytes": 121374, + "xclbin_sha256": "9347fd33202aef08625767f94f78f9c4cf2bd981a8bd098099438beed1fa3979", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K512.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 576, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K576.xclbin", + "xclbin_bytes": 108062, + "xclbin_sha256": "5d89770e92970216544d06859d450732a064a08eaacb09b04df8efd6ae55b498", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K576.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 640, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K640.xclbin", + "xclbin_bytes": 96542, + "xclbin_sha256": "4ee82d5d59a05cb1ebf76c31f995839f60e1e5f5516a6eb949547abcc6f86000", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K640.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 704, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K704.xclbin", + "xclbin_bytes": 123422, + "xclbin_sha256": "e6434bc2c4d65948f4f5ccc89ed7154b54321a3f917665f8c157a2dd4e6f4b35", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K704.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 768, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K768.xclbin", + "xclbin_bytes": 121374, + "xclbin_sha256": "59505b9e1d682fa4176da7dad877d413425857f71b843c8dbbaae65342ca1ec7", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K768.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 832, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K832.xclbin", + "xclbin_bytes": 120862, + "xclbin_sha256": "1b5647c8a1666e15aa5f98d89e9e994c663223c20e9b8ed74e6938e784377fe0", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K832.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 896, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K896.xclbin", + "xclbin_bytes": 96542, + "xclbin_sha256": "81e73eddafb95c1794e0b8db6d1fb2046fdf5b5cb21f25b107f53a17cadebb30", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K896.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 960, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K960.xclbin", + "xclbin_bytes": 108062, + "xclbin_sha256": "ad56f3b47b38c3af84744a4925d5ac5da4ee279b43fcce5b33aaacd05c7e3d5d", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K960.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 1024, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K1024.xclbin", + "xclbin_bytes": 121374, + "xclbin_sha256": "3461b5892d225c0b1bf1c62cf36f878348f1be9f4a450d7129dfecf1e32e2ef1", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K1024.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 1088, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K1088.xclbin", + "xclbin_bytes": 120862, + "xclbin_sha256": "5b0ffbbac9a44533545fe0441a4616375fa7cd58261ec4be241a8a3353ddf5c1", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K1088.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 1152, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K1152.xclbin", + "xclbin_bytes": 108062, + "xclbin_sha256": "47e696f4ce10571e4036b0118c6df735c381a3a6e945f7cc07db91cae5ab9ca5", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K1152.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 1216, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K1216.xclbin", + "xclbin_bytes": 123422, + "xclbin_sha256": "ab1467728cf873b3e7697a1590b2a89e4757cdf334a52fbaeb0918261718f0bd", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K1216.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 1280, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K1280.xclbin", + "xclbin_bytes": 121374, + "xclbin_sha256": "5c4cd599cda361acd0db732a838036ac99c41c98ab809317200979297c3b2258", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K1280.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 1344, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K1344.xclbin", + "xclbin_bytes": 108062, + "xclbin_sha256": "1944f3beac4fb17623533d158c582f10bdd60005b7a5d9ee7f5bc9721ab61d4d", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K1344.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 1408, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K1408.xclbin", + "xclbin_bytes": 96542, + "xclbin_sha256": "eca7e3cb6087e95fafd040d489e9cab00580d704d1b04ecb49eade4356c620d4", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K1408.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 1472, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K1472.xclbin", + "xclbin_bytes": 123422, + "xclbin_sha256": "c71fc305e5df7652805b06171483625502b8924fc2a10afc1a6760c418741d9e", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K1472.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 1536, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K1536.xclbin", + "xclbin_bytes": 121374, + "xclbin_sha256": "a107a9f1fc06866f5c50ad12a292141093aed1c6460c7b2ffb4f2a1598361718", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K1536.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 1728, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K1728.xclbin", + "xclbin_bytes": 108062, + "xclbin_sha256": "52ed1f4d6551aec1d18b1c560bc82ea418df2df984b31d854fd2e1b79e4b6856", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K1728.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 2304, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K2304.xclbin", + "xclbin_bytes": 121374, + "xclbin_sha256": "9879673fb966d76ec4815db94c1bc8183fd998404f0798e10cce84cc3ac2351d", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K2304.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 2880, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K2880.xclbin", + "xclbin_bytes": 108062, + "xclbin_sha256": "9a9ab6db21097d6ad19a661480f190e441dbd7ee945e2e0a3f43a99d476a7346", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K2880.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 3456, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K3456.xclbin", + "xclbin_bytes": 108062, + "xclbin_sha256": "18bbdb45d60b3a75b18fbebaeace4fbf9e7cad45187820d5548e4b4f08e637f2", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K3456.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 4032, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K4032.xclbin", + "xclbin_bytes": 108062, + "xclbin_sha256": "4bfe5846d244a03d66bbde0ecd3daf6fa0824d201c3db7bc7d23134517450023", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K4032.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 4608, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K4608.xclbin", + "xclbin_bytes": 121374, + "xclbin_sha256": "4c97987205d07d9b0882e01141891695e69092ab2a4008327f77b8d19705844d", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K4608.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 5184, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K5184.xclbin", + "xclbin_bytes": 108062, + "xclbin_sha256": "cdb4a58ed81caf48347843c3dd7e9c89098d32ccfa1ff59608384fc877647b67", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K5184.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 5760, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K5760.xclbin", + "xclbin_bytes": 108062, + "xclbin_sha256": "5596fa82555d16ff21502180039083c44dd84062fc69fa85029bac625b0995c6", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K5760.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 6336, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K6336.xclbin", + "xclbin_bytes": 108062, + "xclbin_sha256": "caacaa38cc225cd586f91185adf0572610e4cba017ab379a4b6e229b01f065a6", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K6336.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu1", + "n_aie_cols": 4, + "K": 6912, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu1_4col/gemm_bf16_K6912.xclbin", + "xclbin_bytes": 121374, + "xclbin_sha256": "bc8588c72108ca6c10aa49823d77563955b03bfe54a977c9517cdfb58aaf294e", + "insts_golden": "bf16/npu1_4col/gemm_bf16_K6912.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 64, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K64.xclbin", + "xclbin_bytes": 24520, + "xclbin_sha256": "e4bf1e46f419374054cb46b97903b10b914187500c1f30a6ebe3ad65ec2c44ba", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K64.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 128, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K128.xclbin", + "xclbin_bytes": 27592, + "xclbin_sha256": "9b3ae189f7412f5d57731bbcdbab62176f90136b67dc4559d60c4bcac8f52b28", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K128.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 192, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K192.xclbin", + "xclbin_bytes": 22536, + "xclbin_sha256": "508c6a00a33091e9baa63e022fdc370011dd00c0fe37b376c3da9ba0776575ca", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K192.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 256, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K256.xclbin", + "xclbin_bytes": 23240, + "xclbin_sha256": "b0a61e2b07814fc394645de64a71fdfd0f8e3d2b0ddc58a8aba3d0ef06e6b274", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K256.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 320, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K320.xclbin", + "xclbin_bytes": 23944, + "xclbin_sha256": "8a1ff9f99fb9fa7c9a23016f15fb76086472b153dc3d46a5eeeda3cfd2acdeaa", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K320.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 384, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K384.xclbin", + "xclbin_bytes": 24648, + "xclbin_sha256": "51bd46329159262a63263dfc9d1a0cdba0d168caf7471b725e9092c237734993", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K384.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 448, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K448.xclbin", + "xclbin_bytes": 25352, + "xclbin_sha256": "fb7d11766f238d07090f7c3f109aff732b3f3f4ea448388863d232b7c8da001e", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K448.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 512, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K512.xclbin", + "xclbin_bytes": 26056, + "xclbin_sha256": "990cc7fe77565cf0e1cfe1de58840cc49be3c0ff197040ca7ee4891e1c5cc221", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K512.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 576, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K576.xclbin", + "xclbin_bytes": 26760, + "xclbin_sha256": "ed5fe165764bec49fbcbfaad40c6c0176c54229739ebcfd3cc4c4455003ef899", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K576.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 640, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K640.xclbin", + "xclbin_bytes": 27464, + "xclbin_sha256": "61645b488f708fccb4a52123939f39e9a2371042e744c40231c2ee3867576149", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K640.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 704, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K704.xclbin", + "xclbin_bytes": 28168, + "xclbin_sha256": "00ef0fd9b726bb57aa9e118b8b953bd15fc893a5ab8d30a08e762ba5d6a78af9", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K704.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 768, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K768.xclbin", + "xclbin_bytes": 28872, + "xclbin_sha256": "58ad70211e7d60509ec2645eb61654858f68db830351804f5066e9afa5f2afd4", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K768.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 832, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K832.xclbin", + "xclbin_bytes": 23880, + "xclbin_sha256": "d11e93bf53a881387c0a94c038f0f696e79ba510f0ef39fe91422f5fb9164428", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K832.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 896, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K896.xclbin", + "xclbin_bytes": 22344, + "xclbin_sha256": "c2737c3612fb1849e4134a9faa5adb6a12ad98ed3e377c7c00ad8f9a12579a25", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K896.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 960, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K960.xclbin", + "xclbin_bytes": 22920, + "xclbin_sha256": "e5b0d210cb6feb8cfc875be6116dc489a3f28d3e97042f621d45622f4123cab3", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K960.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1024, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K1024.xclbin", + "xclbin_bytes": 23560, + "xclbin_sha256": "79c2df60bb24998fbe0894d43795a0155a074ebd15b391260b18890286effad8", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K1024.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1088, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K1088.xclbin", + "xclbin_bytes": 23880, + "xclbin_sha256": "be7fbb5d3de823019a4f90ed72666423cd50ed453aba5933d7042b8a4eb12340", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K1088.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1152, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K1152.xclbin", + "xclbin_bytes": 22920, + "xclbin_sha256": "9122b4d17395a003aba92563a774cf2a9ff43f0b6c51b3d27f84e4dc8cc231fb", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K1152.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1216, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K1216.xclbin", + "xclbin_bytes": 23816, + "xclbin_sha256": "1e52350f7f84adcb5ae02e7e3e2d968977f6554c629975b312c1c22332d90646", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K1216.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1280, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K1280.xclbin", + "xclbin_bytes": 23560, + "xclbin_sha256": "5d2e8c05126d66f1b1ae6eb9f565381e3038310d619ec87f49ff8e12da9c4915", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K1280.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1344, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K1344.xclbin", + "xclbin_bytes": 22920, + "xclbin_sha256": "f482d0d0c91cfea68c6ae032a4bc3c03da6370f5787379f28e813d87448a9484", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K1344.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1408, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K1408.xclbin", + "xclbin_bytes": 22344, + "xclbin_sha256": "c59ef27ce3d2cb5a6aad0bca05d7c7c48420dc442b3bc9925079b742bca0625f", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K1408.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1472, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K1472.xclbin", + "xclbin_bytes": 23816, + "xclbin_sha256": "828b64993ef33fc9c661d7c8b0df3c263b7a20ecd46b2008ef87b8f7a24049b0", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K1472.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1536, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K1536.xclbin", + "xclbin_bytes": 23560, + "xclbin_sha256": "ec712aa979972ed68edb6a839d1bdd8819c1d1967bac98802194b6fe405e2c58", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K1536.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1728, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K1728.xclbin", + "xclbin_bytes": 22920, + "xclbin_sha256": "e5cb6bc8439e9e09684e163d3c8acf6fbc87a0fbaf3e25cf8922e06362f2dadb", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K1728.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 2304, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K2304.xclbin", + "xclbin_bytes": 23560, + "xclbin_sha256": "c2e7b754ef446033a5ff81f9f7c3c7750fcd4a0ab3ae3c98ba749eb30900a66b", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K2304.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 2880, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K2880.xclbin", + "xclbin_bytes": 22920, + "xclbin_sha256": "27971e0059a690ec9ac28920ef8cbf55f6f0e2bd55f0bc6d9e23d065f38337e5", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K2880.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 3456, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K3456.xclbin", + "xclbin_bytes": 22920, + "xclbin_sha256": "e6e71f4bdeeec397550acbc070d7c25a5074c93af0f7d99ae7eb9cb9c67889c0", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K3456.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 4032, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K4032.xclbin", + "xclbin_bytes": 22920, + "xclbin_sha256": "0f9b0225639014ec6075d300192cf0948c117694d4a337ad14588ca4fbfa5688", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K4032.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 4608, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K4608.xclbin", + "xclbin_bytes": 23560, + "xclbin_sha256": "893bb1ea5a3924fbf077e979199115ac020600ce5d484f26dd7fb3ff4a71158d", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K4608.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 5184, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K5184.xclbin", + "xclbin_bytes": 22920, + "xclbin_sha256": "77df7410fa90109357a8a711315e7611705565b1baafe8100619c6033ef7d154", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K5184.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 5760, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K5760.xclbin", + "xclbin_bytes": 22920, + "xclbin_sha256": "3c47f724a6ca2d18900c42d03094810eb642b78f9b1cb516b120eca77d0208b6", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K5760.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 6336, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K6336.xclbin", + "xclbin_bytes": 22920, + "xclbin_sha256": "0886077d518b6e66a17f3a341396f6976e26f26af162db6c4e8e167cb0a56735", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K6336.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 6912, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_1col/gemm_bf16_K6912.xclbin", + "xclbin_bytes": 23560, + "xclbin_sha256": "eb83e3acd2fd6e24da03a8d694b1fd8528bec5831b8faab729ff60eb8da255b2", + "insts_golden": "bf16/npu2_1col/gemm_bf16_K6912.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 64, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K64.xclbin", + "xclbin_bytes": 41304, + "xclbin_sha256": "006287507bfd8b051d57d99c0853f85a8a37bae2e77383ad748ab3125e6ff01d", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K64.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 128, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K128.xclbin", + "xclbin_bytes": 47448, + "xclbin_sha256": "80dae6541cc475672b34c7a2bc56df733d97a25de0baf54527e68784e7514a15", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K128.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 192, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K192.xclbin", + "xclbin_bytes": 37336, + "xclbin_sha256": "ef8f9ae50e8277a8bd03bb1231b5e8a37f425d83f435f98399d3d5c2a20d54c6", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K192.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 256, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K256.xclbin", + "xclbin_bytes": 38744, + "xclbin_sha256": "255d5cf6864d467c65c0b4311f459b80fe5dd0d5b3fa15c37228aa7033661997", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K256.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 320, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K320.xclbin", + "xclbin_bytes": 40152, + "xclbin_sha256": "0cc2b4edff23645d9b82333668ba32292381f2c4e40d8f3e689253062b797ca3", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K320.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 384, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K384.xclbin", + "xclbin_bytes": 41560, + "xclbin_sha256": "f3449fd32de835ea66ea4f870969f9f9cf6c513192badb485deba96f345ad0ba", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K384.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 448, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K448.xclbin", + "xclbin_bytes": 42968, + "xclbin_sha256": "90dc7cee8ccee5f2a7e43931eb6ee90af55dcc1dba2294c65d889cdfa1918f43", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K448.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 512, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K512.xclbin", + "xclbin_bytes": 44376, + "xclbin_sha256": "97c83dcc3eede5661bc32ddc8d48978db1e7b0d42a08c414ca19718c0a5e4052", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K512.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 576, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K576.xclbin", + "xclbin_bytes": 45784, + "xclbin_sha256": "52bc1a3317aafe725a2cc20b0b040d59b5e43650f6c020f93aaf491f42b487d8", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K576.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 640, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K640.xclbin", + "xclbin_bytes": 47192, + "xclbin_sha256": "f7d6cc7da150a1193901c0cf3d74a0684bfcefbbf1ab91e377e15059b6a65ac3", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K640.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 704, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K704.xclbin", + "xclbin_bytes": 48600, + "xclbin_sha256": "995ae5d9660f660b6683d8f0485d807f7ebb92e4984d38a0d29246e7d5d7829f", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K704.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 768, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K768.xclbin", + "xclbin_bytes": 50008, + "xclbin_sha256": "87126c39eea1b12360f5b02bedc5f84b2f0924cc2623a025cc23a69f1abbd415", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K768.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 832, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K832.xclbin", + "xclbin_bytes": 40024, + "xclbin_sha256": "665ee05045a554324690aea483a439420281e32387580d2870b0f1a2a39087c8", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K832.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 896, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K896.xclbin", + "xclbin_bytes": 36952, + "xclbin_sha256": "e43592fcc91f5c33c22dca7aec3902feee4f0e280fb6b48403af15949cf50ea4", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K896.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 960, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K960.xclbin", + "xclbin_bytes": 38104, + "xclbin_sha256": "600a067fa014d031ccf3e11b3447edbdd1f2e42ace8db1332667af9c676c0643", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K960.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1024, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K1024.xclbin", + "xclbin_bytes": 39384, + "xclbin_sha256": "e7604da02d7ebfc25ee8828fe0a01f9988c973afadf0f531c8d49c7013857d93", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K1024.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1088, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K1088.xclbin", + "xclbin_bytes": 40024, + "xclbin_sha256": "a902b8c7c04a1aefc27586aac4f9185d0394b9be7410fb88348d1ba71287c9bd", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K1088.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1152, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K1152.xclbin", + "xclbin_bytes": 38104, + "xclbin_sha256": "0fe956ce37da767fa62dcf93a1f2e7d9d6e4170cf5367f179a96d49b98568209", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K1152.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1216, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K1216.xclbin", + "xclbin_bytes": 39896, + "xclbin_sha256": "4b5d3af9966c3377171cb7fb98f16a315796a4162aa7178edf077f47136253f9", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K1216.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1280, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K1280.xclbin", + "xclbin_bytes": 39384, + "xclbin_sha256": "8f18befeeadf27c1f35b773f4a57833a3580216541b545f7258e01476b6169ff", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K1280.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1344, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K1344.xclbin", + "xclbin_bytes": 38104, + "xclbin_sha256": "636114cbac8366ae0dd795fcce10042c88acdc8f853b3d6b043e3ffcddd06162", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K1344.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1408, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K1408.xclbin", + "xclbin_bytes": 36952, + "xclbin_sha256": "347dcc0f0a47279afc8a3a2b07745df34ee4405869a5ea63d08f57fba79c8438", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K1408.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1472, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K1472.xclbin", + "xclbin_bytes": 39896, + "xclbin_sha256": "663b68104bcb6865631516d9b33d4ad7a31d9b464b95fabb8be0737862f6856c", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K1472.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1536, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K1536.xclbin", + "xclbin_bytes": 39384, + "xclbin_sha256": "f1ee118c897a0574dd506bc4ebbdbe326d5284557f433a231f2db1607a557235", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K1536.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1728, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K1728.xclbin", + "xclbin_bytes": 38104, + "xclbin_sha256": "402ade6814723f900f9814ae66a1f9aa6a5eb3f1e638a2cd42e38a883c87a9e9", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K1728.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 2304, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K2304.xclbin", + "xclbin_bytes": 39384, + "xclbin_sha256": "f2054cdc6b29c721dcc20b32c79f92b66bdecfc0043452a37cee3c7293e0d288", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K2304.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 2880, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K2880.xclbin", + "xclbin_bytes": 38104, + "xclbin_sha256": "b92e671ca1042885d76569a155eebf7da2e756b63ce73508cc60dd588947442d", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K2880.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 3456, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K3456.xclbin", + "xclbin_bytes": 38104, + "xclbin_sha256": "d172e0568e22425a4072361bb5d3b1c79e8cad35cf400582b43bc23ddccb6434", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K3456.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 4032, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K4032.xclbin", + "xclbin_bytes": 38104, + "xclbin_sha256": "57b7de3367d213c8515cce2d4d85537a82b3cdb77885544ab6a35d1dc4999ac4", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K4032.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 4608, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K4608.xclbin", + "xclbin_bytes": 39384, + "xclbin_sha256": "2ed32a5823cbdccd2b9e7aaa95eb340f28810b8242599fab39bbb82f4df8b408", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K4608.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 5184, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K5184.xclbin", + "xclbin_bytes": 38104, + "xclbin_sha256": "9f6af645e032d6b44b76408f68a4700a44ae3255b3bcd86f87a8fb4050d1fa39", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K5184.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 5760, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K5760.xclbin", + "xclbin_bytes": 38104, + "xclbin_sha256": "e923f4a4c0a9314d402a975d12d865eccb6dd8d3af1d3d81099cea25323aa328", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K5760.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 6336, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K6336.xclbin", + "xclbin_bytes": 38104, + "xclbin_sha256": "fc6676bc65b5f4c26a76021635dd198ee9a5fb53b292b8342292aa1f0709d7bc", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K6336.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 6912, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_2col/gemm_bf16_K6912.xclbin", + "xclbin_bytes": 39384, + "xclbin_sha256": "4bde66b816a68c6b30bdfdb2d0f4bfe02744daa692c2e12bc6128483a164e424", + "insts_golden": "bf16/npu2_2col/gemm_bf16_K6912.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 64, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K64.xclbin", + "xclbin_bytes": 75118, + "xclbin_sha256": "79ed75cd139c6510a296eb27752bd16e02b7f3670c1cc1b33d086982bc169e77", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K64.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 128, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K128.xclbin", + "xclbin_bytes": 87406, + "xclbin_sha256": "c78300c611ba552f0723681991cb9071e38f09632937d8180667125ae4b740a7", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K128.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 192, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K192.xclbin", + "xclbin_bytes": 67176, + "xclbin_sha256": "84320cd5480206476d6461c90580bb7b436054f9d9d47528ba8f5a698c30a645", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K192.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 256, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K256.xclbin", + "xclbin_bytes": 69996, + "xclbin_sha256": "a93f125eb4d47fc72812f4fea46a1011239a91bf8e1bcabb7f871923c1b3e42c", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K256.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 320, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K320.xclbin", + "xclbin_bytes": 72814, + "xclbin_sha256": "286518b2e71f67cd220092112042fe6b902791ddd6de16c59a56f528b2b4f485", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K320.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 384, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K384.xclbin", + "xclbin_bytes": 75630, + "xclbin_sha256": "2eb4c11c20639c09ec51d45c343315f847da19c7e0b4e0b8a444a50013ae0c9f", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K384.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 448, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K448.xclbin", + "xclbin_bytes": 78446, + "xclbin_sha256": "8185b13d5e984837702f1826880bff09bc0cfb94edcb6b2a9eaba56929217431", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K448.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 512, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K512.xclbin", + "xclbin_bytes": 81262, + "xclbin_sha256": "997933eb5b8ee4d0cbaf02c7191440420aeda56c0710b52803f65e8cba14ddd9", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K512.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 576, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K576.xclbin", + "xclbin_bytes": 84078, + "xclbin_sha256": "999dc70d57fc9a9a75b4d010c5e5b92ac7fa0d57e16683ab50b8c92dec30c559", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K576.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 640, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K640.xclbin", + "xclbin_bytes": 86894, + "xclbin_sha256": "7369aabf82ac1d041a15e98a3e12f715b0686e37813db7075e9090087d36250f", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K640.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 704, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K704.xclbin", + "xclbin_bytes": 89710, + "xclbin_sha256": "76f5c6d29ca5ddeb65c45c51381c69fba5fc4add77137759af05a847ecbbb0c6", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K704.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 768, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K768.xclbin", + "xclbin_bytes": 92526, + "xclbin_sha256": "ea48f04d1dd86eedb41040baf82db7e7246f85d9726a7c2464bc01cab0ba3d51", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K768.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 832, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K832.xclbin", + "xclbin_bytes": 72558, + "xclbin_sha256": "cd258a75f834645722fb0b34a5a0b3613d7cac4146b786780b717009013fcc86", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K832.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 896, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K896.xclbin", + "xclbin_bytes": 66408, + "xclbin_sha256": "416b67d158d0b435986d332000559b313f71752e6c8074ad51822649ef99009e", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K896.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 960, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K960.xclbin", + "xclbin_bytes": 68712, + "xclbin_sha256": "3585d74e25051fd5626e7ffb806e6e867029799487137f3496c158a773b44379", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K960.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1024, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K1024.xclbin", + "xclbin_bytes": 71277, + "xclbin_sha256": "ccd125add8210554cdd61fdda5aa908bc4f8a977f32d0170d357db40e202353a", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K1024.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1088, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K1088.xclbin", + "xclbin_bytes": 72558, + "xclbin_sha256": "9806f58665e9be2b02a0519f684c662391c05508af2f6e6eee7b0c4ca3b0add8", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K1088.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1152, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K1152.xclbin", + "xclbin_bytes": 68712, + "xclbin_sha256": "7890a0de7c0486fa01bb16f3ecbacf4d93f3f3144f40f9da0ae75c064c25a4d4", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K1152.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1216, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K1216.xclbin", + "xclbin_bytes": 72302, + "xclbin_sha256": "2aabca7da9748e0f04725c3f52f7dbfa1cfbdd5c015100584e288df95bb7736e", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K1216.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1280, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K1280.xclbin", + "xclbin_bytes": 71277, + "xclbin_sha256": "abd5429cbb5b217daac9e99209fd9d343e89927299c07356e5e1ee963ad7a11a", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K1280.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1344, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K1344.xclbin", + "xclbin_bytes": 68712, + "xclbin_sha256": "a7f971cfc44be7e9547e2d7bc91e08bb2136d297267876e80d620e9b22564004", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K1344.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1408, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K1408.xclbin", + "xclbin_bytes": 66408, + "xclbin_sha256": "07df015c64abec4ed272c9b4c61b5a276ef1165ef9acb6c9424590c66b341730", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K1408.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1472, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K1472.xclbin", + "xclbin_bytes": 72302, + "xclbin_sha256": "09a4cd9d53d4cbc812920976d49be8ab9793850362ca0c0a95e8617603947eae", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K1472.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1536, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K1536.xclbin", + "xclbin_bytes": 71277, + "xclbin_sha256": "7ace62757304ea913c5a2edb36f1b9aac07d53392fefd9c259f656d58d8df82c", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K1536.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1728, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K1728.xclbin", + "xclbin_bytes": 68712, + "xclbin_sha256": "90f5178fab12b7f9d941b52108e5069d0cad7485bd3445920f8e286c846cf85e", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K1728.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 2304, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K2304.xclbin", + "xclbin_bytes": 71277, + "xclbin_sha256": "d8460ec6e26280e7ecb3df68e80ed84215a3c6284686db65bc4c701c573673d9", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K2304.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 2880, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K2880.xclbin", + "xclbin_bytes": 68712, + "xclbin_sha256": "604ec2a6c214a7d27f3af4a2a784ec71660fdd907cdf48bba02c915593660777", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K2880.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 3456, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K3456.xclbin", + "xclbin_bytes": 68712, + "xclbin_sha256": "37b374a8c6e4a464fca9aa093500dacb5aeaedb8b3849da9ce50f705356a6b28", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K3456.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 4032, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K4032.xclbin", + "xclbin_bytes": 68712, + "xclbin_sha256": "bb4b2db8eff8f17716e4eb83f32512f5efc8c33cbc70453c0f5c6dd5cf37010c", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K4032.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 4608, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K4608.xclbin", + "xclbin_bytes": 71277, + "xclbin_sha256": "8b4183a5274737e87a72b0e83f7e7237153db9ed66eb04f11a1b6e063d804a41", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K4608.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 5184, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K5184.xclbin", + "xclbin_bytes": 68712, + "xclbin_sha256": "8f8960fe592eb4188b69a3cde2816871971b9d381d40dd01913ba5388df1f859", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K5184.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 5760, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K5760.xclbin", + "xclbin_bytes": 68712, + "xclbin_sha256": "9741bb442e0f66a53ed75a936361ee03651170faa71c78b1e355d3e7d6c7518f", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K5760.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 6336, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K6336.xclbin", + "xclbin_bytes": 68712, + "xclbin_sha256": "55dcae8b4b5521089bfe2f11e6a306ffcf4119be8713dfb7c22dd0efa9c97dee", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K6336.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 6912, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_4col/gemm_bf16_K6912.xclbin", + "xclbin_bytes": 71277, + "xclbin_sha256": "691d1aa4684a6d2585dee3b7bec26dfbe4df37a687bcf17031a5e596442d6439", + "insts_golden": "bf16/npu2_4col/gemm_bf16_K6912.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 64, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K64.xclbin", + "xclbin_bytes": 143182, + "xclbin_sha256": "e2494a9ac0f4287c0371c638fdba60f2dfa2c6ef72c7003ac20bf74f5853fffa", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K64.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 128, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K128.xclbin", + "xclbin_bytes": 167758, + "xclbin_sha256": "c8b37dcd46b57a59eea73927abf44245c8520795400e793c4ea2b73ad056262c", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K128.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 192, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K192.xclbin", + "xclbin_bytes": 127310, + "xclbin_sha256": "feb883195184247b3c833dd22a82ba210755fa6ab89d8b96096b23f3e511d5d8", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K192.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 256, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K256.xclbin", + "xclbin_bytes": 132942, + "xclbin_sha256": "6951e0707f4e78f77c4a2aae6bd2d95e7b42ab62d92191489b8f84f954d24104", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K256.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 320, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K320.xclbin", + "xclbin_bytes": 138574, + "xclbin_sha256": "d9d23d5ef87e7d9d3bf1073aa5618017d29f65c1a9a99a461aca04c2d1276f0c", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K320.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 384, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K384.xclbin", + "xclbin_bytes": 144206, + "xclbin_sha256": "8b0f4649cd80280e8545987dd5e6ba8f5e0008bf8a0ca843b0754f6ff1c0da5e", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K384.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 448, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K448.xclbin", + "xclbin_bytes": 149838, + "xclbin_sha256": "8d4845d4479815293fe2e2e85d475f57b48ba4c8cc9a7388f55c90abaff10350", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K448.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 512, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K512.xclbin", + "xclbin_bytes": 155470, + "xclbin_sha256": "d84ea0e15a2a90f9b8f055108736c6c707df0e0ae747ec0677ce093823341fcb", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K512.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 576, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K576.xclbin", + "xclbin_bytes": 161102, + "xclbin_sha256": "03268a8c721b44bc06bc5ceac53908c5bc2373bd394f6a8f8aef5ddd27ad97d2", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K576.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 640, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K640.xclbin", + "xclbin_bytes": 166734, + "xclbin_sha256": "e8ad1bbc35287c85736da2d3129c4c83c9c12a781fb3792d72a38e935ed55891", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K640.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 704, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K704.xclbin", + "xclbin_bytes": 172366, + "xclbin_sha256": "16c3dc40940532cbab463205f40bb636ea0177a1e2dea445cccec2a2fab91f78", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K704.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 768, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K768.xclbin", + "xclbin_bytes": 177998, + "xclbin_sha256": "968cd442ff0fa83a894fb26128f41b9f7698fb7c5be738174863e47c12b69daa", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K768.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 832, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K832.xclbin", + "xclbin_bytes": 138062, + "xclbin_sha256": "187a740d0c9ff85e6b1e0b0bbd826726bd4bfa3bec46f0a35632b3cff40195e6", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K832.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 896, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K896.xclbin", + "xclbin_bytes": 125774, + "xclbin_sha256": "e556b913088f780357c2237b992b8edbb0a40a808890ff965ec4b1f322662eec", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K896.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 960, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K960.xclbin", + "xclbin_bytes": 130382, + "xclbin_sha256": "3a09a4f7cb8f8c666dc4cc9ebb023e71027ac35826ab01c1e1b4326557b57736", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K960.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1024, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K1024.xclbin", + "xclbin_bytes": 135502, + "xclbin_sha256": "da757c3b29dc7a9b027f25c5044f54b668f818b4005b832cc5cbc2dfa915a7d6", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K1024.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1088, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K1088.xclbin", + "xclbin_bytes": 138062, + "xclbin_sha256": "f9094b909f91a6f07d7bea10f7f149c3bf57396bd849ed494a938c4acf65fce9", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K1088.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1152, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K1152.xclbin", + "xclbin_bytes": 130382, + "xclbin_sha256": "cce71962480e758359f1c8638be509e069ca9dd5460ec6fa98efa65024e121f0", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K1152.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1216, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K1216.xclbin", + "xclbin_bytes": 137550, + "xclbin_sha256": "c19665555ec548dd73c5cffc3b336e9638e91d115e1b10f6b2f5dc860b7e0f70", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K1216.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1280, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K1280.xclbin", + "xclbin_bytes": 135502, + "xclbin_sha256": "bddbac9382b2c0d5bf984fa5ba8d01754ca0a670822ce0a2654812be9399e3db", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K1280.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1344, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K1344.xclbin", + "xclbin_bytes": 130382, + "xclbin_sha256": "858b27302210793fbcdbb31fca79a195f3c85dfaa4de9ff19c639fcf39a965ea", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K1344.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1408, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K1408.xclbin", + "xclbin_bytes": 125774, + "xclbin_sha256": "652ac1c37a7b0c5d4119b15b2901600f9f20a328dfaf8f9e47b6242188ca2db8", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K1408.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1472, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K1472.xclbin", + "xclbin_bytes": 137550, + "xclbin_sha256": "aa57283c26a25af1fa4cebfe8df10873b65097cb3c46e8897af47baae0cd059e", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K1472.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1536, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K1536.xclbin", + "xclbin_bytes": 135502, + "xclbin_sha256": "a52d03e5daf406326e717839ba0e16f7ac2cfd774e503d25027d414c1b95ce13", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K1536.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1728, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K1728.xclbin", + "xclbin_bytes": 130382, + "xclbin_sha256": "9f5f7899847e6703af6ae484f9423507770c82513e21451c56463476cc8aca09", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K1728.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 2304, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K2304.xclbin", + "xclbin_bytes": 135502, + "xclbin_sha256": "bcf5f012d20c120cc6d94246f440b56b04a66f64f900a361246236cdd5990df5", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K2304.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 2880, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K2880.xclbin", + "xclbin_bytes": 130382, + "xclbin_sha256": "c7f369c2f8d54c1487a4a28a34709956056b9dda6d0e155415902af412c23dac", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K2880.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 3456, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K3456.xclbin", + "xclbin_bytes": 130382, + "xclbin_sha256": "3aa3c9fff07a4a422de82d8c77018c329e3900b385cd67bce41e384ea502dbd0", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K3456.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 4032, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K4032.xclbin", + "xclbin_bytes": 130382, + "xclbin_sha256": "113018f5babafddb48e33bf270cbcb5db3b9ff444d996564e475ce41aab57763", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K4032.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 4608, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K4608.xclbin", + "xclbin_bytes": 135502, + "xclbin_sha256": "952f906c44520dfeab9f56af71c8da380720a23868c52eda4e91a40eb3421ea2", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K4608.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 5184, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K5184.xclbin", + "xclbin_bytes": 130382, + "xclbin_sha256": "8714b4eeb0f9785549c1d35302d66a872730451aa2409d979a512f5ab042754e", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K5184.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 5760, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K5760.xclbin", + "xclbin_bytes": 130382, + "xclbin_sha256": "6214a18bf25b4e422160ce581536a3fb2d34a3b39c7cb89c0c10ca52234ae6f4", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K5760.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 6336, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K6336.xclbin", + "xclbin_bytes": 130382, + "xclbin_sha256": "3f0ebdae543262421789ad5b1f15dc59049f510b5f9ac68fc927a70223117c05", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K6336.insts.bin" + }, + { + "dtype": "bf16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 6912, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bf16/npu2_8col/gemm_bf16_K6912.xclbin", + "xclbin_bytes": 135502, + "xclbin_sha256": "c2b08fab071deb041f99fc05e95f2f2b6ef4ab7b9c5ec314ca4ff07b297625a7", + "insts_golden": "bf16/npu2_8col/gemm_bf16_K6912.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 64, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K64.xclbin", + "xclbin_bytes": 24072, + "xclbin_sha256": "d1d07825a5634c4d17ff5c391ce954e967017ba9284859a0031671b47a60e377", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K64.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 128, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K128.xclbin", + "xclbin_bytes": 27144, + "xclbin_sha256": "6c8aa165c94a6720043fcc41ae47822b890e78da0a93cb6c71d66a112a3f49fd", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K128.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 192, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K192.xclbin", + "xclbin_bytes": 22088, + "xclbin_sha256": "9fce785b2537dbaff461de54da6a1ee622676c4a3007e54bba3625ecd6b4ee5b", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K192.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 256, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K256.xclbin", + "xclbin_bytes": 22792, + "xclbin_sha256": "fcdd89760327a3dbacaf7a5d30902620aa054dd6fd091236633ae08fd8762f7d", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K256.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 320, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K320.xclbin", + "xclbin_bytes": 23496, + "xclbin_sha256": "938a4b6ff5efc14236674f5c1a5c777877d656a04e36d875f89a2dfc79732596", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K320.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 384, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K384.xclbin", + "xclbin_bytes": 24200, + "xclbin_sha256": "958841a3c6d452f31fbc969b1a14ccea0d6f381eab4f95ed987af2527cf0f31b", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K384.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 448, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K448.xclbin", + "xclbin_bytes": 24904, + "xclbin_sha256": "3c9771118902ecea046cd2f8d1fccf03a6caf33b5b6635b291bf159a731adc45", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K448.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 512, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K512.xclbin", + "xclbin_bytes": 25608, + "xclbin_sha256": "44fcc1d31574c9941c978f3710b0ce9d7e1a6dd92d4c393d2862cd13c8f9225a", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K512.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 576, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K576.xclbin", + "xclbin_bytes": 26312, + "xclbin_sha256": "17337a6311749172875c6e9d5779fbff2075b04b9feab5a7215d28ec2bda7770", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K576.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 640, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K640.xclbin", + "xclbin_bytes": 27016, + "xclbin_sha256": "ce15bce3f8768fb80da470c815bee92d3cb459ef2726a95bc71820b001e9874e", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K640.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 704, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K704.xclbin", + "xclbin_bytes": 27720, + "xclbin_sha256": "3add96796905a3c32a7e5ba212a7616e75decc42d7c15d282f21f73597c66505", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K704.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 768, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K768.xclbin", + "xclbin_bytes": 28424, + "xclbin_sha256": "3647569a6a6b2e0bb6c32f3f24e4ba639f9f4690525a9770af8df02ac409af37", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K768.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 832, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K832.xclbin", + "xclbin_bytes": 23432, + "xclbin_sha256": "755bc99e0d9aafa6e72dc27626bd21ca234396c740f18496d108343a0fc4c85a", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K832.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 896, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K896.xclbin", + "xclbin_bytes": 21896, + "xclbin_sha256": "87ea1c9c21aac198a4e3f00b51ead3bfcc75b2404051770ff7dcc12718d4056c", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K896.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 960, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K960.xclbin", + "xclbin_bytes": 22472, + "xclbin_sha256": "f50ca5b20e5df24510d6b3fc7330d988266c374059210559e71b7b6c05d5d3dc", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K960.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1024, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K1024.xclbin", + "xclbin_bytes": 23112, + "xclbin_sha256": "2728788f56768714823dd7b48eda12a7571f9ddf9c468897e436ac7a3f8dc419", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K1024.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1088, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K1088.xclbin", + "xclbin_bytes": 23432, + "xclbin_sha256": "9a9031de25689824564cc0f30bc42ee34d9ee5245798054483690775f8285f79", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K1088.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1152, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K1152.xclbin", + "xclbin_bytes": 22472, + "xclbin_sha256": "c101c667e4ce88ff2d0f7ad72fdc5cece635d608e85134b2324ce81d61caa03d", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K1152.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1216, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K1216.xclbin", + "xclbin_bytes": 23368, + "xclbin_sha256": "1184bad54724dabee4ca003b0f709a5b7e61a5e6fd41c9a4c876be9798ba4caf", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K1216.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1280, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K1280.xclbin", + "xclbin_bytes": 23112, + "xclbin_sha256": "fbdb12913542cd70fff4dc51f26281488c2afd61ac19f6c0e1a0ba67a5f505d4", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K1280.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1344, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K1344.xclbin", + "xclbin_bytes": 22472, + "xclbin_sha256": "fcc432a33e32b744aae674fe9c50850fc19a43c5f64ca71c8c30efcf947fb860", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K1344.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1408, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K1408.xclbin", + "xclbin_bytes": 21896, + "xclbin_sha256": "ade98b2cf7e758b1f91e94d6f46c2c3e16e1f9e1b946828138f59333a2bcade4", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K1408.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1472, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K1472.xclbin", + "xclbin_bytes": 23368, + "xclbin_sha256": "c205ad292a5edc11963659f481379be338da1eace8d9b378416602a4cd3c2c6c", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K1472.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1536, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K1536.xclbin", + "xclbin_bytes": 23112, + "xclbin_sha256": "eb17eb62c273b87e91cb6e091ccb2211f15c1bc40de94147338ed7b7886009fe", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K1536.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 1728, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K1728.xclbin", + "xclbin_bytes": 22472, + "xclbin_sha256": "accd3dbd800b1dd53e98b4f380a90fbb64ca141d6fdee682dceae3ddfafae744", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K1728.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 2304, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K2304.xclbin", + "xclbin_bytes": 23112, + "xclbin_sha256": "7a3f62314c612228c7f8198abe9847fdc7f1e80a7772e47ce0a9e0402feaff20", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K2304.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 2880, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K2880.xclbin", + "xclbin_bytes": 22472, + "xclbin_sha256": "9055df355135e13a2afeccb5df479d8ff5e313e22bc461e20e12e2bf0a7ab2de", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K2880.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 3456, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K3456.xclbin", + "xclbin_bytes": 22472, + "xclbin_sha256": "10a268e077ef34f8764cb11cb34895fe93efa1f3095949a5bf92039928ea3502", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K3456.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 4032, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K4032.xclbin", + "xclbin_bytes": 22472, + "xclbin_sha256": "db84945621154a4eb06a5bc092c1c2a519dced2dbe0bd5a2a79c2deed2104606", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K4032.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 4608, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K4608.xclbin", + "xclbin_bytes": 23112, + "xclbin_sha256": "65de9a4fc1d67ee75eaf857c798e499b655c5e450654f7148facd38dd5feb23d", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K4608.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 5184, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K5184.xclbin", + "xclbin_bytes": 22472, + "xclbin_sha256": "410141301ecc3593d7abbd6bbfc11790edf1895bb91569a40006d6ba4471f63c", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K5184.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 5760, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K5760.xclbin", + "xclbin_bytes": 22472, + "xclbin_sha256": "2d5d251aff5d2502f7d7ff90e3564fe7e33e164f2cf0ab36da1cab87acb6c570", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K5760.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 6336, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K6336.xclbin", + "xclbin_bytes": 22472, + "xclbin_sha256": "d0582fdc36ffb093bd36a76cca4e7561b9829145ddf111ea5a1b3274ba55244c", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K6336.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 1, + "K": 6912, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_1col/gemm_bf16_K6912.xclbin", + "xclbin_bytes": 23112, + "xclbin_sha256": "ccdb87e23377c92864e11afaefb7988f45e3b35f2f46587fabafea2f67e52e7f", + "insts_golden": "bfp16/npu2_1col/gemm_bf16_K6912.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 64, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K64.xclbin", + "xclbin_bytes": 40408, + "xclbin_sha256": "02c60093212674f55574c12f17dfd85338b03b4222372732de24964d7fcb529b", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K64.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 128, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K128.xclbin", + "xclbin_bytes": 46552, + "xclbin_sha256": "60a58c4fff2f321f04ecad61ccbf5f160e6b62b4ab87308c7f67b0e747a2209b", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K128.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 192, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K192.xclbin", + "xclbin_bytes": 36440, + "xclbin_sha256": "3afb1e417673640b5cfff123546aad909ee13ed9b63822828911f55b789fdfa0", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K192.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 256, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K256.xclbin", + "xclbin_bytes": 37848, + "xclbin_sha256": "d60b15eb3d0dbe7e39d687fbafa40ffe0c891b983c9a05f79a6f5816c832a2ab", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K256.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 320, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K320.xclbin", + "xclbin_bytes": 39256, + "xclbin_sha256": "5580dd4a6bdef4e83450031be47b536cfc9124572b90669d7bd02085db3f90bc", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K320.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 384, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K384.xclbin", + "xclbin_bytes": 40664, + "xclbin_sha256": "fdd7131056501c791a51d17ef28e9f25f4bef5e9eeb2439f91969e6f3911141f", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K384.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 448, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K448.xclbin", + "xclbin_bytes": 42072, + "xclbin_sha256": "59cc28f4cff76955d8aa517aae7b09d684520569ab2f6fe6fd0264ffdae0d854", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K448.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 512, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K512.xclbin", + "xclbin_bytes": 43480, + "xclbin_sha256": "86d3ab7e8144a4c835586ec73813b2955274242a72d2759dfcd7258ae257e542", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K512.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 576, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K576.xclbin", + "xclbin_bytes": 44888, + "xclbin_sha256": "cef09d28fc42ff9e77b67df6fa267ab6aec1eb0127b351c24b42580af0074494", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K576.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 640, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K640.xclbin", + "xclbin_bytes": 46296, + "xclbin_sha256": "b27ec1f20b276f6239e7c48c7315f14ee5417a9c5114b28de0fe5707028b5980", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K640.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 704, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K704.xclbin", + "xclbin_bytes": 47704, + "xclbin_sha256": "76f2c3c277052d44032b88d9a514eb8653938a32e867cde8c68cef0786fe663e", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K704.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 768, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K768.xclbin", + "xclbin_bytes": 49112, + "xclbin_sha256": "a8a8840f67b66ba9fdbcf8cb7a8f277e4ed2148cc27335ebe704a391026edcc2", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K768.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 832, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K832.xclbin", + "xclbin_bytes": 39128, + "xclbin_sha256": "2dd283d80d847bf5f1d87da4f09dae2200aada3af2f7e83a558fed3b2a628d3b", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K832.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 896, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K896.xclbin", + "xclbin_bytes": 36056, + "xclbin_sha256": "68951377cb1d842b07bd0f5de858db6b3f185897b180d551404dfac5e4e93152", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K896.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 960, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K960.xclbin", + "xclbin_bytes": 37208, + "xclbin_sha256": "1e7af2879091caed4338ad7605dabfa7fa9cc90c53f342a63f5e5262ece9102d", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K960.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1024, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K1024.xclbin", + "xclbin_bytes": 38488, + "xclbin_sha256": "d34d034096f72584fd613a22e59a6011d6af0b5b909cf4c565dbb7a7def23f81", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K1024.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1088, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K1088.xclbin", + "xclbin_bytes": 39128, + "xclbin_sha256": "49f40b1289e938377f4944b46192a643c0dafc99336fbf4abd7450a63026136b", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K1088.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1152, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K1152.xclbin", + "xclbin_bytes": 37208, + "xclbin_sha256": "5e07efe8f3ef6d4b48142bad27ed85873fd22b43a4d852e59f73836b6d847a34", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K1152.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1216, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K1216.xclbin", + "xclbin_bytes": 39000, + "xclbin_sha256": "e7fcbc21a3815406de047e5e16723fa6cf8a3c8627e400c57445472bf26fd74e", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K1216.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1280, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K1280.xclbin", + "xclbin_bytes": 38488, + "xclbin_sha256": "02cca9bae9b3b9f15821f04f8f79b2477cfda83003d433199725bb47d54223a3", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K1280.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1344, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K1344.xclbin", + "xclbin_bytes": 37208, + "xclbin_sha256": "007c4760fcc7bcd918fe2aa1c6e8a108dbe78b620acc337451a7b8b8b799d8c7", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K1344.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1408, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K1408.xclbin", + "xclbin_bytes": 36056, + "xclbin_sha256": "d26fefb8ce6f53eb136988efc73ba0b98e1a7f27da86ac1bc936caf9954f2ba6", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K1408.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1472, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K1472.xclbin", + "xclbin_bytes": 39000, + "xclbin_sha256": "37d739e791f2f1bc4d2dc0776ede5bddfdb42c5f04bf5b477ff6387e370b5a07", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K1472.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1536, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K1536.xclbin", + "xclbin_bytes": 38488, + "xclbin_sha256": "890a20e2dcd4e08b8dedc2b6dc8ed5216c12654d7dcf9321b449b65a7541b026", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K1536.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 1728, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K1728.xclbin", + "xclbin_bytes": 37208, + "xclbin_sha256": "c1d59385f0a745f5f46fa226e31f5bf0cf952cf450098cc9b4a81e7df851a292", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K1728.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 2304, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K2304.xclbin", + "xclbin_bytes": 38488, + "xclbin_sha256": "627f6f569e88cc63cdfc42802a13bccc353785336bafae00d468aa64e5fbc284", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K2304.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 2880, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K2880.xclbin", + "xclbin_bytes": 37208, + "xclbin_sha256": "ae14438dc9c5a1e39025b15f2c7710253164c4e6655d8138a6ec82952a6c29eb", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K2880.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 3456, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K3456.xclbin", + "xclbin_bytes": 37208, + "xclbin_sha256": "08577e771a2d672de3164c0ae8db73affae5be5d50faf06c81b2f34ae7f87452", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K3456.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 4032, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K4032.xclbin", + "xclbin_bytes": 37208, + "xclbin_sha256": "ac8e6f2ff145dff08f8dc5d1c5d29c24c653729cde2327576eb829fd0d6803d5", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K4032.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 4608, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K4608.xclbin", + "xclbin_bytes": 38488, + "xclbin_sha256": "9dba6a1c509f719f48d6d14fc687bb5361260f51e2548af6ae663ce2f00d3ffc", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K4608.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 5184, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K5184.xclbin", + "xclbin_bytes": 37208, + "xclbin_sha256": "2a2a7e4463b4056693204c344142f32b9ed7761691cf49f35aa54627f36837fd", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K5184.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 5760, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K5760.xclbin", + "xclbin_bytes": 37208, + "xclbin_sha256": "d3e6012696f7521f7c30b6f85305d43d0f3018cea6e65317960d0410ff8ab37f", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K5760.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 6336, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K6336.xclbin", + "xclbin_bytes": 37208, + "xclbin_sha256": "9e775c0e8b989e7b3442dbcb04dea8c319a5310407625d02c49707e2cbe10ecd", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K6336.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 2, + "K": 6912, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_2col/gemm_bf16_K6912.xclbin", + "xclbin_bytes": 38488, + "xclbin_sha256": "e6c6bceb3389776f49cae4f8655c20ef00d4a418494015c63da25507919e4166", + "insts_golden": "bfp16/npu2_2col/gemm_bf16_K6912.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 64, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K64.xclbin", + "xclbin_bytes": 73326, + "xclbin_sha256": "e819628fd9c26a5565bc71d448f549981ea5c6564fa9f1ff4f64b1bba1ba1aaa", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K64.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 128, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K128.xclbin", + "xclbin_bytes": 85614, + "xclbin_sha256": "a10a927edb41ee27a123986f40f5fe32b4de8556f567317b13710bf0060646c9", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K128.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 192, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K192.xclbin", + "xclbin_bytes": 65384, + "xclbin_sha256": "961b9722c18b488fc18ba1934bd4cbaa0c885c3110e3d7a45ea5f05f6c2f3f1c", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K192.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 256, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K256.xclbin", + "xclbin_bytes": 68200, + "xclbin_sha256": "be22adfde4a3cf2f8fe3c3d0fafde7bd3cdcd1f9ecf5bfe34a894b4c3fbfee13", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K256.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 320, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K320.xclbin", + "xclbin_bytes": 71021, + "xclbin_sha256": "01f1c40ec38fa51892389859165be2e5af2913b290aad9da1c3723bf4a5256d3", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K320.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 384, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K384.xclbin", + "xclbin_bytes": 73838, + "xclbin_sha256": "1f26b37b0f2d53c212ee855daecf70c7e348dc45dc4e06a67607f9c36b24f206", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K384.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 448, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K448.xclbin", + "xclbin_bytes": 76654, + "xclbin_sha256": "1b6cfc4668f57f17d4333a1d535cfc0013f611c0fecf7617376c9779201c4333", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K448.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 512, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K512.xclbin", + "xclbin_bytes": 79470, + "xclbin_sha256": "a202a1fd78737020bcd939fc221cbaf281a96f0cc6967db52b52d846f15be87e", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K512.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 576, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K576.xclbin", + "xclbin_bytes": 82286, + "xclbin_sha256": "bed5dbce60fb1b98d73d882ea8551c3543f9666484007fed103f30b68b34e4be", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K576.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 640, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K640.xclbin", + "xclbin_bytes": 85102, + "xclbin_sha256": "ce01c70e311ed3b780ec61b3b95e8cca0dbc2d643b515ca464de193aae586c67", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K640.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 704, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K704.xclbin", + "xclbin_bytes": 87918, + "xclbin_sha256": "1ffd95b5f7e44c2ba2b69924ffa6f072291baea974f580016cb74ffc6354d36a", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K704.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 768, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K768.xclbin", + "xclbin_bytes": 90734, + "xclbin_sha256": "1d16bb804bb64d864f8d5e030b6e465d1f465aea36b1a289be7f958a3df6b081", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K768.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 832, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K832.xclbin", + "xclbin_bytes": 70765, + "xclbin_sha256": "69eb90b890db50603199feffea62ab01313d4885756da0cc498b730e5d066f0b", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K832.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 896, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K896.xclbin", + "xclbin_bytes": 64616, + "xclbin_sha256": "a54d6630942977d1a1f07c7c616ee6882fa3b63c0741c234fd8045a74aaeb8d9", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K896.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 960, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K960.xclbin", + "xclbin_bytes": 66920, + "xclbin_sha256": "917dce7623f484e3036b8663f78943c54ba36df3884141a3d68d8bc98708e9a6", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K960.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1024, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K1024.xclbin", + "xclbin_bytes": 69484, + "xclbin_sha256": "6177618da825fdd1dd228fc75bc45943bc4f8ef96b7118dd0a3b77167ac7b315", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K1024.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1088, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K1088.xclbin", + "xclbin_bytes": 70765, + "xclbin_sha256": "58221bc28ac714e714bfaa8d24f78a62f16aa64ecab838494bf3ff343afd8d35", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K1088.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1152, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K1152.xclbin", + "xclbin_bytes": 66920, + "xclbin_sha256": "0f61410e90b8f51191afa18adfbfaf79d78cab367142d5e27d9265fd06dde50f", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K1152.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1216, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K1216.xclbin", + "xclbin_bytes": 70508, + "xclbin_sha256": "977cb054bb985c9cebe960889bcad5afc290c0ef41717c08e486400a4a673e41", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K1216.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1280, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K1280.xclbin", + "xclbin_bytes": 69484, + "xclbin_sha256": "a109377f0552449f7c81ae9303593145ff8d61396a5948acc4762a8e6d94e9ec", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K1280.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1344, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K1344.xclbin", + "xclbin_bytes": 66920, + "xclbin_sha256": "2227922cbffee3e5afed5fdfe189d709520da1d8ca7f4f033eb12ebdf1724f51", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K1344.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1408, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K1408.xclbin", + "xclbin_bytes": 64616, + "xclbin_sha256": "fd3109a9b8ba6d7132fe44fcbe6a8e86fe2cac57aef86d8f5108536a98fda91a", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K1408.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1472, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K1472.xclbin", + "xclbin_bytes": 70508, + "xclbin_sha256": "57c9bf4358005911864e81800f80dad73fab479a69dcc6a6280d8fe3d21ea1db", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K1472.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1536, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K1536.xclbin", + "xclbin_bytes": 69484, + "xclbin_sha256": "ab95dd844d12354f07e4661db4d2851d51b9bbefd38c74bb79b9b8f0e199941e", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K1536.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 1728, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K1728.xclbin", + "xclbin_bytes": 66920, + "xclbin_sha256": "e40d30a59ade6e6fac5eefb9c8126f47b5b5a65fade7bd35717be5870ece2320", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K1728.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 2304, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K2304.xclbin", + "xclbin_bytes": 69484, + "xclbin_sha256": "c500a5f2393fc48ed7cb84ec53f695eae893cbb72247c07c08186ae08a40b898", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K2304.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 2880, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K2880.xclbin", + "xclbin_bytes": 66920, + "xclbin_sha256": "76d4daadfe6a0848385bdff242aa3c7fb383b9e75b9837aa4485901aca1c2ddc", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K2880.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 3456, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K3456.xclbin", + "xclbin_bytes": 66920, + "xclbin_sha256": "7eaf9c23477614a670234bc4b93cb0923ef58a8d5cab3a612183bc5b4e8a0f19", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K3456.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 4032, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K4032.xclbin", + "xclbin_bytes": 66920, + "xclbin_sha256": "f3ec382d6a480c344af37544961eb67ee7c674420bf00e9c3a0d5c9a794856b4", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K4032.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 4608, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K4608.xclbin", + "xclbin_bytes": 69484, + "xclbin_sha256": "05305863cf8c52704deff169b96956626538311605c23dd58e438c79f1cacdcf", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K4608.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 5184, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K5184.xclbin", + "xclbin_bytes": 66920, + "xclbin_sha256": "bb714eefdd789fc427f395ecca0c29efb50cc7ddb13df89ee78f944db91b4602", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K5184.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 5760, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K5760.xclbin", + "xclbin_bytes": 66920, + "xclbin_sha256": "a064bac7accd69565f16e176738b7e9b6175300b5bf202358d0a06fe39499efb", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K5760.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 6336, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K6336.xclbin", + "xclbin_bytes": 66920, + "xclbin_sha256": "2c6a36192781aaa2d5c111ccd1b3d5dd7d6894eab5e76fd56e3cfc8f11e8305d", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K6336.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 4, + "K": 6912, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_4col/gemm_bf16_K6912.xclbin", + "xclbin_bytes": 69484, + "xclbin_sha256": "4c31467c43a633a2b46c86ec696f3da70193e2f3ddb0dd3cc28e67e14115ba29", + "insts_golden": "bfp16/npu2_4col/gemm_bf16_K6912.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 64, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K64.xclbin", + "xclbin_bytes": 139598, + "xclbin_sha256": "1bd01d897e944442a1f786d0e2f45c266b86daa36fc85dc0b857553dfc2ee446", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K64.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 128, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K128.xclbin", + "xclbin_bytes": 164174, + "xclbin_sha256": "ef6ff050b6861792b071d9d43243ad28414ce3645ce9abf5792a36abf238079e", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K128.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 192, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K192.xclbin", + "xclbin_bytes": 123726, + "xclbin_sha256": "8ccb6299dbc40bf9ee957eac738becfcbf8cb54b1373d54b4c516f5edcbe1197", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K192.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 256, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K256.xclbin", + "xclbin_bytes": 129358, + "xclbin_sha256": "8456c5495e23e97424f92a8a844a77337120020135055af6bf6d849d0198e7aa", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K256.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 320, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K320.xclbin", + "xclbin_bytes": 134990, + "xclbin_sha256": "5948a5d6c55ae1b4add12ed4d586187b25f39c69c0c765120d3ae79f610dee3a", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K320.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 384, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K384.xclbin", + "xclbin_bytes": 140622, + "xclbin_sha256": "95692d6313f0c5ff18e4349c730035c53a13cadd6428652079883f917495994e", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K384.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 448, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K448.xclbin", + "xclbin_bytes": 146254, + "xclbin_sha256": "b66ce2192335ec5e7b8457d291ce41ee0d21680f1c73c655f0bc002827e1a8cb", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K448.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 512, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K512.xclbin", + "xclbin_bytes": 151886, + "xclbin_sha256": "02aa5976c23dcca376cd98031e4aff4a2bc40d3f52ffd1586215a82e4e67d865", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K512.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 576, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K576.xclbin", + "xclbin_bytes": 157518, + "xclbin_sha256": "c4a390f9ed65c90e798bf34e8ba42d543b0a7fbfad854bab272f41d63ef31744", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K576.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 640, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K640.xclbin", + "xclbin_bytes": 163150, + "xclbin_sha256": "58931746df02710ca37f5df8233a19bd3de2c00da4e3dbe1c957484ea57e7ca1", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K640.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 704, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K704.xclbin", + "xclbin_bytes": 168782, + "xclbin_sha256": "ac2078220a88aba00da4e8d5bd8a7689862baf426aa8aa1d9ae009e38590eadb", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K704.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 768, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K768.xclbin", + "xclbin_bytes": 174414, + "xclbin_sha256": "3f7157cc3c43d368805eff95b8e759dbfba060ef5a8fbf68bc6bf01c33b59b83", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K768.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 832, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K832.xclbin", + "xclbin_bytes": 134478, + "xclbin_sha256": "5b70104afee64fe26d33cb0a5c78ac9d118bb96905351496fe38df8c2fb619d1", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K832.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 896, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K896.xclbin", + "xclbin_bytes": 122190, + "xclbin_sha256": "fa4891601074638b98d7a2af867861b68271c3e5ab8f2b630302b3835faa3839", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K896.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 960, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K960.xclbin", + "xclbin_bytes": 126798, + "xclbin_sha256": "3f011c299e2d512500cd465b497b3d0316565842b26f6d3e1eafbceb77daa3d6", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K960.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1024, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K1024.xclbin", + "xclbin_bytes": 131918, + "xclbin_sha256": "c57aa38b1245dc331962dd7dfc1d1c4babdb740eb023581a861dbf10a919109f", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K1024.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1088, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K1088.xclbin", + "xclbin_bytes": 134478, + "xclbin_sha256": "556cb0a47e9ffeda26a982ce511602dc529084a24607c4b19ed74a6f83b5e77e", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K1088.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1152, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K1152.xclbin", + "xclbin_bytes": 126798, + "xclbin_sha256": "9c628a99f5eb15cace83610eb84a31dcc0e9bdb83dfbae2b80df56c98849a918", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K1152.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1216, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K1216.xclbin", + "xclbin_bytes": 133966, + "xclbin_sha256": "9ec5ec561ff9036cca86b0293276842e8ca439b418ec7577de8fbe81bd18457f", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K1216.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1280, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K1280.xclbin", + "xclbin_bytes": 131918, + "xclbin_sha256": "282c5a6bc70c69a0c436d6a272427b8e43ce490f75e2da26f49d3f226524ee40", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K1280.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1344, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K1344.xclbin", + "xclbin_bytes": 126798, + "xclbin_sha256": "b2c9440ab12f508e501881ec2a5d1daf0aaad95c92b8d44522d610d466fde32e", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K1344.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1408, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K1408.xclbin", + "xclbin_bytes": 122190, + "xclbin_sha256": "cb48d7e0331a95fb56f3c456ac71dd94dab389d0e39d718eb90fad00c193aa06", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K1408.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1472, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K1472.xclbin", + "xclbin_bytes": 133966, + "xclbin_sha256": "fe17d33ca2fbf1500d9f0a3cd43929d21aba1acf7956cd384b0c8462e0b332a7", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K1472.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1536, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K1536.xclbin", + "xclbin_bytes": 131918, + "xclbin_sha256": "8573fd92a2e8ec244eb1e1c222c8d44f68218c83a44fcb3806ee52707bbde099", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K1536.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 1728, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K1728.xclbin", + "xclbin_bytes": 126798, + "xclbin_sha256": "360ad0d2f8dc4cb7b4c2e063c8adfcd1cdb2b854d3c1336bf8fb60c2d47785ab", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K1728.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 2304, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K2304.xclbin", + "xclbin_bytes": 131918, + "xclbin_sha256": "b91f6f975e9e57a497f960e99c488577058648103906b4a07bf38c74af7ebe91", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K2304.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 2880, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K2880.xclbin", + "xclbin_bytes": 126798, + "xclbin_sha256": "f0a2dbc010168d29e19dbe6741de6be0604fd0b142cc3fa0b517541462ed38c6", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K2880.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 3456, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K3456.xclbin", + "xclbin_bytes": 126798, + "xclbin_sha256": "31f09dc17e003c01185862946ba0fcb57c2aedf6d6ca4bb1f86bc2448e948d0a", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K3456.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 4032, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K4032.xclbin", + "xclbin_bytes": 126798, + "xclbin_sha256": "ee895895fb295052dab9538deac03aede03fb6a85525d172455e2f861318cd4b", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K4032.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 4608, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K4608.xclbin", + "xclbin_bytes": 131918, + "xclbin_sha256": "93168c53a58ea02c9a1ea27d3020918aeb80be750ce10d29581e2b13f9a15505", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K4608.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 5184, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K5184.xclbin", + "xclbin_bytes": 126798, + "xclbin_sha256": "c2fe1daa1838285d3487a36c180577e27fa9f617d6d84e29c6893b7366e774ea", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K5184.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 5760, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K5760.xclbin", + "xclbin_bytes": 126798, + "xclbin_sha256": "207ff29c827a7109c122385c93785d92b1d869faf7de806ca7c859aa5387e89d", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K5760.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 6336, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K6336.xclbin", + "xclbin_bytes": 126798, + "xclbin_sha256": "beddce21342623ec8b88c31f6890dfca9165b72b3033f65e3487c2f0f17f0b0a", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K6336.insts.bin" + }, + { + "dtype": "bfp16", + "arch": "npu2", + "n_aie_cols": 8, + "K": 6912, + "compiled_at": null, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "xclbin": "bfp16/npu2_8col/gemm_bf16_K6912.xclbin", + "xclbin_bytes": 131918, + "xclbin_sha256": "500adfc65f86f4b607bbef5c276d5ea6ed2e048a8b4e7797cfed2244a4ba03f8", + "insts_golden": "bfp16/npu2_8col/gemm_bf16_K6912.insts.bin" + } + ] +} \ No newline at end of file diff --git a/cpp/external/ryzenai_artifacts/manifest.json b/cpp/external/ryzenai_artifacts/manifest.json new file mode 100644 index 000000000..4e0328538 --- /dev/null +++ b/cpp/external/ryzenai_artifacts/manifest.json @@ -0,0 +1,894 @@ +{ + "manifest_version": 1, + "generated_by": "cpp/neuralnet/ryzenai/kernels/build_kernels.py", + "generated_at": "2026-08-13T02:43:20+00:00", + "design": { + "template": "mlir-aie programming_examples/basic/matrix_multiplication/whole_array", + "gemm": "bf16 x bf16 -> fp32 (fp32 accumulate), row-major A/B/C host buffers", + "bfp16_note": "dtype=bfp16 uses AIE2P BFP16-emulated bf16 MMUL (mac_dims (8,8,8)); same host ABI as bf16", + "n_aie_rows": 4, + "lookup": "artifacts[] by (arch, dtype, n_aie_cols, M, K, N)" + }, + "abi": { + "kernel_name": "MLIR_AIE", + "arg_slots": [ + { + "slot": 0, + "name": "opcode", + "kind": "scalar", + "value": 3, + "note": "ERT start-kernel-with-instruction-buffer opcode; pass as a 32-bit scalar (xclbin metadata declares uint64, only the low 32 bits are used)" + }, + { + "slot": 1, + "name": "instr", + "kind": "bo", + "flags": "XCL_BO_FLAGS_CACHEABLE", + "group_id": "kernel.group_id(1)", + "content": "raw bytes of the .insts.bin file" + }, + { + "slot": 2, + "name": "n_instr", + "kind": "scalar", + "unit": "uint32_words", + "note": "official mlir-aie C++ harness passes the word count (insts_bytes / 4); the Python iron runtime passes the byte count. Both were verified to run correctly on XRT 2.21 / Strix (the TXN control code self-describes its length). Use the word count for consistency with the C++ harness." + }, + { + "slot": 3, + "name": "A", + "kind": "bo", + "flags": "XRT_BO_FLAGS_HOST_ONLY", + "group_id": "kernel.group_id(3)" + }, + { + "slot": 4, + "name": "B", + "kind": "bo", + "flags": "XRT_BO_FLAGS_HOST_ONLY", + "group_id": "kernel.group_id(4)" + }, + { + "slot": 5, + "name": "C", + "kind": "bo", + "flags": "XRT_BO_FLAGS_HOST_ONLY", + "group_id": "kernel.group_id(5)" + } + ], + "data_arg_order": [ + "A", + "B", + "C" + ], + "declared_bo_slots": 5, + "declared_bo_slots_note": "the xclbin declares 5 data BO slots (bo0..bo4, kernel args 3..7); this design uses the first 3. Never pass more than 5 data BOs.", + "group_id_note": "group_id values are assigned by XRT at load time; always query kernel.group_id(n) at runtime, never hardcode the observed numbers.", + "data_layout": { + "A": "M x K bfloat16, plain row-major contiguous (row stride = K elements), 2 bytes little-endian per element, no tiling or packing in the host buffer", + "B": "K x N bfloat16, plain row-major contiguous (row stride = N elements), 2 bytes little-endian per element, no tiling or packing in the host buffer", + "C": "M x N float32, plain row-major contiguous (row stride = N elements), written by the NPU, no tiling or packing in the host buffer", + "note": "all (r,s,t) sub-tile reordering required by the MMUL intrinsic is performed on-chip by the shim/memtile/core DMAs; the host buffers stay plain row-major" + }, + "sync": "sync instr + A + B + C XCL_BO_SYNC_BO_TO_DEVICE after filling them (C sync is only needed if the host wrote to it); sync C XCL_BO_SYNC_BO_FROM_DEVICE after run.wait()", + "dispatch_cpp": "xrt::device dev(0); auto x = xrt::xclbin(xclbin_path); dev.register_xclbin(x); xrt::hw_context ctx(dev, x.get_uuid()); xrt::kernel k(ctx, \"MLIR_AIE\"); xrt::bo instr(dev, insts_bytes, XCL_BO_FLAGS_CACHEABLE, k.group_id(1)); xrt::bo a(dev, M*K*2, XRT_BO_FLAGS_HOST_ONLY, k.group_id(3)); xrt::bo b(dev, K*N*2, XRT_BO_FLAGS_HOST_ONLY, k.group_id(4)); xrt::bo c(dev, M*N*4, XRT_BO_FLAGS_HOST_ONLY, k.group_id(5)); xrt::run r(k); r.set_arg(0, 3); r.set_arg(1, instr); r.set_arg(2, insts_bytes/4); r.set_arg(3, a); r.set_arg(4, b); r.set_arg(5, c); r.start(); r.wait();" + }, + "artifacts": [ + { + "xclbin": "bf16/npu1_4col/gemm_bf16_M512K384N384.xclbin", + "insts": "bf16/npu1_4col/gemm_bf16_M512K384N384.insts.bin", + "arch": "npu1", + "dtype": "bf16", + "n_aie_cols": 4, + "M": 512, + "K": 384, + "N": 384, + "tile": { + "m": 32, + "k": 64, + "n": 48 + }, + "mac_dims": [ + 4, + 8, + 4 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 1292, + "xclbin_bytes": 80926, + "xclbin_sha256": "09253c368a044ac44d5ee1776956ea5456d0753ebd1104cf72fed909b59d2166", + "insts_bytes": 5168, + "insts_sha256": "6ee5b46c5c3093571a731d70608455fb3c3009b2830c005cfe37c1f383ed3697", + "bo_sizes_bytes": { + "A": 393216, + "B": 294912, + "C": 786432 + }, + "hardware_verified": false, + "compile_seconds": 11.7 + }, + { + "xclbin": "bf16/npu1_4col/gemm_bf16_M512K512N512.xclbin", + "insts": "bf16/npu1_4col/gemm_bf16_M512K512N512.insts.bin", + "arch": "npu1", + "dtype": "bf16", + "n_aie_cols": 4, + "M": 512, + "K": 512, + "N": 512, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 4, + 8, + 4 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 1292, + "xclbin_bytes": 75294, + "xclbin_sha256": "2355c501070130d288f573306c401e409a833954d845cb557a1a5907e74fbc34", + "insts_bytes": 5168, + "insts_sha256": "e8eba035c40cf34dccbad9b9308b618e15809c6575ad813940377d7ea9ca10e2", + "bo_sizes_bytes": { + "A": 524288, + "B": 524288, + "C": 1048576 + }, + "hardware_verified": false, + "compile_seconds": 10.0 + }, + { + "xclbin": "bf16/npu1_4col/gemm_bf16_M512K768N768.xclbin", + "insts": "bf16/npu1_4col/gemm_bf16_M512K768N768.insts.bin", + "arch": "npu1", + "dtype": "bf16", + "n_aie_cols": 4, + "M": 512, + "K": 768, + "N": 768, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 4, + 8, + 4 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 1292, + "xclbin_bytes": 75294, + "xclbin_sha256": "d5927c3ee36767b7967ef33ebb592195786fea05f29cc148828cdb1873dce77b", + "insts_bytes": 5168, + "insts_sha256": "0ec974baa93d488a7616563445a8da5863370ac03ce3206328b736ea8a7c7626", + "bo_sizes_bytes": { + "A": 786432, + "B": 1179648, + "C": 1572864 + }, + "hardware_verified": false, + "compile_seconds": 9.9 + }, + { + "xclbin": "bf16/npu1_1col/gemm_bf16_M512K384N384.xclbin", + "insts": "bf16/npu1_1col/gemm_bf16_M512K384N384.insts.bin", + "arch": "npu1", + "dtype": "bf16", + "n_aie_cols": 1, + "M": 512, + "K": 384, + "N": 384, + "tile": { + "m": 32, + "k": 64, + "n": 48 + }, + "mac_dims": [ + 4, + 8, + 4 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 326, + "xclbin_bytes": 25992, + "xclbin_sha256": "5877ac0160d710727cfa784c134937dce32505fb8e23a5d4917f9fbef74263f5", + "insts_bytes": 1304, + "insts_sha256": "2ebffa614ea2feb73cb68f41f15d9af2fb2aa9cf9571551fd8a0d205c5955a16", + "bo_sizes_bytes": { + "A": 393216, + "B": 294912, + "C": 786432 + }, + "hardware_verified": false, + "compile_seconds": 6.9 + }, + { + "xclbin": "bf16/npu1_1col/gemm_bf16_M512K512N512.xclbin", + "insts": "bf16/npu1_1col/gemm_bf16_M512K512N512.insts.bin", + "arch": "npu1", + "dtype": "bf16", + "n_aie_cols": 1, + "M": 512, + "K": 512, + "N": 512, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 4, + 8, + 4 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 326, + "xclbin_bytes": 24584, + "xclbin_sha256": "ecc71a1a490366bac779a9ad7a70a0cdadad608a7cf9998987ad77282e93a1e9", + "insts_bytes": 1304, + "insts_sha256": "dcff95ae97b99ee11f823f30dd3631e05a62a78fe300ff9127386aa45c78caed", + "bo_sizes_bytes": { + "A": 524288, + "B": 524288, + "C": 1048576 + }, + "hardware_verified": false, + "compile_seconds": 7.7 + }, + { + "xclbin": "bf16/npu1_1col/gemm_bf16_M512K768N768.xclbin", + "insts": "bf16/npu1_1col/gemm_bf16_M512K768N768.insts.bin", + "arch": "npu1", + "dtype": "bf16", + "n_aie_cols": 1, + "M": 512, + "K": 768, + "N": 768, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 4, + 8, + 4 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 326, + "xclbin_bytes": 24584, + "xclbin_sha256": "26ab701bb20d6cc48887eeafd30bfea4779eb7b3c5ad30515fd9e2ccb08d11e5", + "insts_bytes": 1304, + "insts_sha256": "69d9ddceeebaec17d92a1766008b67377463a215a67be514dadc93b0efb3cbca", + "bo_sizes_bytes": { + "A": 786432, + "B": 1179648, + "C": 1572864 + }, + "hardware_verified": false, + "compile_seconds": 7.0 + }, + { + "xclbin": "bf16/npu2_8col/gemm_bf16_M512K384N384.xclbin", + "insts": "bf16/npu2_8col/gemm_bf16_M512K384N384.insts.bin", + "arch": "npu2", + "dtype": "bf16", + "n_aie_cols": 8, + "M": 512, + "K": 384, + "N": 384, + "tile": { + "m": 32, + "k": 64, + "n": 48 + }, + "mac_dims": [ + 4, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 2100, + "xclbin_bytes": 145230, + "xclbin_sha256": "fac999294a6d1daa779e3c8315655bfe6317e44352604c22143eb2332d5b7f90", + "insts_bytes": 8400, + "insts_sha256": "274294c4864594591c01afa7fb5794ad66fe4df6e7db17b6322e72994201846f", + "bo_sizes_bytes": { + "A": 393216, + "B": 294912, + "C": 786432 + }, + "hardware_verified": true, + "compile_seconds": 32.4 + }, + { + "xclbin": "bf16/npu2_8col/gemm_bf16_M512K512N512.xclbin", + "insts": "bf16/npu2_8col/gemm_bf16_M512K512N512.insts.bin", + "arch": "npu2", + "dtype": "bf16", + "n_aie_cols": 8, + "M": 512, + "K": 512, + "N": 512, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 4, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 2100, + "xclbin_bytes": 155470, + "xclbin_sha256": "fe38a588635df848f7e427736e6b57d24f8e19ed1700fc7100cb02e48e45e2bb", + "insts_bytes": 8400, + "insts_sha256": "08d5727f5f47de1315af95c8a2f30e96787608d4576ddbb2663b60eee3b1aac3", + "bo_sizes_bytes": { + "A": 524288, + "B": 524288, + "C": 1048576 + }, + "hardware_verified": true, + "compile_seconds": 36.0 + }, + { + "xclbin": "bf16/npu2_8col/gemm_bf16_M512K768N768.xclbin", + "insts": "bf16/npu2_8col/gemm_bf16_M512K768N768.insts.bin", + "arch": "npu2", + "dtype": "bf16", + "n_aie_cols": 8, + "M": 512, + "K": 768, + "N": 768, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 4, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 2100, + "xclbin_bytes": 177998, + "xclbin_sha256": "ca6f9ab1edb8960cc1973aeefe1a72db06256f8e18dca3512b0a73ab275c934d", + "insts_bytes": 8400, + "insts_sha256": "e8614292674a4946074446354f86aff268ff9bec581dd8cd04441b1ad68f16ab", + "bo_sizes_bytes": { + "A": 786432, + "B": 1179648, + "C": 1572864 + }, + "hardware_verified": true, + "compile_seconds": 39.9 + }, + { + "xclbin": "bf16/npu2_4col/gemm_bf16_M512K384N384.xclbin", + "insts": "bf16/npu2_4col/gemm_bf16_M512K384N384.insts.bin", + "arch": "npu2", + "dtype": "bf16", + "n_aie_cols": 4, + "M": 512, + "K": 384, + "N": 384, + "tile": { + "m": 32, + "k": 64, + "n": 48 + }, + "mac_dims": [ + 4, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 1292, + "xclbin_bytes": 76142, + "xclbin_sha256": "fbdb691f2b846213dc8341e92cd635043157f70ea7c3425cc866c4767c7d407a", + "insts_bytes": 5168, + "insts_sha256": "77aa4246090925aa8a8580dcbe702f636d059806886b6ccc07f594290e75d8db", + "bo_sizes_bytes": { + "A": 393216, + "B": 294912, + "C": 786432 + }, + "hardware_verified": true, + "compile_seconds": 24.5 + }, + { + "xclbin": "bf16/npu2_4col/gemm_bf16_M512K512N512.xclbin", + "insts": "bf16/npu2_4col/gemm_bf16_M512K512N512.insts.bin", + "arch": "npu2", + "dtype": "bf16", + "n_aie_cols": 4, + "M": 512, + "K": 512, + "N": 512, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 4, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 1292, + "xclbin_bytes": 81262, + "xclbin_sha256": "da7b65ac807c2a5883d376b035cb113548fba3ae20f256d04848568e83f4c0a9", + "insts_bytes": 5168, + "insts_sha256": "e8f42bb5b265fb51d50191844250afe8321ea7d2b735986fd882e62de8bcdea4", + "bo_sizes_bytes": { + "A": 524288, + "B": 524288, + "C": 1048576 + }, + "hardware_verified": true, + "compile_seconds": 20.5 + }, + { + "xclbin": "bf16/npu2_4col/gemm_bf16_M512K768N768.xclbin", + "insts": "bf16/npu2_4col/gemm_bf16_M512K768N768.insts.bin", + "arch": "npu2", + "dtype": "bf16", + "n_aie_cols": 4, + "M": 512, + "K": 768, + "N": 768, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 4, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 1292, + "xclbin_bytes": 92526, + "xclbin_sha256": "d45773b5755dd9359a96096225f97e104ff8cc8f14ebcb8d200f2144ec88126e", + "insts_bytes": 5168, + "insts_sha256": "a5288db6688002b9b32f169e15ae32c473e1f05fa6090ba7764ebc87b0306118", + "bo_sizes_bytes": { + "A": 786432, + "B": 1179648, + "C": 1572864 + }, + "hardware_verified": true, + "compile_seconds": 23.3 + }, + { + "xclbin": "bf16/npu2_1col/gemm_bf16_M512K384N384.xclbin", + "insts": "bf16/npu2_1col/gemm_bf16_M512K384N384.insts.bin", + "arch": "npu2", + "dtype": "bf16", + "n_aie_cols": 1, + "M": 512, + "K": 384, + "N": 384, + "tile": { + "m": 32, + "k": 64, + "n": 48 + }, + "mac_dims": [ + 4, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 326, + "xclbin_bytes": 24776, + "xclbin_sha256": "b7b0ac807bfe0fb0920e28e7bd4a36461a1e0a507836206b13add7f0bd3a8389", + "insts_bytes": 1304, + "insts_sha256": "cf1e307b8a68b83590126bfde26ea157530cd219c1867eb04867f5a2f4fb1a2b", + "bo_sizes_bytes": { + "A": 393216, + "B": 294912, + "C": 786432 + }, + "hardware_verified": true, + "compile_seconds": 18.0 + }, + { + "xclbin": "bf16/npu2_1col/gemm_bf16_M512K512N512.xclbin", + "insts": "bf16/npu2_1col/gemm_bf16_M512K512N512.insts.bin", + "arch": "npu2", + "dtype": "bf16", + "n_aie_cols": 1, + "M": 512, + "K": 512, + "N": 512, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 4, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 326, + "xclbin_bytes": 26056, + "xclbin_sha256": "90ee826c18937809151e0ff4c43d1705e426ebf065e8531d45786b94c3a40825", + "insts_bytes": 1304, + "insts_sha256": "2382f2e853c9ba939466ab84acca02b3087ff261972eb62d38402a1f1d77a909", + "bo_sizes_bytes": { + "A": 524288, + "B": 524288, + "C": 1048576 + }, + "hardware_verified": true, + "compile_seconds": 10.0 + }, + { + "xclbin": "bf16/npu2_1col/gemm_bf16_M512K768N768.xclbin", + "insts": "bf16/npu2_1col/gemm_bf16_M512K768N768.insts.bin", + "arch": "npu2", + "dtype": "bf16", + "n_aie_cols": 1, + "M": 512, + "K": 768, + "N": 768, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 4, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 326, + "xclbin_bytes": 28872, + "xclbin_sha256": "347637ed652ca26cfba0d9d90bd513cfe68d8f3ec8bd43666079481774b397e4", + "insts_bytes": 1304, + "insts_sha256": "6b4a2a790b460eb92efc46aaab6e2ddf080178d40e75affd1e9cfa0f0e9e0d17", + "bo_sizes_bytes": { + "A": 786432, + "B": 1179648, + "C": 1572864 + }, + "hardware_verified": true, + "compile_seconds": 9.3 + }, + { + "xclbin": "bfp16/npu2_8col/gemm_bf16_M512K384N384.xclbin", + "insts": "bfp16/npu2_8col/gemm_bf16_M512K384N384.insts.bin", + "arch": "npu2", + "dtype": "bfp16", + "n_aie_cols": 8, + "M": 512, + "K": 384, + "N": 384, + "tile": { + "m": 32, + "k": 64, + "n": 48 + }, + "mac_dims": [ + 8, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 2100, + "xclbin_bytes": 142670, + "xclbin_sha256": "6264bd24fe75554fee7164a8ebe05e74f1b72684d598f9f4b9984970a205cd0e", + "insts_bytes": 8400, + "insts_sha256": "274294c4864594591c01afa7fb5794ad66fe4df6e7db17b6322e72994201846f", + "bo_sizes_bytes": { + "A": 393216, + "B": 294912, + "C": 786432 + }, + "hardware_verified": false, + "compile_seconds": 17.0 + }, + { + "xclbin": "bfp16/npu2_8col/gemm_bf16_M512K512N512.xclbin", + "insts": "bfp16/npu2_8col/gemm_bf16_M512K512N512.insts.bin", + "arch": "npu2", + "dtype": "bfp16", + "n_aie_cols": 8, + "M": 512, + "K": 512, + "N": 512, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 8, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 2100, + "xclbin_bytes": 151886, + "xclbin_sha256": "759e4c06fd9eea81055e649d1255fb54fc1c8c9ba8966c9af1dd2d3415132ce7", + "insts_bytes": 8400, + "insts_sha256": "08d5727f5f47de1315af95c8a2f30e96787608d4576ddbb2663b60eee3b1aac3", + "bo_sizes_bytes": { + "A": 524288, + "B": 524288, + "C": 1048576 + }, + "hardware_verified": false, + "compile_seconds": 20.0 + }, + { + "xclbin": "bfp16/npu2_8col/gemm_bf16_M512K768N768.xclbin", + "insts": "bfp16/npu2_8col/gemm_bf16_M512K768N768.insts.bin", + "arch": "npu2", + "dtype": "bfp16", + "n_aie_cols": 8, + "M": 512, + "K": 768, + "N": 768, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 8, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 2100, + "xclbin_bytes": 174414, + "xclbin_sha256": "94baa0eae6363ed609b834e03574407649b86ecb6e21874732d4d64bdbc463fe", + "insts_bytes": 8400, + "insts_sha256": "e8614292674a4946074446354f86aff268ff9bec581dd8cd04441b1ad68f16ab", + "bo_sizes_bytes": { + "A": 786432, + "B": 1179648, + "C": 1572864 + }, + "hardware_verified": false, + "compile_seconds": 25.5 + }, + { + "xclbin": "bfp16/npu2_4col/gemm_bf16_M512K384N384.xclbin", + "insts": "bfp16/npu2_4col/gemm_bf16_M512K384N384.insts.bin", + "arch": "npu2", + "dtype": "bfp16", + "n_aie_cols": 4, + "M": 512, + "K": 384, + "N": 384, + "tile": { + "m": 32, + "k": 64, + "n": 48 + }, + "mac_dims": [ + 8, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 1292, + "xclbin_bytes": 74862, + "xclbin_sha256": "9353f2bbc9746edae37aca13441e70d4d1c3618b5b68a852fb24184197586bf4", + "insts_bytes": 5168, + "insts_sha256": "77aa4246090925aa8a8580dcbe702f636d059806886b6ccc07f594290e75d8db", + "bo_sizes_bytes": { + "A": 393216, + "B": 294912, + "C": 786432 + }, + "hardware_verified": false, + "compile_seconds": 15.1 + }, + { + "xclbin": "bfp16/npu2_4col/gemm_bf16_M512K512N512.xclbin", + "insts": "bfp16/npu2_4col/gemm_bf16_M512K512N512.insts.bin", + "arch": "npu2", + "dtype": "bfp16", + "n_aie_cols": 4, + "M": 512, + "K": 512, + "N": 512, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 8, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 1292, + "xclbin_bytes": 79470, + "xclbin_sha256": "24eaa3d3ef86293b83fb571b3f628ab6cfafc72b1168843d344fd2ee6e505de0", + "insts_bytes": 5168, + "insts_sha256": "e8f42bb5b265fb51d50191844250afe8321ea7d2b735986fd882e62de8bcdea4", + "bo_sizes_bytes": { + "A": 524288, + "B": 524288, + "C": 1048576 + }, + "hardware_verified": false, + "compile_seconds": 11.9 + }, + { + "xclbin": "bfp16/npu2_4col/gemm_bf16_M512K768N768.xclbin", + "insts": "bfp16/npu2_4col/gemm_bf16_M512K768N768.insts.bin", + "arch": "npu2", + "dtype": "bfp16", + "n_aie_cols": 4, + "M": 512, + "K": 768, + "N": 768, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 8, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 1292, + "xclbin_bytes": 90734, + "xclbin_sha256": "b91967c2a06d25291179ad748655e40300f5b7afb356c9bf272507f85c3001a9", + "insts_bytes": 5168, + "insts_sha256": "a5288db6688002b9b32f169e15ae32c473e1f05fa6090ba7764ebc87b0306118", + "bo_sizes_bytes": { + "A": 786432, + "B": 1179648, + "C": 1572864 + }, + "hardware_verified": false, + "compile_seconds": 12.8 + }, + { + "xclbin": "bfp16/npu2_1col/gemm_bf16_M512K384N384.xclbin", + "insts": "bfp16/npu2_1col/gemm_bf16_M512K384N384.insts.bin", + "arch": "npu2", + "dtype": "bfp16", + "n_aie_cols": 1, + "M": 512, + "K": 384, + "N": 384, + "tile": { + "m": 32, + "k": 64, + "n": 48 + }, + "mac_dims": [ + 8, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 326, + "xclbin_bytes": 24456, + "xclbin_sha256": "4a81b7e99e330c8a95f0c9dedc6224ff6d779bd65694b7b62ccb984db945948e", + "insts_bytes": 1304, + "insts_sha256": "cf1e307b8a68b83590126bfde26ea157530cd219c1867eb04867f5a2f4fb1a2b", + "bo_sizes_bytes": { + "A": 393216, + "B": 294912, + "C": 786432 + }, + "hardware_verified": false, + "compile_seconds": 9.1 + }, + { + "xclbin": "bfp16/npu2_1col/gemm_bf16_M512K512N512.xclbin", + "insts": "bfp16/npu2_1col/gemm_bf16_M512K512N512.insts.bin", + "arch": "npu2", + "dtype": "bfp16", + "n_aie_cols": 1, + "M": 512, + "K": 512, + "N": 512, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 8, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 326, + "xclbin_bytes": 25608, + "xclbin_sha256": "fe666f21f7a0e09e69507096a37487fd50401a56abce51ae716a4d90715a48a4", + "insts_bytes": 1304, + "insts_sha256": "2382f2e853c9ba939466ab84acca02b3087ff261972eb62d38402a1f1d77a909", + "bo_sizes_bytes": { + "A": 524288, + "B": 524288, + "C": 1048576 + }, + "hardware_verified": false, + "compile_seconds": 10.2 + }, + { + "xclbin": "bfp16/npu2_1col/gemm_bf16_M512K768N768.xclbin", + "insts": "bfp16/npu2_1col/gemm_bf16_M512K768N768.insts.bin", + "arch": "npu2", + "dtype": "bfp16", + "n_aie_cols": 1, + "M": 512, + "K": 768, + "N": 768, + "tile": { + "m": 32, + "k": 64, + "n": 32 + }, + "mac_dims": [ + 8, + 8, + 8 + ], + "core_kernel": "MLIR_AIE", + "zero_kernel": "zero_f32", + "n_instr_words": 326, + "xclbin_bytes": 28424, + "xclbin_sha256": "6c3843f37343c3c3d110929c607ff6e6b2cf59a1849b8a3ec9ba1a7a875791f1", + "insts_bytes": 1304, + "insts_sha256": "6b4a2a790b460eb92efc46aaab6e2ddf080178d40e75affd1e9cfa0f0e9e0d17", + "bo_sizes_bytes": { + "A": 786432, + "B": 1179648, + "C": 1572864 + }, + "hardware_verified": false, + "compile_seconds": 9.9 + } + ] +} diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h12_s169.insts.bin b/cpp/external/ryzenai_artifacts/ops/attn_h12_s169.insts.bin new file mode 100644 index 000000000..787435a2b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h12_s169.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h12_s169.xclbin b/cpp/external/ryzenai_artifacts/ops/attn_h12_s169.xclbin new file mode 100644 index 000000000..28460dc06 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h12_s169.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h12_s361.insts.bin b/cpp/external/ryzenai_artifacts/ops/attn_h12_s361.insts.bin new file mode 100644 index 000000000..e65ceb22e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h12_s361.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h12_s361.xclbin b/cpp/external/ryzenai_artifacts/ops/attn_h12_s361.xclbin new file mode 100644 index 000000000..365be9a7b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h12_s361.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h12_s81.insts.bin b/cpp/external/ryzenai_artifacts/ops/attn_h12_s81.insts.bin new file mode 100644 index 000000000..d117a37e8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h12_s81.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h12_s81.xclbin b/cpp/external/ryzenai_artifacts/ops/attn_h12_s81.xclbin new file mode 100644 index 000000000..2563b756c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h12_s81.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h6_s169.insts.bin b/cpp/external/ryzenai_artifacts/ops/attn_h6_s169.insts.bin new file mode 100644 index 000000000..956193771 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h6_s169.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h6_s169.xclbin b/cpp/external/ryzenai_artifacts/ops/attn_h6_s169.xclbin new file mode 100644 index 000000000..d433a723b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h6_s169.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h6_s361.insts.bin b/cpp/external/ryzenai_artifacts/ops/attn_h6_s361.insts.bin new file mode 100644 index 000000000..f4850c7e5 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h6_s361.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h6_s361.xclbin b/cpp/external/ryzenai_artifacts/ops/attn_h6_s361.xclbin new file mode 100644 index 000000000..0524c8f60 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h6_s361.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h6_s81.insts.bin b/cpp/external/ryzenai_artifacts/ops/attn_h6_s81.insts.bin new file mode 100644 index 000000000..1cca8f517 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h6_s81.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h6_s81.xclbin b/cpp/external/ryzenai_artifacts/ops/attn_h6_s81.xclbin new file mode 100644 index 000000000..b8347e8bf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h6_s81.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h8_s169.insts.bin b/cpp/external/ryzenai_artifacts/ops/attn_h8_s169.insts.bin new file mode 100644 index 000000000..69b8f2c8b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h8_s169.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h8_s169.xclbin b/cpp/external/ryzenai_artifacts/ops/attn_h8_s169.xclbin new file mode 100644 index 000000000..c68dacd39 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h8_s169.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h8_s361.insts.bin b/cpp/external/ryzenai_artifacts/ops/attn_h8_s361.insts.bin new file mode 100644 index 000000000..ce6dab1aa Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h8_s361.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h8_s361.xclbin b/cpp/external/ryzenai_artifacts/ops/attn_h8_s361.xclbin new file mode 100644 index 000000000..d0e5892cf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h8_s361.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h8_s81.insts.bin b/cpp/external/ryzenai_artifacts/ops/attn_h8_s81.insts.bin new file mode 100644 index 000000000..397818f18 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h8_s81.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/attn_h8_s81.xclbin b/cpp/external/ryzenai_artifacts/ops/attn_h8_s81.xclbin new file mode 100644 index 000000000..7aa634382 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/attn_h8_s81.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_1536x1024.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x1024.insts.bin new file mode 100644 index 000000000..bb1332af0 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x1024.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_1536x1024.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x1024.xclbin new file mode 100644 index 000000000..9d6ecb62e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x1024.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_1536x192.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x192.insts.bin new file mode 100644 index 000000000..8f4699914 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_1536x192.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x192.xclbin new file mode 100644 index 000000000..5ecb97e7c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_1536x256.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x256.insts.bin new file mode 100644 index 000000000..ab4eed40c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x256.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_1536x256.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x256.xclbin new file mode 100644 index 000000000..48bee6a3c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x256.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_1536x384.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x384.insts.bin new file mode 100644 index 000000000..9c300e69b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_1536x384.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x384.xclbin new file mode 100644 index 000000000..acefa67ab Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_1536x512.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x512.insts.bin new file mode 100644 index 000000000..3ec78beef Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_1536x512.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x512.xclbin new file mode 100644 index 000000000..c10accb7c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_1536x768.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x768.insts.bin new file mode 100644 index 000000000..6244af867 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_1536x768.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x768.xclbin new file mode 100644 index 000000000..6b7cdfeca Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_1536x768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_3072x1024.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x1024.insts.bin new file mode 100644 index 000000000..895b49b66 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x1024.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_3072x1024.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x1024.xclbin new file mode 100644 index 000000000..238b69ba7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x1024.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_3072x192.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x192.insts.bin new file mode 100644 index 000000000..a0ebddae7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_3072x192.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x192.xclbin new file mode 100644 index 000000000..4177f8d21 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_3072x256.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x256.insts.bin new file mode 100644 index 000000000..49ffbde24 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x256.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_3072x256.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x256.xclbin new file mode 100644 index 000000000..7a6f76f86 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x256.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_3072x384.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x384.insts.bin new file mode 100644 index 000000000..1bfb1aed2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_3072x384.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x384.xclbin new file mode 100644 index 000000000..3f7996b65 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_3072x512.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x512.insts.bin new file mode 100644 index 000000000..d04182c80 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_3072x512.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x512.xclbin new file mode 100644 index 000000000..84a2592ce Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_3072x768.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x768.insts.bin new file mode 100644 index 000000000..536d9e888 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_3072x768.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x768.xclbin new file mode 100644 index 000000000..e7fc9a786 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_3072x768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x1024.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x1024.insts.bin new file mode 100644 index 000000000..406d72c54 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x1024.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x1024.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x1024.xclbin new file mode 100644 index 000000000..64d102d87 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x1024.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x128.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x128.insts.bin new file mode 100644 index 000000000..30faf3b35 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x128.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x128.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x128.xclbin new file mode 100644 index 000000000..25a7199bf Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x128.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x160.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x160.insts.bin new file mode 100644 index 000000000..af9eea42e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x160.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x160.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x160.xclbin new file mode 100644 index 000000000..a2d1a197c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x160.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x192.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x192.insts.bin new file mode 100644 index 000000000..c831da614 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x192.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x192.xclbin new file mode 100644 index 000000000..31a55a260 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x256.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x256.insts.bin new file mode 100644 index 000000000..d0ac495be Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x256.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x256.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x256.xclbin new file mode 100644 index 000000000..fab04700e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x256.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x320.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x320.insts.bin new file mode 100644 index 000000000..5646456e7 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x320.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x320.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x320.xclbin new file mode 100644 index 000000000..0f1f42f35 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x320.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x384.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x384.insts.bin new file mode 100644 index 000000000..9c9cea2c8 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x384.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x384.xclbin new file mode 100644 index 000000000..f20cc1e28 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x512.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x512.insts.bin new file mode 100644 index 000000000..d5f93a979 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x512.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x512.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x512.xclbin new file mode 100644 index 000000000..480f34ce1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x512.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x64.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x64.insts.bin new file mode 100644 index 000000000..31a4b8495 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x64.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x64.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x64.xclbin new file mode 100644 index 000000000..174bb6984 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x64.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x640.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x640.insts.bin new file mode 100644 index 000000000..3280e0abc Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x640.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x640.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x640.xclbin new file mode 100644 index 000000000..a93a7380a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x640.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x768.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x768.insts.bin new file mode 100644 index 000000000..0d12fbd88 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x768.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x768.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x768.xclbin new file mode 100644 index 000000000..b459fcdb4 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x768.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x96.insts.bin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x96.insts.bin new file mode 100644 index 000000000..a7fd90631 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x96.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/bnmish_384x96.xclbin b/cpp/external/ryzenai_artifacts/ops/bnmish_384x96.xclbin new file mode 100644 index 000000000..d7af94f5c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/bnmish_384x96.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/rmsnorm_384x384.insts.bin b/cpp/external/ryzenai_artifacts/ops/rmsnorm_384x384.insts.bin new file mode 100644 index 000000000..902f8e30f Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/rmsnorm_384x384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/rmsnorm_384x384.xclbin b/cpp/external/ryzenai_artifacts/ops/rmsnorm_384x384.xclbin new file mode 100644 index 000000000..2f8663a1a Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/rmsnorm_384x384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_1024x192.insts.bin b/cpp/external/ryzenai_artifacts/ops/softmax_1024x192.insts.bin new file mode 100644 index 000000000..ec02697c1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_1024x192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_1024x192.xclbin b/cpp/external/ryzenai_artifacts/ops/softmax_1024x192.xclbin new file mode 100644 index 000000000..9012837d2 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_1024x192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_1024x96.insts.bin b/cpp/external/ryzenai_artifacts/ops/softmax_1024x96.insts.bin new file mode 100644 index 000000000..fbd1d34bb Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_1024x96.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_1024x96.xclbin b/cpp/external/ryzenai_artifacts/ops/softmax_1024x96.xclbin new file mode 100644 index 000000000..74d14b8eb Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_1024x96.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_1408x192.insts.bin b/cpp/external/ryzenai_artifacts/ops/softmax_1408x192.insts.bin new file mode 100644 index 000000000..2740a1183 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_1408x192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_1408x192.xclbin b/cpp/external/ryzenai_artifacts/ops/softmax_1408x192.xclbin new file mode 100644 index 000000000..352b6681d Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_1408x192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_2048x192.insts.bin b/cpp/external/ryzenai_artifacts/ops/softmax_2048x192.insts.bin new file mode 100644 index 000000000..22913f137 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_2048x192.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_2048x192.xclbin b/cpp/external/ryzenai_artifacts/ops/softmax_2048x192.xclbin new file mode 100644 index 000000000..2f7516c87 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_2048x192.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_2176x384.insts.bin b/cpp/external/ryzenai_artifacts/ops/softmax_2176x384.insts.bin new file mode 100644 index 000000000..c1cd70895 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_2176x384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_2176x384.xclbin b/cpp/external/ryzenai_artifacts/ops/softmax_2176x384.xclbin new file mode 100644 index 000000000..34074b0ef Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_2176x384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_2944x384.insts.bin b/cpp/external/ryzenai_artifacts/ops/softmax_2944x384.insts.bin new file mode 100644 index 000000000..51769eb19 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_2944x384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_2944x384.xclbin b/cpp/external/ryzenai_artifacts/ops/softmax_2944x384.xclbin new file mode 100644 index 000000000..42809c641 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_2944x384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_4352x384.insts.bin b/cpp/external/ryzenai_artifacts/ops/softmax_4352x384.insts.bin new file mode 100644 index 000000000..b8958fa54 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_4352x384.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_4352x384.xclbin b/cpp/external/ryzenai_artifacts/ops/softmax_4352x384.xclbin new file mode 100644 index 000000000..5eb01e138 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_4352x384.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_512x96.insts.bin b/cpp/external/ryzenai_artifacts/ops/softmax_512x96.insts.bin new file mode 100644 index 000000000..66077038e Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_512x96.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_512x96.xclbin b/cpp/external/ryzenai_artifacts/ops/softmax_512x96.xclbin new file mode 100644 index 000000000..4b785487c Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_512x96.xclbin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_704x96.insts.bin b/cpp/external/ryzenai_artifacts/ops/softmax_704x96.insts.bin new file mode 100644 index 000000000..f59c6afe1 Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_704x96.insts.bin differ diff --git a/cpp/external/ryzenai_artifacts/ops/softmax_704x96.xclbin b/cpp/external/ryzenai_artifacts/ops/softmax_704x96.xclbin new file mode 100644 index 000000000..8b72ce37b Binary files /dev/null and b/cpp/external/ryzenai_artifacts/ops/softmax_704x96.xclbin differ diff --git a/cpp/main.cpp b/cpp/main.cpp index a843f991d..0f6cf1a67 100644 --- a/cpp/main.cpp +++ b/cpp/main.cpp @@ -271,6 +271,8 @@ string Version::getKataGoVersionFullInfo() { #endif #elif defined(USE_EIGEN_BACKEND) out << "Using Eigen(CPU) backend" << endl; +#elif defined(USE_RYZENAI_BACKEND) + out << "Using RyzenAI (AMD NPU) backend" << endl; #elif defined(USE_ONNX_BACKEND) out << "Using ONNX Runtime backend" << endl; #else @@ -311,6 +313,8 @@ string Version::getGitRevisionWithBackend() { s += "-opencl"; #elif defined(USE_EIGEN_BACKEND) s += "-eigen"; +#elif defined(USE_RYZENAI_BACKEND) + s += "-ryzenai"; #elif defined(USE_ONNX_BACKEND) s += "-onnx"; #else diff --git a/cpp/neuralnet/ryzenaibackend.cpp b/cpp/neuralnet/ryzenaibackend.cpp new file mode 100644 index 000000000..c290c30f2 --- /dev/null +++ b/cpp/neuralnet/ryzenaibackend.cpp @@ -0,0 +1,694 @@ +#ifdef USE_RYZENAI_BACKEND + +/** RyzenAI (AMD NPU) backend. + * + * Structured after cpp/neuralnet/eigenbackend.cpp. Currently all evaluation + * runs on the pure C++ CPU reference forward path (neuralnet/ryzenaireference.h); + * NPU kernel dispatch via XRT will be layered on top of it. Inputs and all + * internal activations are NHWC float32. + */ + +#include "../neuralnet/nninterface.h" + +#include "../neuralnet/desc.h" +#include "../neuralnet/modelversion.h" +#include "../neuralnet/nninputs.h" +#include "../neuralnet/nneval.h" + +#include "../core/test.h" + +#include "../neuralnet/ryzenaidevice.h" +#include "../neuralnet/ryzenaikernel.h" +#include "../neuralnet/ryzenaimatmul.h" +#include "../neuralnet/ryzenaireference.h" +#include "../neuralnet/ryzenaishapes.h" + +using namespace std; + +// LoadedModel / ModelDesc --------------------------------------------------------------------------------------------- + +struct LoadedModel { + ModelDesc modelDesc; + + LoadedModel(const string& fileName, const string& expectedSha256) { + ModelDesc::loadFromFileMaybeGZipped(fileName,modelDesc,expectedSha256); + } + + LoadedModel() = delete; + LoadedModel(const LoadedModel&) = delete; + LoadedModel& operator=(const LoadedModel&) = delete; +}; + +LoadedModel* NeuralNet::loadModelFile(const string& file, const string& expectedSha256) { + LoadedModel* loadedModel = new LoadedModel(file,expectedSha256); + return loadedModel; +} + +void NeuralNet::freeLoadedModel(LoadedModel* loadedModel) { + // NOTE: modelDesc weights must still be intact here if any Workspace still + // references them - but all ComputeHandles are always freed before this. + delete loadedModel; +} + +const ModelDesc& NeuralNet::getModelDesc(const LoadedModel* loadedModel) { + return loadedModel->modelDesc; +} + +// -------------------------------------------------------------------------------------------------------------- + +struct ComputeContext { + const int nnXLen; + const int nnYLen; + + const enabled_t useFP16Mode; + + // Backend-specific configuration, read off of cfg in createComputeContext. + // Device indices themselves (ryzenaiDeviceToUse / ryzenaiDeviceToUseThread) + // are parsed uniformly by setup.cpp and arrive via gpuIdxs / gpuIdxForThisThread. + const string artifactDir; + const string dtype; + const bool forceNpuOnly; + const bool verboseDispatch; + const int maxCols; + const int forceK; + const vector gpuIdxs; + const vector xclbins; + + ComputeContext() = delete; + ComputeContext(const ComputeContext&) = delete; + ComputeContext& operator=(const ComputeContext&) = delete; + + ComputeContext( + int nnX, + int nnY, + enabled_t fp16Mode, + const string& aDir, + const string& dt, + bool forceNpu, + bool verbose, + int maxColumns, + int forceReduceDim, + const vector& gIdxs, + const vector& xcl + ) + : nnXLen(nnX), + nnYLen(nnY), + useFP16Mode(fp16Mode), + artifactDir(aDir), + dtype(dt), + forceNpuOnly(forceNpu), + verboseDispatch(verbose), + maxCols(maxColumns), + forceK(forceReduceDim), + gpuIdxs(gIdxs), + xclbins(xcl) + {} + ~ComputeContext() {} +}; + +// -------------------------------------------------------------------------------------------------------------- + +struct ComputeHandle { + ComputeContext* context; + bool inputsUseNHWC; + int gpuIdxForThisThread; + + // NOT owned - owned by the LoadedModel, which always outlives this handle. + // Do not call releaseWeights() on it: the workspace references its weights. + const ModelDesc& modelDesc; + + RyzenAIRef::Workspace* workspace; + + // Dense-layer accelerator. Null when no NPU/artifact is usable, in which case + // the workspace runs entirely on the CPU reference path. + RyzenAIMatMul::Accel* accel; + string accelInitError; + Logger* logger; // not owned; may be null + + // Output buffers for RyzenAIRef::forward(), allocated once per handle. + vector policyBuf; + vector policyPassBuf; + vector valueBuf; + vector scoreValueBuf; + vector ownershipBuf; + + ComputeHandle() = delete; + ComputeHandle(const ComputeHandle&) = delete; + ComputeHandle& operator=(const ComputeHandle&) = delete; + + ComputeHandle( + ComputeContext* ctx, + const LoadedModel& loadedModel, + int maxBatchSize, + bool iNHWC, + int gpuIdx, + Logger* lg + ) + : context(ctx), + inputsUseNHWC(iNHWC), + gpuIdxForThisThread(gpuIdx), + modelDesc(loadedModel.modelDesc), + workspace(NULL), + accel(NULL), + logger(lg) + { + workspace = RyzenAIRef::createWorkspace(modelDesc,maxBatchSize,context->nnXLen,context->nnYLen); + RyzenAIRef::setProfileEnabled(context->verboseDispatch); + + RyzenAIMatMul::Options options; + options.artifactDir = context->artifactDir; + options.deviceIdx = gpuIdx; + options.dtype = context->dtype; + options.maxCols = context->maxCols; + options.forceK = context->forceK; + string accelErr; + accel = RyzenAIMatMul::create(options,accelErr); + if(accel != NULL) + RyzenAIRef::setMatMulAccel(workspace,accel); + else + accelInitError = accelErr; + + const int nnXLen = context->nnXLen; + const int nnYLen = context->nnYLen; + policyBuf = vector((size_t)maxBatchSize * nnXLen * nnYLen * modelDesc.numPolicyChannels); + policyPassBuf = vector((size_t)maxBatchSize * modelDesc.numPolicyChannels); + valueBuf = vector((size_t)maxBatchSize * modelDesc.numValueChannels); + scoreValueBuf = vector((size_t)maxBatchSize * modelDesc.numScoreValueChannels); + ownershipBuf = vector((size_t)maxBatchSize * nnXLen * nnYLen * modelDesc.numOwnershipChannels); + } + + ~ComputeHandle() { + // Report the NPU/CPU split here rather than at startup: how many dense + // layers were actually accelerated is only known after evaluating. + if(logger != NULL && accel != NULL && context->verboseDispatch) + logger->write(RyzenAIMatMul::report(accel)); + if(logger != NULL && context->verboseDispatch) + logger->write(RyzenAIRef::profileReport()); + + // The workspace holds a bare pointer to the accelerator, so it has to stop + // referring to it before the accelerator's device buffers go away. + if(workspace != NULL) + RyzenAIRef::setMatMulAccel(workspace,NULL); + if(accel != NULL) + RyzenAIMatMul::free(accel); + accel = NULL; + if(workspace != NULL) + RyzenAIRef::freeWorkspace(workspace); + workspace = NULL; + } +}; + +//-------------------------------------------------------------- + +struct InputBuffers { + int maxBatchSize; + + size_t singleInputElts; + size_t singleInputGlobalElts; + size_t singleInputMetaElts; + + size_t singlePolicyPassResultElts; + size_t singlePolicyResultElts; + size_t singleValueResultElts; + size_t singleScoreValueResultElts; + size_t singleOwnershipResultElts; + + std::vector spatialInput; + std::vector globalInput; + std::vector metaInput; + + InputBuffers(const LoadedModel* loadedModel, int maxBatchSz, int nnXLen, int nnYLen) { + const ModelDesc& m = loadedModel->modelDesc; + + maxBatchSize = maxBatchSz; + singleInputElts = m.numInputChannels * nnXLen * nnYLen; + singleInputGlobalElts = m.numInputGlobalChannels; + singleInputMetaElts = m.numInputMetaChannels; + + singlePolicyPassResultElts = (size_t)(m.numPolicyChannels); + singlePolicyResultElts = (size_t)(m.numPolicyChannels * nnXLen * nnYLen); + singleValueResultElts = (size_t)m.numValueChannels; + singleScoreValueResultElts = (size_t)m.numScoreValueChannels; + singleOwnershipResultElts = (size_t)m.numOwnershipChannels * nnXLen * nnYLen; + + testAssert(NNModelVersion::getNumSpatialFeatures(m.modelVersion) == m.numInputChannels); + testAssert(NNModelVersion::getNumGlobalFeatures(m.modelVersion) == m.numInputGlobalChannels); + if(m.numInputMetaChannels > 0) { + testAssert(SGFMetadata::METADATA_INPUT_NUM_CHANNELS == m.numInputMetaChannels); + } + + spatialInput = vector(m.numInputChannels * nnXLen * nnYLen * maxBatchSize); + globalInput = vector(m.numInputGlobalChannels * maxBatchSize); + if(m.numInputMetaChannels > 0) + metaInput = vector(m.numInputMetaChannels * maxBatchSize); + else + metaInput = vector(1); + } + + ~InputBuffers() { } + + InputBuffers() = delete; + InputBuffers(const InputBuffers&) = delete; + InputBuffers& operator=(const InputBuffers&) = delete; +}; + +InputBuffers* NeuralNet::createInputBuffers(const LoadedModel* loadedModel, int maxBatchSize, int nnXLen, int nnYLen) { + return new InputBuffers(loadedModel, maxBatchSize, nnXLen, nnYLen); +} +void NeuralNet::freeInputBuffers(InputBuffers* inputBuffers) { + delete inputBuffers; +} + +// NeuralNet ----------------------------------------------------------------------------------------------------------- + +void NeuralNet::globalInitialize() { + // Must happen before the first XRT call of the process. printDevices() also + // runs before any compute context exists, so it calls this too. + RyzenAIDevice::ensureRuntimeLibraryPath(); +} + +void NeuralNet::globalCleanup() { + // no-op +} + +//------------------------------------------------------------------------------ + +ComputeContext* NeuralNet::createComputeContext( + const std::vector& gpuIdxs, + Logger* logger, + int nnXLen, + int nnYLen, + const string& homeDataDirOverride, + enabled_t useFP16Mode, + const LoadedModel* loadedModel, + ConfigParser& cfg +) { + string artifactDirConfig = cfg.contains("ryzenaiArtifactDir") ? cfg.getString("ryzenaiArtifactDir") : ""; + // auto | bf16 | bfp16. Both bf16 and bfp16 hand the NPU bfloat16 operands and + // read float32 back - the difference is entirely inside the kernel - so this + // only selects which artifact directory is loaded. See resolveDtype() for why + // auto currently means bf16 even on hardware that supports bfp16. + string dtypeStr = cfg.contains("ryzenaiDtype") ? cfg.getString("ryzenaiDtype") : "auto"; + RyzenAIKernel::Dtype dtype = RyzenAIKernel::Dtype::Auto; + if(!RyzenAIKernel::parseDtype(dtypeStr, dtype)) + throw StringError( + "RyzenAI backend: unrecognized ryzenaiDtype = '" + dtypeStr + "', expected auto, bf16 or bfp16" + ); + bool forceNpuOnly = cfg.contains("ryzenaiForceNpuOnly") ? cfg.getBool("ryzenaiForceNpuOnly") : false; + bool verboseDispatch = cfg.contains("ryzenaiVerboseDispatch") ? cfg.getBool("ryzenaiVerboseDispatch") : false; + // Wider is not automatically faster: at one board per evaluation the array + // is starved and the fixed dispatch cost dominates, so 4 columns measured + // faster than 8. 0 means "as wide as the device allows". + int maxCols = cfg.contains("ryzenaiMaxColumns") ? cfg.getInt("ryzenaiMaxColumns",0,64) : 4; + // Run every layer from one xclbin, trading zero-padded arithmetic for not + // switching hardware contexts. 0 = pick the closest K per layer. + // -1 (the default) means decide from the model: see RyzenAIShapes::chooseSingleK. + // 0 disables it, a positive value forces that reduction dim. + int forceK = cfg.contains("ryzenaiForceK") ? cfg.getInt("ryzenaiForceK",-1,65536) : -1; + if(forceK < 0) { + // 4x is where the measured trade turns: below it the extra zero-padded + // arithmetic is lost in the noise (NPU compute is ~1% of a forward pass), + // above it the padding is real work on models whose GEMMs are already big. + forceK = loadedModel != NULL ? RyzenAIShapes::chooseSingleK(loadedModel->modelDesc, nnXLen, nnYLen, 4.0) : 0; + } + + string artifactDir = RyzenAIDevice::resolveArtifactDir(artifactDirConfig); + + if(logger != NULL) { + logger->write("RyzenAI backend: " + RyzenAIDevice::ensureRuntimeLibraryPath()); + logger->write("RyzenAI backend: " + RyzenAIDevice::describeRuntime()); + logger->write("RyzenAI backend: artifact dir = " + artifactDir); + logger->write("RyzenAI backend: dtype = " + dtypeStr + " (resolved: " + + RyzenAIKernel::dtypeName(RyzenAIKernel::resolveDtype(dtype, RyzenAIDevice::archOfDevice(-1))) + ")"); + if(useFP16Mode == enabled_t::True) + logger->write("RyzenAI backend: useFP16 = true was requested, but the current reference path always computes in fp32"); + } + + vector xclbins = RyzenAIDevice::listXclbins(artifactDir); + if(xclbins.empty()) { + if(forceNpuOnly) { + throw StringError( + "RyzenAI backend: ryzenaiForceNpuOnly = true but no .xclbin NPU kernel artifacts were found in " + + artifactDir + " - NPU dispatch is not possible" + ); + } + if(logger != NULL) { + logger->write( + "RyzenAI backend: no .xclbin NPU kernel artifacts found in " + artifactDir + + " - running on the CPU reference forward path, NPU acceleration is not enabled yet" + ); + } + } + else if(cfg.contains("ryzenaiSelfTest") && cfg.getBool("ryzenaiSelfTest")) { + // Loads every artifact, dispatches it on the NPU and checks it against a + // plain-C++ GEMM. Opt-in because it costs a few seconds of startup, but it + // is the fastest way to tell whether a machine's NPU/driver/artifact set is + // actually working. + if(logger != NULL) + logger->write(RyzenAIKernel::selfTest(artifactDir, -1)); + } + + // Which GEMM shapes this model actually needs. An xclbin bakes in the + // reduction dim K (and only K -- M and N ride in the instruction stream), so + // this is what decides which artifacts must exist and which layers fall back + // to the CPU reference path. + if(cfg.contains("ryzenaiShapeReport") && cfg.getBool("ryzenaiShapeReport")) { + if(logger != NULL && loadedModel != NULL) + logger->write(RyzenAIShapes::report(loadedModel->modelDesc, nnXLen, nnYLen)); + } + + if(!xclbins.empty()) { + if(logger != NULL) { + // Count only: the shipped grid is a few hundred files, and naming them + // all put tens of thousands of characters on one line of every log. + // Which ones actually got loaded is what matters, and verbose dispatch + // reports that per engine. + logger->write( + "RyzenAI backend: found " + Global::uint64ToString((uint64_t)xclbins.size()) + + " NPU kernel artifacts in " + artifactDir + ); + } + } + + ComputeContext* context = new ComputeContext( + nnXLen,nnYLen,useFP16Mode,artifactDir,dtypeStr,forceNpuOnly,verboseDispatch,maxCols,forceK,gpuIdxs,xclbins + ); + return context; +} + +void NeuralNet::freeComputeContext(ComputeContext* computeContext) { + delete computeContext; +} + +//------------------------------------------------------------------------------ + +ComputeHandle* NeuralNet::createComputeHandle( + ComputeContext* context, + const LoadedModel* loadedModel, + Logger* logger, + int maxBatchSize, + bool requireExactNNLen, + bool inputsUseNHWC, + int gpuIdxForThisThread, + int serverThreadIdx +) { + if(logger != NULL) { + logger->write("RyzenAI (AMD NPU) backend thread " + Global::intToString(serverThreadIdx) + ": Model version " + Global::intToString(loadedModel->modelDesc.modelVersion)); + logger->write("RyzenAI (AMD NPU) backend thread " + Global::intToString(serverThreadIdx) + ": Model name: " + loadedModel->modelDesc.name + " (" + loadedModel->modelDesc.getShortInfoString() + ")"); + } + + (void)requireExactNNLen; //We don't bother with mask optimizations if we know exact sizes right now. + + if(!inputsUseNHWC) + throw StringError("RyzenAI backend: inputsUseNHWC = false unsupported (the reference path requires NHWC input)"); + + ComputeHandle* handle = new ComputeHandle(context, *loadedModel, maxBatchSize, inputsUseNHWC, gpuIdxForThisThread, logger); + if(logger != NULL) { + const string prefix = "RyzenAI (AMD NPU) backend thread " + Global::intToString(serverThreadIdx) + ": "; + if(handle->accel == NULL) + logger->write(prefix + "dense layers stay on the CPU (" + handle->accelInitError + ")"); + else if(context->verboseDispatch) + logger->write(prefix + "device index " + Global::intToString(gpuIdxForThisThread) + + ", dense layers offered to the NPU"); + } + return handle; +} + +void NeuralNet::freeComputeHandle(ComputeHandle* gpuHandle) { + delete gpuHandle; +} + + +bool NeuralNet::isUsingFP16(const ComputeHandle* handle) { + (void)handle; + return false; +} + +bool NeuralNet::setIsWarmup(const ComputeHandle* handle, bool isWarmup) { + (void)handle; + (void)isWarmup; + return false; +} + +//------------------------------------------------------------------------------ + +void NeuralNet::getOutput( + ComputeHandle* computeHandle, + InputBuffers* inputBuffers, + int numBatchEltsFilled, + NNResultBuf** inputBufs, + vector& outputs +) { + assert(numBatchEltsFilled <= inputBuffers->maxBatchSize); + assert(numBatchEltsFilled > 0); + const int batchSize = numBatchEltsFilled; + const int nnXLen = computeHandle->context->nnXLen; + const int nnYLen = computeHandle->context->nnYLen; + const ModelDesc& modelDesc = computeHandle->modelDesc; + const int modelVersion = modelDesc.modelVersion; + + const int numSpatialFeatures = NNModelVersion::getNumSpatialFeatures(modelVersion); + const int numGlobalFeatures = NNModelVersion::getNumGlobalFeatures(modelVersion); + const int numMetaFeatures = inputBuffers->singleInputMetaElts; + assert(numSpatialFeatures == modelDesc.numInputChannels); + assert(numSpatialFeatures * nnXLen * nnYLen == inputBuffers->singleInputElts); + assert(numGlobalFeatures == inputBuffers->singleInputGlobalElts); + const int numPolicyChannels = modelDesc.numPolicyChannels; + + for(int nIdx = 0; nIdxspatialInput.data() + (inputBuffers->singleInputElts * nIdx); + float* rowGlobalInput = inputBuffers->globalInput.data() + (inputBuffers->singleInputGlobalElts * nIdx); + float* rowMetaInput = inputBuffers->metaInput.data() + (inputBuffers->singleInputMetaElts * nIdx); + + const float* rowGlobal = inputBufs[nIdx]->rowGlobalBuf.data(); + const float* rowSpatial = inputBufs[nIdx]->rowSpatialBuf.data(); + const float* rowMeta = inputBufs[nIdx]->rowMetaBuf.data(); + const bool hasRowMeta = inputBufs[nIdx]->hasRowMeta; + std::copy(rowGlobal,rowGlobal+numGlobalFeatures,rowGlobalInput); + if(numMetaFeatures > 0) { + testAssert(rowMeta != NULL); + testAssert(hasRowMeta); + std::copy(rowMeta,rowMeta+numMetaFeatures,rowMetaInput); + } + else { + testAssert(!hasRowMeta); + } + SymmetryHelpers::copyInputsWithSymmetry(rowSpatial, rowSpatialInput, 1, nnYLen, nnXLen, numSpatialFeatures, computeHandle->inputsUseNHWC, inputBufs[nIdx]->symmetry); + } + + RyzenAIRef::forward( + computeHandle->workspace, + batchSize, + inputBuffers->spatialInput.data(), + inputBuffers->globalInput.data(), + (numMetaFeatures > 0 ? inputBuffers->metaInput.data() : NULL), + computeHandle->policyBuf.data(), + computeHandle->policyPassBuf.data(), + computeHandle->valueBuf.data(), + computeHandle->scoreValueBuf.data(), + computeHandle->ownershipBuf.data() + ); + + assert(inputBuffers->singlePolicyPassResultElts == numPolicyChannels); + assert(inputBuffers->singlePolicyResultElts == numPolicyChannels * nnXLen * nnYLen); + + assert(outputs.size() == batchSize); + + float policyProbsTmp[NNPos::MAX_NN_POLICY_SIZE]; + + const float* policyData = computeHandle->policyBuf.data(); + const float* policyPassData = computeHandle->policyPassBuf.data(); + const float* valueData = computeHandle->valueBuf.data(); + const float* scoreValueData = computeHandle->scoreValueBuf.data(); + const float* ownershipData = computeHandle->ownershipBuf.data(); + + for(int row = 0; row < batchSize; row++) { + NNOutput* output = outputs[row]; + assert(output->nnXLen == nnXLen); + assert(output->nnYLen == nnYLen); + float policyOptimism = (float)inputBufs[row]->policyOptimism; + + const float* policyPassSrcBuf = policyPassData + row * numPolicyChannels; + const float* policySrcBuf = policyData + row * numPolicyChannels * nnXLen * nnYLen; + float* policyProbs = output->policyProbs; + + // These are in logits, the client does the postprocessing to turn them into + // policy probabilities and white game outcome probabilities + // Also we don't fill in the nnHash here either + // Handle version >= 12 policy optimism + if(numPolicyChannels == 2 || (numPolicyChannels == 4 && modelVersion >= 16)) { + // NHWC + for(int i = 0; isymmetry); + policyProbs[nnXLen*nnYLen] = policyPassSrcBuf[0] + (policyPassSrcBuf[1] - policyPassSrcBuf[0]) * policyOptimism; + } + else { + assert(numPolicyChannels == 1); + SymmetryHelpers::copyOutputsWithSymmetry(policySrcBuf, policyProbs, 1, nnYLen, nnXLen, inputBufs[row]->symmetry); + policyProbs[inputBuffers->singlePolicyResultElts] = policyPassSrcBuf[0]; + } + + int numValueChannels = modelDesc.numValueChannels; + assert(numValueChannels == 3); + output->whiteWinProb = valueData[row * numValueChannels]; + output->whiteLossProb = valueData[row * numValueChannels + 1]; + output->whiteNoResultProb = valueData[row * numValueChannels + 2]; + + //As above, these are NOT actually from white's perspective, but rather the player to move. + //As usual the client does the postprocessing. + if(output->whiteOwnerMap != NULL) { + const float* ownershipSrcBuf = ownershipData + row * nnXLen * nnYLen; + assert(modelDesc.numOwnershipChannels == 1); + SymmetryHelpers::copyOutputsWithSymmetry(ownershipSrcBuf, output->whiteOwnerMap, 1, nnYLen, nnXLen, inputBufs[row]->symmetry); + } + + if(modelVersion >= 9) { + int numScoreValueChannels = modelDesc.numScoreValueChannels; + assert(numScoreValueChannels == 6); + output->whiteScoreMean = scoreValueData[row * numScoreValueChannels]; + output->whiteScoreMeanSq = scoreValueData[row * numScoreValueChannels + 1]; + output->whiteLead = scoreValueData[row * numScoreValueChannels + 2]; + output->varTimeLeft = scoreValueData[row * numScoreValueChannels + 3]; + output->shorttermWinlossError = scoreValueData[row * numScoreValueChannels + 4]; + output->shorttermScoreError = scoreValueData[row * numScoreValueChannels + 5]; + } + else if(modelVersion >= 8) { + int numScoreValueChannels = modelDesc.numScoreValueChannels; + assert(numScoreValueChannels == 4); + output->whiteScoreMean = scoreValueData[row * numScoreValueChannels]; + output->whiteScoreMeanSq = scoreValueData[row * numScoreValueChannels + 1]; + output->whiteLead = scoreValueData[row * numScoreValueChannels + 2]; + output->varTimeLeft = scoreValueData[row * numScoreValueChannels + 3]; + output->shorttermWinlossError = 0; + output->shorttermScoreError = 0; + } + else if(modelVersion >= 4) { + int numScoreValueChannels = modelDesc.numScoreValueChannels; + assert(numScoreValueChannels == 2); + output->whiteScoreMean = scoreValueData[row * numScoreValueChannels]; + output->whiteScoreMeanSq = scoreValueData[row * numScoreValueChannels + 1]; + output->whiteLead = output->whiteScoreMean; + output->varTimeLeft = 0; + output->shorttermWinlossError = 0; + output->shorttermScoreError = 0; + } + else if(modelVersion >= 3) { + int numScoreValueChannels = modelDesc.numScoreValueChannels; + assert(numScoreValueChannels == 1); + output->whiteScoreMean = scoreValueData[row * numScoreValueChannels]; + //Version 3 neural nets don't have any second moment output, implicitly already folding it in, so we just use the mean squared + output->whiteScoreMeanSq = output->whiteScoreMean * output->whiteScoreMean; + output->whiteLead = output->whiteScoreMean; + output->varTimeLeft = 0; + output->shorttermWinlossError = 0; + output->shorttermScoreError = 0; + } + else { + ASSERT_UNREACHABLE; + } + } +} + +//------------------------------------------------------------------------------ + +void NeuralNet::printDevices() { + cout << RyzenAIDevice::ensureRuntimeLibraryPath() << endl; + cout << RyzenAIDevice::describeRuntime() << endl; +} + +// FOR TESTING --------------------------------------------------------------------------------------------------------- +bool NeuralNet::testEvaluateConv( + const ConvLayerDesc* desc, + int batchSize, + int nnXLen, + int nnYLen, + bool useFP16, + bool useNHWC, + const std::vector& inputBuffer, + std::vector& outputBuffer +) { + (void)desc; + (void)batchSize; + (void)nnXLen; + (void)nnYLen; + (void)useFP16; + (void)useNHWC; + (void)inputBuffer; + (void)outputBuffer; + return false; +} + +bool NeuralNet::testEvaluateBatchNorm( + const BatchNormLayerDesc* desc, + int batchSize, + int nnXLen, + int nnYLen, + bool useFP16, + bool useNHWC, + const std::vector& inputBuffer, + const std::vector& maskBuffer, + std::vector& outputBuffer +) { + (void)desc; + (void)batchSize; + (void)nnXLen; + (void)nnYLen; + (void)useFP16; + (void)useNHWC; + (void)inputBuffer; + (void)maskBuffer; + (void)outputBuffer; + return false; +} + +bool NeuralNet::testEvaluateResidualBlock( + const ResidualBlockDesc* desc, + int batchSize, + int nnXLen, + int nnYLen, + bool useFP16, + bool useNHWC, + const std::vector& inputBuffer, + const std::vector& maskBuffer, + std::vector& outputBuffer +) { + (void)desc; + (void)batchSize; + (void)nnXLen; + (void)nnYLen; + (void)useFP16; + (void)useNHWC; + (void)inputBuffer; + (void)maskBuffer; + (void)outputBuffer; + return false; +} + +bool NeuralNet::testEvaluateGlobalPoolingResidualBlock( + const GlobalPoolingResidualBlockDesc* desc, + int batchSize, + int nnXLen, + int nnYLen, + bool useFP16, + bool useNHWC, + const std::vector& inputBuffer, + const std::vector& maskBuffer, + std::vector& outputBuffer +) { + (void)desc; + (void)batchSize; + (void)nnXLen; + (void)nnYLen; + (void)useFP16; + (void)useNHWC; + (void)inputBuffer; + (void)maskBuffer; + (void)outputBuffer; + return false; +} + +#endif // USE_RYZENAI_BACKEND diff --git a/cpp/neuralnet/ryzenaidevice.cpp b/cpp/neuralnet/ryzenaidevice.cpp new file mode 100644 index 000000000..4295d3d85 --- /dev/null +++ b/cpp/neuralnet/ryzenaidevice.cpp @@ -0,0 +1,225 @@ +#include "../neuralnet/ryzenaidevice.h" + +#include +#include + +#include "../core/global.h" +#include "../core/os.h" +#include "../dataio/homedata.h" + +#ifdef OS_IS_WINDOWS +#include +#endif + +// XRT's headers are noisy under MSVC's default warning level and pull in a lot +// of Windows machinery; keep them isolated to this translation unit. +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4100 4245 4267 4996) +#endif +#include "xrt/xrt_device.h" +#include "xrt/experimental/xrt_system.h" +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include "../external/filesystem-1.5.8/include/ghc/filesystem.hpp" + +namespace gfs = ghc::filesystem; + +using namespace std; + +int RyzenAIDevice::maxColumns(Arch arch) { + switch(arch) { + case Arch::NPU1: return 4; + case Arch::NPU2: return 8; + default: return 0; + } +} + +const char* RyzenAIDevice::archName(Arch arch) { + switch(arch) { + case Arch::NPU1: return "npu1"; + case Arch::NPU2: return "npu2"; + default: return "unknown"; + } +} + +RyzenAIDevice::Arch RyzenAIDevice::archOfDeviceName(const string& name) { + const string lowered = Global::toLower(name); + auto has = [&lowered](const char* needle) { return lowered.find(needle) != string::npos; }; + + // XDNA2 / aie2p + if(has("strix") || has("krackan") || has("halo") || has("npu2")) + return Arch::NPU2; + // XDNA1 / aie2 + if(has("phoenix") || has("hawk") || has("npu1")) + return Arch::NPU1; + return Arch::Unknown; +} + +namespace { + +string repointXrtIfNeeded() { +#ifdef OS_IS_WINDOWS + static const char* const kRuntimeLib = "xrt_core.dll"; +#else + static const char* const kRuntimeLib = "libxrt_core.so"; +#endif + + auto hasRuntime = [](const string& dir) { + if(dir.size() <= 0) + return false; + std::error_code ec; + return gfs::exists(gfs::u8path(dir) / kRuntimeLib, ec); + }; + + string current; + const char* env = std::getenv("XILINX_XRT"); + if(env != NULL) + current = env; + if(hasRuntime(current)) + return "XILINX_XRT = " + current; + + string exeDir; + try { + const vector dirs = HomeData::getDefaultFilesDirs(); + if(dirs.size() > 0) + exeDir = dirs[0]; + } + catch(const std::exception&) { + // Leave exeDir empty; handled below. + } + if(!hasRuntime(exeDir)) { + if(current.size() > 0) + return "XILINX_XRT = " + current + " (no " + kRuntimeLib + + " there, and none next to the executable either)"; + return string("XILINX_XRT is unset and no ") + kRuntimeLib + + " sits next to the executable; relying on the system library path"; + } + + // Both the Win32 environment block and the CRT copy need updating: XRT lives + // in its own DLL with its own CRT, and which one it reads is not contractual. +#ifdef OS_IS_WINDOWS + SetEnvironmentVariableA("XILINX_XRT", exeDir.c_str()); + _putenv_s("XILINX_XRT", exeDir.c_str()); +#else + setenv("XILINX_XRT", exeDir.c_str(), 1); +#endif + + if(current.size() > 0) + return "XILINX_XRT was " + current + ", which has no " + kRuntimeLib + + "; repointed at " + exeDir; + return "XILINX_XRT set to " + exeDir; +} + +} // namespace + +string RyzenAIDevice::ensureRuntimeLibraryPath() { + // Only the first call changes anything. Later callers are logging paths, and + // caching means they report the repair that actually happened rather than the + // already-repaired state, which reads as if nothing had been wrong. + static const string description = repointXrtIfNeeded(); + return description; +} + +RyzenAIDevice::Arch RyzenAIDevice::archOfDevice(int deviceIdx) { + try { + xrt::device device((unsigned int)(deviceIdx < 0 ? 0 : deviceIdx)); + return archOfDeviceName(device.get_info()); + } + catch(const std::exception&) { + return Arch::Unknown; + } +} + +vector RyzenAIDevice::enumerate() { + vector devices; + unsigned int numDevices = 0; + try { + numDevices = xrt::system::enumerate_devices(); + } + catch(const std::exception&) { + // No driver, no device, or an XRT that cannot talk to it. Not an error + // here - the caller reports "none found". + return devices; + } + + for(unsigned int i = 0; i < numDevices; i++) { + Info info; + info.index = (int)i; + info.arch = Arch::Unknown; + try { + xrt::device device(i); + info.name = device.get_info(); + info.bdf = device.get_info(); + info.arch = archOfDeviceName(info.name); + } + catch(const std::exception& e) { + // Report the device as present but undescribable rather than dropping it, + // so that a device that exists-but-is-busy is still visible to the user. + info.name = string("(could not query: ") + e.what() + ")"; + } + devices.push_back(info); + } + return devices; +} + +string RyzenAIDevice::describeRuntime() { + vector devices = enumerate(); + if(devices.size() <= 0) + return string( + "No NPU devices found by XRT. Check that the AMD NPU driver is installed and that the NPU is " + "enabled in the BIOS." + ); + + string ret = "Found " + Global::uint64ToString((uint64_t)devices.size()) + " NPU device(s):"; + for(size_t i = 0; i < devices.size(); i++) { + ret += "\n Device " + Global::intToString(devices[i].index) + ": " + devices[i].name + + (devices[i].bdf.size() > 0 ? (" [" + devices[i].bdf + "]") : string("")); + if(devices[i].arch == Arch::Unknown) + ret += " - unrecognized architecture, NPU acceleration unavailable (will use the CPU reference path)"; + else + ret += " - " + string(archName(devices[i].arch)) + ", up to " + + Global::intToString(maxColumns(devices[i].arch)) + " columns"; + } + return ret; +} + +string RyzenAIDevice::resolveArtifactDir(const string& configuredDir) { + if(configuredDir.size() > 0) + return configuredDir; + + // Kernel artifacts are deployed next to the executable, so that an install is + // just exe + dlls + this directory. + vector dirs = HomeData::getDefaultFilesDirs(); + if(dirs.size() > 0) { + gfs::path p = gfs::u8path(dirs[0]) / "ryzenai"; + return p.u8string(); + } + return string("ryzenai"); +} + +vector RyzenAIDevice::listXclbins(const string& dir) { + vector names; + try { + gfs::path p = gfs::u8path(dir); + if(!gfs::exists(p) || !gfs::is_directory(p)) + return names; + // Artifacts are grouped into per-dtype subdirectories (bf16/, ...), so + // recurse and report paths relative to dir rather than bare filenames. + for(const auto& entry : gfs::recursive_directory_iterator(p)) { + if(!gfs::is_regular_file(entry.path())) + continue; + string filename = entry.path().filename().u8string(); + if(Global::isSuffix(Global::toLower(filename), ".xclbin")) + names.push_back(gfs::relative(entry.path(), p).generic_u8string()); + } + } + catch(const std::exception&) { + // An unreadable directory is equivalent to an empty one for our purposes. + return names; + } + std::sort(names.begin(), names.end()); + return names; +} diff --git a/cpp/neuralnet/ryzenaidevice.h b/cpp/neuralnet/ryzenaidevice.h new file mode 100644 index 000000000..0bb53872b --- /dev/null +++ b/cpp/neuralnet/ryzenaidevice.h @@ -0,0 +1,82 @@ +/* + * XRT device discovery and NPU kernel-artifact (xclbin) location for the + * RyzenAI backend. + * + * This layer is deliberately the ONLY place that includes XRT headers, so that + * the rest of the backend can be built and reasoned about without them. + */ + +#ifndef NEURALNET_RYZENAI_DEVICE_H_ +#define NEURALNET_RYZENAI_DEVICE_H_ + +#include +#include + +namespace RyzenAIDevice { + + // AIE architecture family. Kernel binaries are per-family and NOT + // interchangeable: XDNA2 cores run the aie2p ISA, XDNA1 cores run aie2, so an + // xclbin built for one will not load on the other. The families also differ in + // width - XDNA1 exposes 4 columns (16 compute tiles) to the toolchain, XDNA2 + // exposes 8 (32 tiles) - and only XDNA2 supports the BFP16 path. + enum class Arch { Unknown, NPU1, NPU2 }; + + // Largest column count the toolchain can target for a family, which is also + // the widest artifact variant we ship for it. + int maxColumns(Arch arch); + const char* archName(Arch arch); // "npu1" / "npu2" / "unknown" + + struct Info { + int index; + std::string name; // e.g. "NPU Strix" + std::string bdf; // e.g. "00c2:00:01.1" + Arch arch; + }; + + // Classifies a device by the product name XRT reports. Substring matching is + // all that is available: XRT exposes no architecture field, so new silicon + // will read as Unknown until its name is added here (which degrades to the CPU + // reference path rather than loading a wrong-ISA xclbin). + Arch archOfDeviceName(const std::string& name); + + // Architecture of one device, or Unknown if it cannot be opened/classified. + // deviceIdx < 0 selects the default device. + Arch archOfDevice(int deviceIdx); + + // Makes XRT able to find its own runtime libraries, and must be called before + // any other function here. + // + // XRT resolves xrt_core from $XILINX_XRT. The Windows XRT *SDK* installs only + // headers and import libraries under that path - the runtime DLLs live in the + // driver store and are shipped next to katago.exe - so a machine where + // XILINX_XRT points at the SDK (the natural thing to do when building) has + // every XRT call fail with "No such library ...\\xrt_core.dll", which surfaces + // as "no NPU devices found" rather than as anything pointing at the cause. + // + // If the variable is unset or points somewhere without xrt_core, and the DLL + // is present beside the executable, this repoints it there. Returns a + // description of what it did, for logging; never throws. + std::string ensureRuntimeLibraryPath(); + + // Enumerates NPU devices visible to XRT. Never throws: on any XRT failure it + // returns an empty vector, since callers (notably printDevices) must stay + // usable on machines with no NPU or no driver. + std::vector enumerate(); + + // Human-readable one-line summary of the XRT/driver stack, e.g. for logging. + // Returns an explanatory string rather than throwing if XRT is unavailable. + std::string describeRuntime(); + + // Directory holding the NPU kernel binaries. Resolution order: + // 1. configuredDir, if non-empty (the ryzenaiArtifactDir config key) + // 2. "/ryzenai" + // The directory is not required to exist; callers decide how to react. + std::string resolveArtifactDir(const std::string& configuredDir); + + // Names (not full paths) of the *.xclbin files found directly under dir, or + // an empty vector if dir does not exist. Sorted, for reproducible logging. + std::vector listXclbins(const std::string& dir); + +} // namespace RyzenAIDevice + +#endif // NEURALNET_RYZENAI_DEVICE_H_ diff --git a/cpp/neuralnet/ryzenaikernel.cpp b/cpp/neuralnet/ryzenaikernel.cpp new file mode 100644 index 000000000..1e4a4d782 --- /dev/null +++ b/cpp/neuralnet/ryzenaikernel.cpp @@ -0,0 +1,738 @@ +#include "../neuralnet/ryzenaikernel.h" + +#include +#include +#if defined(_M_X64) || defined(__x86_64__) || defined(__SSE2__) +#define RYZENAI_BF16_SSE2 1 +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "../core/fileutils.h" +#include "../core/global.h" +#include "../neuralnet/ryzenaimanifest.h" +#include "../neuralnet/ryzenaisequence.h" + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4100 4245 4267 4996) +#endif +#include "xrt/xrt_bo.h" +#include "xrt/xrt_device.h" +#include "xrt/xrt_hw_context.h" +#include "xrt/xrt_kernel.h" +#include "xrt/experimental/xrt_xclbin.h" +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#include "../external/filesystem-1.5.8/include/ghc/filesystem.hpp" + +namespace gfs = ghc::filesystem; + +using namespace std; + +namespace { + + string variantDir( + const string& artifactDir, RyzenAIKernel::Dtype dtype, RyzenAIDevice::Arch arch, int cols, + bool swiglu = false) { + return (gfs::u8path(artifactDir) / RyzenAIKernel::dtypeName(dtype) / + (string(RyzenAIDevice::archName(arch)) + "_" + Global::intToString(cols) + "col" + + (swiglu ? "_swiglu" : ""))) + .u8string(); + } + + // Artifact file names carry the shape they were compiled at. Only K matters + // to the binary, so the K is parsed out and the rest ignored -- which also + // means the older gemm_bf16_MKN names and a plain gemm_bf16_K + // both resolve correctly. + bool parseKFromStem(const string& stem, int& kOut) { + const size_t at = stem.rfind('K'); + if(at == string::npos) + return false; + size_t end = at + 1; + while(end < stem.size() && stem[end] >= '0' && stem[end] <= '9') + end++; + if(end == at + 1) + return false; + try { + kOut = Global::stringToInt(stem.substr(at + 1, end - at - 1)); + } + catch(const std::exception&) { + return false; + } + return kOut > 0; + } + + // The grid names artifacts by the only dimension that matters to the binary. + bool isCanonicalStem(const string& stem, int k) { + return stem == "gemm_bf16_K" + Global::intToString(k); + } + + // K -> xclbin path for one variant directory. + map scanVariant(const string& dir) { + map byK; + std::set canonical; + std::error_code ec; + if(!gfs::is_directory(gfs::u8path(dir), ec)) + return byK; + for(auto& entry : gfs::directory_iterator(gfs::u8path(dir), ec)) { + if(!entry.is_regular_file(ec)) + continue; + const gfs::path p = entry.path(); + if(p.extension().u8string() != ".xclbin") + continue; + const string stem = p.stem().u8string(); + int k = 0; + if(!parseKFromStem(stem, k)) + continue; + // Older artifacts are named for the full shape they happened to be + // compiled at, which can collide with a grid entry for the same K. Both + // are correct binaries, but prefer the grid's so the choice does not + // depend on directory order. + const bool canon = isCanonicalStem(stem, k); + if(canon || byK.find(k) == byK.end()) { + if(canon || canonical.find(k) == canonical.end()) + byK[k] = p.u8string(); + if(canon) + canonical.insert(k); + } + } + return byK; + } + + // mlir-aie appends a generated suffix to the kernel name, so match on the + // prefix over what the xclbin actually declares rather than assuming a + // literal name. + string findKernelName(const xrt::xclbin& xclbin, const string& prefix) { + for(const auto& kernel : xclbin.get_kernels()) { + string name = kernel.get_name(); + if(name.rfind(prefix, 0) == 0) + return name; + } + return string(); + } + + int roundUpTo(int v, int q) { + return ((v + q - 1) / q) * q; + } + +} // namespace + +struct RyzenAIKernel::Engine { + RyzenAIKernel::EngineInfo info; + RyzenAISequence::Arch seqArch = RyzenAISequence::Arch::NPU2; + + xrt::device device; + xrt::xclbin xclbin; + xrt::hw_context context; + xrt::kernel kernel; + + // Scratch grown on demand. A and C are per-dispatch; the instruction stream + // changes whenever (M, N) changes, so it is uploaded per dispatch too, but + // only re-generated when the shape actually differs from the last one. + xrt::bo boInstr; + xrt::bo boA; + xrt::bo boC; + size_t capInstrBytes = 0; + size_t capABytes = 0; + size_t capCBytes = 0; + + vector instr; + int lastM = 0; + int lastN = 0; + + // Bumped whenever a scratch BO is reallocated, so cached runs know their + // bound arguments are stale. + uint64_t bufferGeneration = 0; + + RyzenAIKernel::Timings timings; +}; + +struct RyzenAIKernel::Weights { + xrt::bo bo; + int paddedN = 0; + size_t bytes = 0; // K * paddedN * sizeof(uint16_t), for rewriteWeights + + // Building an xrt::run and binding six arguments costs about as much as the + // GEMM itself at these sizes, and the binding only changes when a scratch BO + // moves, so the run is cached per weight set. + xrt::run run; + bool runValid = false; + uint64_t runGeneration = 0; + uint32_t lastNumInstr = 0; +}; + +struct RyzenAIKernel::Op { + xrt::device device; + xrt::xclbin xclbin; + xrt::hw_context context; + xrt::kernel kernel; + xrt::bo boInstr; + std::vector boIns; + xrt::bo boC; + xrt::run run; + std::vector inBytes; + size_t bytesC = 0; +}; + +void RyzenAIKernel::floatToBf16Bulk(const float* src, uint16_t* dst, size_t n) { + size_t i = 0; +#ifdef RYZENAI_BF16_SSE2 + const __m128i expMask = _mm_set1_epi32(0x7F800000); + const __m128i mantMask = _mm_set1_epi32(0x007FFFFF); + const __m128i one = _mm_set1_epi32(1); + const __m128i bias = _mm_set1_epi32(0x7FFF); + const __m128i quiet = _mm_set1_epi32(0x0040); + const __m128i zero = _mm_setzero_si128(); + // Packing 32-bit lanes down to 16 has no unsigned form in SSE2, so shift the + // values into the signed range first and shift them back afterwards. Every + // value is in [0, 0xFFFF] by then, so the bias lands them exactly inside + // int16 and the saturating pack never actually saturates. + const __m128i packBias = _mm_set1_epi32(0x8000); + const __m128i unBias = _mm_set1_epi16((short)0x8000); + + auto round4 = [&](const float* p) { + const __m128i bits = _mm_loadu_si128(reinterpret_cast(p)); + const __m128i isExpAllOnes = _mm_cmpeq_epi32(_mm_and_si128(bits, expMask), expMask); + const __m128i mantIsZero = _mm_cmpeq_epi32(_mm_and_si128(bits, mantMask), zero); + const __m128i isNan = _mm_andnot_si128(mantIsZero, isExpAllOnes); + const __m128i lsb = _mm_and_si128(_mm_srli_epi32(bits, 16), one); + const __m128i rounded = + _mm_srli_epi32(_mm_add_epi32(_mm_add_epi32(bits, bias), lsb), 16); + const __m128i nanVal = _mm_or_si128(_mm_srli_epi32(bits, 16), quiet); + return _mm_or_si128(_mm_and_si128(isNan, nanVal), _mm_andnot_si128(isNan, rounded)); + }; + + for(; i + 8 <= n; i += 8) { + const __m128i lo = _mm_sub_epi32(round4(src + i), packBias); + const __m128i hi = _mm_sub_epi32(round4(src + i + 4), packBias); + _mm_storeu_si128( + reinterpret_cast<__m128i*>(dst + i), _mm_add_epi16(_mm_packs_epi32(lo, hi), unBias)); + } +#endif + for(; i < n; i++) + dst[i] = floatToBf16(src[i]); +} + +const char* RyzenAIKernel::dtypeName(Dtype dtype) { + return dtype == Dtype::Bfp16 ? "bfp16" : "bf16"; +} + +bool RyzenAIKernel::parseDtype(const string& s, Dtype& out) { + const string lowered = Global::toLower(Global::trim(s)); + if(lowered == "auto") { out = Dtype::Auto; return true; } + if(lowered == "bf16") { out = Dtype::Bf16; return true; } + if(lowered == "bfp16") { out = Dtype::Bfp16; return true; } + return false; +} + +RyzenAIKernel::Dtype RyzenAIKernel::resolveDtype(Dtype requested, RyzenAIDevice::Arch arch) { + if(requested != Dtype::Auto) + return requested; + + // Auto means BFP16 where the hardware has it, which is XDNA2 only. + // + // A single BFP16 GEMM carries roughly 3% relative error against a float32 + // reference, against ~2e-5 for bf16, and that gap is what kept the default on + // bf16 until a whole network could be measured. It now has been, and the + // compounding turns out to be mild: over the ~160 chained GEMMs of an + // evaluation, BFP16 lands within about 1.3-2x of bf16's deviation from the + // CPU reference rather than anywhere near 1000x (b10c384h6 policy mean + // 4.1e-4 vs 2.5e-4; b28c512nbt 2.4e-4 vs 1.8e-4), and the policy top-10 set + // is identical for both formats on both models. The per-GEMM error is input + // quantisation, not accumulation - the accumulator is fp32 either way - so it + // does not compound the way a truncated accumulator would. + // + // ryzenaiDtype = bf16 forces the more accurate format for anyone who wants + // it, and is still the only option on XDNA1. + if(arch == RyzenAIDevice::Arch::NPU2) + return Dtype::Bfp16; + return Dtype::Bf16; +} + +int RyzenAIKernel::padM(const EngineInfo& info, int want) { + // One pass over the 4 double-buffered AIE rows consumes tileM*8 rows. + return roundUpTo(std::max(want, 1), info.tileM * 8); +} + +int RyzenAIKernel::padN(const EngineInfo& info, int want) { + return roundUpTo(std::max(want, 1), info.tileN * info.cols); +} + +namespace { + + bool readWholeFile(const string& path, vector& out) { + try { + if(!FileUtils::exists(path)) + return false; + ifstream in; + FileUtils::open(in, path, ios::in | ios::binary | ios::ate); + streamsize size = in.tellg(); + if(size < 0) + return false; + in.seekg(0, ios::beg); + out.resize((size_t)size); + if(size > 0) + in.read(out.data(), size); + return in.good() || in.eof(); + } + catch(const std::exception&) { + return false; + } + } + + // One attempt at one (dtype, arch, cols). Picks the smallest available K that + // is >= the requested one. With swiglu set, scans the SwiGLU-epilogue + // variant's directory instead (same naming, gemm_swiglu_bf16_K stems). + RyzenAIKernel::Engine* tryLoadVariant( + const string& artifactDir, int deviceIdx, RyzenAIKernel::Dtype dtype, + RyzenAIDevice::Arch arch, int cols, int K, bool swiglu, string& err + ) { + err.clear(); + const map byK = scanVariant(variantDir(artifactDir, dtype, arch, cols, swiglu)); + auto it = byK.lower_bound(K); + if(it == byK.end()) { + err = "no artifact with reduction dim >= " + Global::intToString(K) + " at " + + Global::intToString(cols) + " column(s)"; + return nullptr; + } + + try { + unique_ptr engine(new RyzenAIKernel::Engine()); + engine->info.K = it->first; + engine->info.cols = cols; + engine->info.dtype = dtype; + // Every artifact in the set is built from the same whole_array design. + // tileN 48 only appears on shapes whose N is a multiple of 48, and the + // grid is compiled at tileN 32 throughout; manifest.json records the + // actual geometry if that ever stops being true. + engine->info.tileM = RyzenAIManifest::GEMM_TILE_M; + engine->info.tileK = RyzenAIManifest::GEMM_TILE_K; + engine->info.tileN = RyzenAIManifest::GEMM_TILE_N; + engine->seqArch = (arch == RyzenAIDevice::Arch::NPU1) ? RyzenAISequence::Arch::NPU1 + : RyzenAISequence::Arch::NPU2; + + if(!RyzenAISequence::supportsColumns(cols)) { + err = "no instruction-stream layout for " + Global::intToString(cols) + " column(s)"; + return nullptr; + } + + engine->device = xrt::device((unsigned int)(deviceIdx < 0 ? 0 : deviceIdx)); + engine->xclbin = xrt::xclbin(it->second); + + const string kernelName = findKernelName(engine->xclbin, RyzenAIManifest::KERNEL_NAME_PREFIX); + if(kernelName.size() <= 0) { + err = "no kernel named " + string(RyzenAIManifest::KERNEL_NAME_PREFIX) + "* in " + it->second; + return nullptr; + } + + engine->device.register_xclbin(engine->xclbin); + engine->context = xrt::hw_context(engine->device, engine->xclbin.get_uuid()); + engine->kernel = xrt::kernel(engine->context, kernelName); + return engine.release(); + } + catch(const std::exception& e) { + err = string("XRT failed to load ") + it->second + ": " + e.what(); + return nullptr; + } + } + +} // namespace + +namespace { + + RyzenAIKernel::Engine* loadEngineImpl( + const string& artifactDir, int deviceIdx, RyzenAIKernel::Dtype dtype, int K, int maxCols, + bool swiglu, RyzenAIKernel::EngineInfo& infoOut, string& err + ) { + err.clear(); + + const RyzenAIDevice::Arch arch = RyzenAIDevice::archOfDevice(deviceIdx); + if(arch == RyzenAIDevice::Arch::Unknown) { + err = "NPU architecture could not be determined, so no kernel binary can be selected"; + return nullptr; + } + const RyzenAIKernel::Dtype resolved = RyzenAIKernel::resolveDtype(dtype, arch); + + int startCols = RyzenAIDevice::maxColumns(arch); + if(maxCols > 0) + startCols = std::min(startCols, maxCols); + + string lastErr; + for(int cols = startCols; cols >= 1; cols /= 2) { + string variantErr; + RyzenAIKernel::Engine* engine = + tryLoadVariant(artifactDir, deviceIdx, resolved, arch, cols, K, swiglu, variantErr); + if(engine != nullptr) { + infoOut = engine->info; + return engine; + } + if(lastErr.size() <= 0) + lastErr = variantErr; + } + + err = string("no usable ") + RyzenAIKernel::dtypeName(resolved) + + (swiglu ? " swiglu-epilogue" : "") + " kernel for K=" + Global::intToString(K) + + " on " + RyzenAIDevice::archName(arch) + " (" + lastErr + ")"; + return nullptr; + } + +} // namespace + +RyzenAIKernel::Engine* RyzenAIKernel::loadEngine( + const string& artifactDir, int deviceIdx, Dtype dtype, int K, int maxCols, + EngineInfo& infoOut, string& err +) { + return loadEngineImpl(artifactDir, deviceIdx, dtype, K, maxCols, false, infoOut, err); +} + +RyzenAIKernel::Engine* RyzenAIKernel::loadEngineSwiglu( + const string& artifactDir, int deviceIdx, Dtype dtype, int K, int maxCols, + EngineInfo& infoOut, string& err +) { + return loadEngineImpl(artifactDir, deviceIdx, dtype, K, maxCols, true, infoOut, err); +} + +void RyzenAIKernel::freeEngine(Engine* engine) { + delete engine; +} + +const RyzenAIKernel::EngineInfo& RyzenAIKernel::engineInfo(const Engine* engine) { + return engine->info; +} + +const RyzenAIKernel::Timings& RyzenAIKernel::engineTimings(const Engine* engine) { + return engine->timings; +} + +RyzenAIKernel::Weights* RyzenAIKernel::uploadWeights( + Engine* engine, int paddedN, const uint16_t* B, string& err) { + err.clear(); + try { + unique_ptr w(new Weights()); + w->paddedN = paddedN; + w->bytes = (size_t)engine->info.K * (size_t)paddedN * sizeof(uint16_t); + w->bo = xrt::bo( + engine->device, w->bytes, XRT_BO_FLAGS_HOST_ONLY, + engine->kernel.group_id(RyzenAIManifest::ARG_B)); + std::memcpy(w->bo.map(), B, w->bytes); + w->bo.sync(XCL_BO_SYNC_BO_TO_DEVICE); + return w.release(); + } + catch(const std::exception& e) { + err = string("XRT failed to upload weights: ") + e.what(); + return nullptr; + } +} + +void RyzenAIKernel::freeWeights(Weights* weights) { + delete weights; +} + +void RyzenAIKernel::rewriteWeights(Weights* weights, const uint16_t* B) { + std::memcpy(weights->bo.map(), B, weights->bytes); + weights->bo.sync(XCL_BO_SYNC_BO_TO_DEVICE); +} + +RyzenAIKernel::Op* RyzenAIKernel::loadOp( + const string& xclbinPath, const string& instsPath, int deviceIdx, + const size_t* inBytes, int numIns, size_t bytesC, string& err) { + err.clear(); + + vector insts; + if(!readWholeFile(instsPath, insts) || insts.empty()) { + err = "no instruction stream at " + instsPath; + return nullptr; + } + + try { + unique_ptr op(new Op()); + op->bytesC = bytesC; + op->device = xrt::device((unsigned int)(deviceIdx < 0 ? 0 : deviceIdx)); + op->xclbin = xrt::xclbin(xclbinPath); + + const string kernelName = findKernelName(op->xclbin, RyzenAIManifest::KERNEL_NAME_PREFIX); + if(kernelName.empty()) { + err = "no kernel named " + string(RyzenAIManifest::KERNEL_NAME_PREFIX) + "* in " + xclbinPath; + return nullptr; + } + + op->device.register_xclbin(op->xclbin); + op->context = xrt::hw_context(op->device, op->xclbin.get_uuid()); + op->kernel = xrt::kernel(op->context, kernelName); + + op->boInstr = xrt::bo( + op->device, insts.size(), XCL_BO_FLAGS_CACHEABLE, + op->kernel.group_id(RyzenAIManifest::ARG_INSTR)); + op->inBytes.assign(inBytes, inBytes + numIns); + for(int j = 0; j < numIns; j++) + op->boIns.emplace_back( + op->device, inBytes[j], XRT_BO_FLAGS_HOST_ONLY, + op->kernel.group_id(RyzenAIManifest::ARG_A + j)); + op->boC = xrt::bo( + op->device, bytesC, XRT_BO_FLAGS_HOST_ONLY, + op->kernel.group_id(RyzenAIManifest::ARG_A + numIns)); + std::memcpy(op->boInstr.map(), insts.data(), insts.size()); + op->boInstr.sync(XCL_BO_SYNC_BO_TO_DEVICE); + + // Every argument is fixed for the op's lifetime, so the run is built once. + op->run = xrt::run(op->kernel); + op->run.set_arg(RyzenAIManifest::ARG_OPCODE, RyzenAIManifest::OPCODE_START_WITH_INSTRUCTIONS); + op->run.set_arg(RyzenAIManifest::ARG_INSTR, op->boInstr); + op->run.set_arg(RyzenAIManifest::ARG_NINSTR, (uint32_t)(insts.size() / sizeof(uint32_t))); + for(int j = 0; j < numIns; j++) + op->run.set_arg(RyzenAIManifest::ARG_A + j, op->boIns[j]); + op->run.set_arg(RyzenAIManifest::ARG_A + numIns, op->boC); + return op.release(); + } + catch(const std::exception& e) { + err = string("XRT failed to load op ") + xclbinPath + ": " + e.what(); + return nullptr; + } +} + +void RyzenAIKernel::freeOp(Op* op) { + delete op; +} + +void RyzenAIKernel::runOp(Op* op, const void* const* ins, int numIns, void* C) { + try { + for(int j = 0; j < numIns && j < (int)op->boIns.size(); j++) { + std::memcpy(op->boIns[j].map(), ins[j], op->inBytes[j]); + op->boIns[j].sync(XCL_BO_SYNC_BO_TO_DEVICE); + } + op->run.start(); + ert_cmd_state state = op->run.wait(); + if(state != ERT_CMD_STATE_COMPLETED) + throw StringError( + "RyzenAI op dispatch did not complete, ERT state " + Global::intToString((int)state)); + op->boC.sync(XCL_BO_SYNC_BO_FROM_DEVICE); + std::memcpy(C, op->boC.map(), op->bytesC); + } + catch(const StringError&) { + throw; + } + catch(const std::exception& e) { + throw StringError(string("RyzenAI op dispatch failed: ") + e.what()); + } +} + +void RyzenAIKernel::runGemm( + Engine* engine, Weights* weights, int paddedM, int paddedN, const uint16_t* A, float* C) { + try { + const EngineInfo& info = engine->info; + if(paddedN != weights->paddedN) + throw StringError( + "RyzenAI GEMM: N=" + Global::intToString(paddedN) + " does not match the uploaded " + + "weight width " + Global::intToString(weights->paddedN)); + + if(paddedM != engine->lastM || paddedN != engine->lastN) { + engine->instr = RyzenAISequence::generateSequence( + engine->seqArch, info.cols, paddedM, info.K, paddedN, info.tileM, info.tileK, info.tileN); + engine->lastM = paddedM; + engine->lastN = paddedN; + const size_t instrBytes = engine->instr.size() * sizeof(uint32_t); + if(instrBytes > engine->capInstrBytes) { + engine->boInstr = xrt::bo( + engine->device, instrBytes, XCL_BO_FLAGS_CACHEABLE, + engine->kernel.group_id(RyzenAIManifest::ARG_INSTR)); + engine->capInstrBytes = instrBytes; + } + std::memcpy(engine->boInstr.map(), engine->instr.data(), instrBytes); + engine->boInstr.sync(XCL_BO_SYNC_BO_TO_DEVICE); + } + + const size_t bytesA = (size_t)paddedM * (size_t)info.K * sizeof(uint16_t); + const size_t bytesC = (size_t)paddedM * (size_t)paddedN * sizeof(float); + if(bytesA > engine->capABytes) { + engine->boA = xrt::bo( + engine->device, bytesA, XRT_BO_FLAGS_HOST_ONLY, + engine->kernel.group_id(RyzenAIManifest::ARG_A)); + engine->capABytes = bytesA; + engine->bufferGeneration++; + } + if(bytesC > engine->capCBytes) { + engine->boC = xrt::bo( + engine->device, bytesC, XRT_BO_FLAGS_HOST_ONLY, + engine->kernel.group_id(RyzenAIManifest::ARG_C)); + engine->capCBytes = bytesC; + engine->bufferGeneration++; + } + + const auto tUpload = std::chrono::steady_clock::now(); + std::memcpy(engine->boA.map(), A, bytesA); + engine->boA.sync(XCL_BO_SYNC_BO_TO_DEVICE); + const auto tExec = std::chrono::steady_clock::now(); + + if(!weights->runValid || weights->runGeneration != engine->bufferGeneration) { + weights->run = xrt::run(engine->kernel); + weights->run.set_arg( + RyzenAIManifest::ARG_OPCODE, RyzenAIManifest::OPCODE_START_WITH_INSTRUCTIONS); + weights->run.set_arg(RyzenAIManifest::ARG_INSTR, engine->boInstr); + weights->run.set_arg(RyzenAIManifest::ARG_A, engine->boA); + weights->run.set_arg(RyzenAIManifest::ARG_B, weights->bo); + weights->run.set_arg(RyzenAIManifest::ARG_C, engine->boC); + weights->runValid = true; + weights->runGeneration = engine->bufferGeneration; + weights->lastNumInstr = 0; + } + // The instruction count is the one argument that tracks the shape. + if(weights->lastNumInstr != (uint32_t)engine->instr.size()) { + weights->run.set_arg(RyzenAIManifest::ARG_NINSTR, (uint32_t)engine->instr.size()); + weights->lastNumInstr = (uint32_t)engine->instr.size(); + } + + weights->run.start(); + ert_cmd_state state = weights->run.wait(); + const auto tDownload = std::chrono::steady_clock::now(); + if(state != ERT_CMD_STATE_COMPLETED) + throw StringError( + "RyzenAI GEMM dispatch did not complete, ERT state " + Global::intToString((int)state)); + + engine->boC.sync(XCL_BO_SYNC_BO_FROM_DEVICE); + std::memcpy(C, engine->boC.map(), bytesC); + + const auto tEnd = std::chrono::steady_clock::now(); + using Secs = std::chrono::duration; + engine->timings.secsUploadA += Secs(tExec - tUpload).count(); + engine->timings.secsExecute += Secs(tDownload - tExec).count(); + engine->timings.secsDownloadC += Secs(tEnd - tDownload).count(); + engine->timings.numDispatches++; + } + catch(const StringError&) { + throw; + } + catch(const std::exception& e) { + throw StringError(string("RyzenAI GEMM dispatch failed: ") + e.what()); + } +} + +vector RyzenAIKernel::listGemmK(const string& artifactDir) { + std::set ks; + std::error_code ec; + const gfs::path root = gfs::u8path(artifactDir); + if(!gfs::is_directory(root, ec)) + return vector(); + for(auto& entry : gfs::recursive_directory_iterator(root, ec)) { + if(!entry.is_regular_file(ec)) + continue; + const gfs::path p = entry.path(); + if(p.extension().u8string() != ".xclbin") + continue; + const string stem = p.stem().u8string(); + // The swiglu-epilogue variants share the K-suffixed naming but are a + // different operator; they must not advertise a plain-GEMM K. + if(stem.rfind("gemm_swiglu_", 0) == 0) + continue; + int k = 0; + if(parseKFromStem(stem, k)) + ks.insert(k); + } + return vector(ks.begin(), ks.end()); +} + +vector RyzenAIKernel::listSwigluK(const string& artifactDir) { + std::set ks; + std::error_code ec; + const gfs::path root = gfs::u8path(artifactDir); + if(!gfs::is_directory(root, ec)) + return vector(); + for(auto& entry : gfs::recursive_directory_iterator(root, ec)) { + if(!entry.is_regular_file(ec)) + continue; + const gfs::path p = entry.path(); + if(p.extension().u8string() != ".xclbin") + continue; + const string stem = p.stem().u8string(); + if(stem.rfind("gemm_swiglu_", 0) != 0) + continue; + int k = 0; + if(parseKFromStem(stem, k)) + ks.insert(k); + } + return vector(ks.begin(), ks.end()); +} + +string RyzenAIKernel::selfTest(const string& artifactDir, int deviceIdx) { + string out = "RyzenAI NPU self-test:"; + const vector ks = listGemmK(artifactDir); + if(ks.empty()) + return out + " no artifacts found under " + artifactDir; + + std::mt19937 rng(12345); + std::uniform_real_distribution dist(-1.0f, 1.0f); + + for(size_t i = 0; i < ks.size(); i++) { + const int K = ks[i]; + EngineInfo info; + string err; + Engine* engine = loadEngine(artifactDir, deviceIdx, Dtype::Auto, K, 0, info, err); + if(engine == nullptr) { + out += "\n K=" + Global::intToString(K) + ": LOAD FAILED (" + err + ")"; + continue; + } + + try { + // A board's worth of rows and a typical layer width, padded as a real + // dispatch would be. + const int M = padM(info, 361); + const int N = padN(info, 512); + vector A((size_t)M * info.K); + vector B((size_t)info.K * N); + for(size_t j = 0; j < A.size(); j++) A[j] = floatToBf16(dist(rng)); + for(size_t j = 0; j < B.size(); j++) B[j] = floatToBf16(dist(rng)); + vector C((size_t)M * N, 0.0f); + + Weights* w = uploadWeights(engine, N, B.data(), err); + if(w == nullptr) { + out += "\n K=" + Global::intToString(K) + ": " + err; + freeEngine(engine); + continue; + } + + runGemm(engine, w, M, N, A.data(), C.data()); + + // Spot-check a sample of C: a wrong descriptor field produces gross + // garbage, never a subtle drift, so full recomputation buys nothing. + double maxErr = 0.0; + std::mt19937 pick(7); + for(int t = 0; t < 200; t++) { + const int r = (int)(pick() % (unsigned)M); + const int c = (int)(pick() % (unsigned)N); + double acc = 0.0; + for(int k = 0; k < info.K; k++) + acc += (double)bf16ToFloat(A[(size_t)r * info.K + k]) * + bf16ToFloat(B[(size_t)k * N + c]); + maxErr = std::max(maxErr, std::fabs(acc - C[(size_t)r * N + c])); + } + + const int iters = 20; + auto t0 = std::chrono::steady_clock::now(); + for(int t = 0; t < iters; t++) + runGemm(engine, w, M, N, A.data(), C.data()); + auto t1 = std::chrono::steady_clock::now(); + const double ms = std::chrono::duration(t1 - t0).count() / iters; + + char line[256]; + std::snprintf( + line, sizeof(line), "\n K=%-5d %s %dcol M=%d N=%d %.3f ms %.1f GFLOP/s maxAbsErr=%.3g %s", + info.K, dtypeName(info.dtype), info.cols, M, N, ms, + 2.0 * M * info.K * N / (ms * 1e6), maxErr, maxErr < 0.5 ? "OK" : "FAILED"); + out += line; + + freeWeights(w); + } + catch(const std::exception& e) { + out += "\n K=" + Global::intToString(K) + ": THREW (" + e.what() + ")"; + } + freeEngine(engine); + } + return out; +} diff --git a/cpp/neuralnet/ryzenaikernel.h b/cpp/neuralnet/ryzenaikernel.h new file mode 100644 index 000000000..72e4323d5 --- /dev/null +++ b/cpp/neuralnet/ryzenaikernel.h @@ -0,0 +1,193 @@ +/* + * Loading and dispatch of the NPU kernel binaries (xclbin) produced by + * python/ryzenai_kernels/. + * + * Like device.{h,cpp}, this is one of the only places that includes XRT + * headers; callers deal in plain buffers. + * + * An .xclbin bakes in only the reduction dimension K (measured; see + * python/ryzenai_kernels/INSTS_FORMAT.md), so one binary serves every M and N -- the + * instruction stream that carries those is generated per dispatch by + * sequence.cpp. That is why the unit of loading here is a K, not a shape. + */ + +#ifndef NEURALNET_RYZENAI_KERNEL_H_ +#define NEURALNET_RYZENAI_KERNEL_H_ + +#include +#include +#include +#include + +#include "../neuralnet/ryzenaidevice.h" + +namespace RyzenAIKernel { + + // ---- bfloat16 ------------------------------------------------------------- + // bf16 is just the top 16 bits of an IEEE fp32, so conversion is a shift plus + // round-to-nearest-even. No lookup tables and no library needed. + + // Converts a whole run of floats, eight at a time where the hardware allows. + // Bit-for-bit what the element-wise version below produces, NaN handling + // included - it is the same arithmetic, just widened. Worth having as its own + // function because packing activations is a few percent of every evaluation: + // the branch on NaN keeps compilers from vectorising the obvious loop. + void floatToBf16Bulk(const float* src, uint16_t* dst, size_t n); + + inline uint16_t floatToBf16(float f) { + uint32_t bits; + static_assert(sizeof(bits) == sizeof(f), "float is not 32 bits"); + std::memcpy(&bits, &f, sizeof(bits)); + // NaN must stay NaN: rounding a quiet NaN's payload away could turn it into + // an infinity, so force the quiet bit instead of rounding. + if((bits & 0x7F800000u) == 0x7F800000u && (bits & 0x007FFFFFu) != 0u) + return (uint16_t)((bits >> 16) | 0x0040u); + const uint32_t roundingBias = 0x7FFFu + ((bits >> 16) & 1u); + return (uint16_t)((bits + roundingBias) >> 16); + } + + inline float bf16ToFloat(uint16_t b) { + uint32_t bits = (uint32_t)b << 16; + float f; + std::memcpy(&f, &bits, sizeof(f)); + return f; + } + + // ---- numeric format ------------------------------------------------------- + + // Bf16 runs the native bfloat16 MMUL. Bfp16 compiles the same bfloat16 kernel + // against AIE_API_EMULATE_BFLOAT16_MMUL_WITH_BFP16, which doubles the MMUL + // micro-kernel (measured 1.42x) and is XDNA2-only. The distinction is entirely + // inside the kernel: host buffers are bfloat16 in / float32 out either way, so + // only which artifact directory we load from changes. + enum class Dtype { Auto, Bf16, Bfp16 }; + + const char* dtypeName(Dtype dtype); // "bf16" / "bfp16" + + // Parses a ryzenaiDtype config value. Returns false for anything unrecognized. + bool parseDtype(const std::string& s, Dtype& out); + + // Resolves Auto against the hardware. See the implementation for why Auto is + // currently bf16 even where bfp16 is available. + Dtype resolveDtype(Dtype requested, RyzenAIDevice::Arch arch); + + // ---- engines -------------------------------------------------------------- + + // One loaded xclbin, bound to a device, computing C[M,N] = A[M,K] * B[K,N] + // with bfloat16 inputs and float32 accumulation for any M and N the shape + // rules below allow. K is fixed by the binary. + struct Engine; + + struct EngineInfo { + int K = 0; // the reduction dim this binary was compiled for + int cols = 0; // AIE columns acquired + int tileM = 0; // MMUL tile geometry, needed to pad M and N + int tileK = 0; + int tileN = 0; + Dtype dtype = Dtype::Bf16; + }; + + // Smallest M >= want that an instruction stream can express, and likewise for + // N. Callers zero-pad up to these; the extra rows and columns of C are + // computed and ignored. K is not paddable here -- pick an engine whose K is + // >= the layer's K and zero-pad A's columns and B's rows into it. + int padM(const EngineInfo& info, int want); + int padN(const EngineInfo& info, int want); + + // Loads the artifact for reduction dim K: an exact match if one exists, + // otherwise the smallest available K greater than it (the caller then + // zero-pads). Column counts are tried widest-first down to 1, since a device + // whose columns are partly claimed by another process should still get NPU + // acceleration rather than falling back to the CPU. maxCols caps that search; + // pass 0 for no cap. Wider is not always faster at small M -- see + // references/performance.md. + // + // Returns nullptr and fills err when nothing loads; that is an ordinary + // outcome (callers use the CPU reference path), not a fatal error. + Engine* loadEngine( + const std::string& artifactDir, + int deviceIdx, + Dtype dtype, + int K, + int maxCols, + EngineInfo& infoOut, + std::string& err + ); + void freeEngine(Engine* engine); + const EngineInfo& engineInfo(const Engine* engine); + + // Same as loadEngine, but loads the SwiGLU-epilogue variant of the GEMM + // (gemm_swiglu_bf16_K, in the _swiglu directories). That binary + // computes silu(l)*g on chip for B whose columns interleave two weight + // matrices in groups of 8; see python/ryzenai_kernels/gemm_swiglu_bf16.py. + // It is a separate xclbin and therefore a separate hardware context. + Engine* loadEngineSwiglu( + const std::string& artifactDir, + int deviceIdx, + Dtype dtype, + int K, + int maxCols, + EngineInfo& infoOut, + std::string& err + ); + + // Reduction dims for which a SwiGLU-epilogue artifact exists. Sorted. + std::vector listSwigluK(const std::string& artifactDir); + + // Device-resident B for one layer. Weights do not change between evaluations, + // so they are uploaded once and bound per dispatch. N is the padded width. + struct Weights; + Weights* uploadWeights(Engine* engine, int paddedN, const uint16_t* B, std::string& err); + void freeWeights(Weights* weights); + + // Rewrites the contents of an already-uploaded B in place. This is the path + // for operands that change every dispatch (attention keys/values, as opposed + // to layer weights): the BO itself does not move, so the xrt::run cached + // against it in runGemm stays valid and only a memcpy + sync is paid. + void rewriteWeights(Weights* weights, const uint16_t* B); + + // ---- standalone ops ------------------------------------------------------- + // A non-GEMM kernel (softmax, fused attention, ...) whose instruction stream + // is precompiled next to the xclbin -- unlike the engines nothing is + // generated at run time, so the op computes exactly the one shape it was + // compiled for. Same opcode-3 ABI as the GEMM except that the data args are + // arg3..arg3+numIns-1 = inputs and arg3+numIns = output. Buffer sizes are + // fixed at load. + struct Op; + Op* loadOp( + const std::string& xclbinPath, const std::string& instsPath, int deviceIdx, + const size_t* inBytes, int numIns, size_t bytesC, std::string& err); + void freeOp(Op* op); + // memcpy the inputs in, dispatch, memcpy the output out. ins[j] must point + // at inBytes[j] bytes. Throws StringError on a dispatch failure. + void runOp(Op* op, const void* const* ins, int numIns, void* C); + + // C[M,N] = A[M,K] * B[K,N], all row-major, with M and N already padded per + // padM/padN and A's row stride equal to the engine's K. Blocks until the NPU + // has finished. Throws StringError on a dispatch failure. + void runGemm( + Engine* engine, Weights* weights, int paddedM, int paddedN, const uint16_t* A, float* C); + + // Wall clock accumulated inside runGemm, split so that host<->device transfer + // can be told apart from the NPU's own execution. Deciding whether keeping + // activations resident on the device is worth it needs exactly this split. + struct Timings { + double secsUploadA = 0.0; + double secsExecute = 0.0; + double secsDownloadC = 0.0; + long long numDispatches = 0; + }; + const Timings& engineTimings(const Engine* engine); + + // Reduction dims for which an artifact exists under artifactDir, parsed from + // the filenames. Sorted, for reproducible logging. + std::vector listGemmK(const std::string& artifactDir); + + // Loads every available artifact, runs it against a plain-C++ GEMM on + // pseudorandom data, and times it. Returns a human-readable report; never + // throws, so it is safe to call from a logging path. + std::string selfTest(const std::string& artifactDir, int deviceIdx); + +} // namespace RyzenAIKernel + +#endif // NEURALNET_RYZENAI_KERNEL_H_ diff --git a/cpp/neuralnet/ryzenaimanifest.h b/cpp/neuralnet/ryzenaimanifest.h new file mode 100644 index 000000000..edb912372 --- /dev/null +++ b/cpp/neuralnet/ryzenaimanifest.h @@ -0,0 +1,56 @@ +/* + * ABI contract between the NPU kernel binaries under artifacts/ and this C++ + * host code. + * + * The kernel build (python/ryzenai_kernels/build_kernels.py) writes the + * same facts into artifacts/manifest.json. Both must agree: ABI_VERSION here is + * checked against the manifest's "manifest_version" at load time so that a + * mismatched pair fails loudly instead of computing garbage. + * + * None of this is shape information. M/K/N live in the per-shape instruction + * stream, not in the xclbin - see artifacts/README.md. + */ + +#ifndef NEURALNET_RYZENAI_MANIFEST_H_ +#define NEURALNET_RYZENAI_MANIFEST_H_ + +#include + +namespace RyzenAIManifest { + + // Bump together with "manifest_version" in artifacts/manifest.json whenever + // anything below changes. + constexpr int ABI_VERSION = 1; + + // mlir-aie names the xclbin's kernel with this prefix plus a generated + // suffix, so hosts must prefix-match over xclbin.get_kernels() rather than + // compare for equality (this mirrors what mlir-aie's own + // runtime_lib/test_lib/test_utils.cpp does). + constexpr const char* KERNEL_NAME_PREFIX = "MLIR_AIE"; + + // ERT opcode for "start kernel with instruction buffer". + constexpr uint32_t OPCODE_START_WITH_INSTRUCTIONS = 3; + + // xrt::run argument slots. + constexpr int ARG_OPCODE = 0; // scalar, OPCODE_START_WITH_INSTRUCTIONS + constexpr int ARG_INSTR = 1; // xrt::bo, cacheable, holds the .insts.bin bytes + constexpr int ARG_NINSTR = 2; // scalar, instruction length in 32-bit words + constexpr int ARG_A = 3; // xrt::bo, host_only, M*K bfloat16 row-major + constexpr int ARG_B = 4; // xrt::bo, host_only, K*N bfloat16 row-major + constexpr int ARG_C = 5; // xrt::bo, host_only, M*N float32 row-major + + // MMUL tile geometry the GEMM artifacts are compiled with, as recorded in + // artifacts/manifest.json. These drive the padding rules: M must be a + // multiple of GEMM_TILE_M*8 (one pass over 4 double-buffered AIE rows), N a + // multiple of GEMM_TILE_N*cols, and K a multiple of GEMM_TILE_K. + // + // A few early artifacts were compiled at tileN 48 because their N was 384; + // the grid is tileN 32 throughout, which divides every N the padding rules + // produce. + constexpr int GEMM_TILE_M = 32; + constexpr int GEMM_TILE_K = 64; + constexpr int GEMM_TILE_N = 32; + +} // namespace RyzenAIManifest + +#endif // NEURALNET_RYZENAI_MANIFEST_H_ diff --git a/cpp/neuralnet/ryzenaimatmul.cpp b/cpp/neuralnet/ryzenaimatmul.cpp new file mode 100644 index 000000000..9e7e61982 --- /dev/null +++ b/cpp/neuralnet/ryzenaimatmul.cpp @@ -0,0 +1,1504 @@ +#include "../neuralnet/ryzenaimatmul.h" + +#include +#include +#include +#include + +#include "../core/global.h" +#include "../neuralnet/desc.h" +#include "../neuralnet/ryzenaikernel.h" + +using namespace std; + +namespace RyzenAIMatMul { + +namespace { + + // One dense layer's device-resident weights, plus the engine that serves its + // reduction dim. Engines are shared between every layer with the same K. + struct Layer { + RyzenAIKernel::Engine* engine = nullptr; // not owned + RyzenAIKernel::Weights* weights = nullptr; + int K = 0; // the engine's K, >= inChannels + int paddedN = 0; // >= outChannels + bool usable = false; + string why; // set when !usable, for the report + }; + + // Everything tryAttention needs to route one attention block shape's QK^T + // and P*V GEMMs to the NPU. Unlike a Layer, the B operands (the K and V + // activations) change every evaluation, so the weights BOs are rewritten in + // place per dispatch via RyzenAIKernel::rewriteWeights. The engines are the + // same shared ones the dense layers use. + // + // All heads of one batch element go into ONE GEMM per direction, because a + // dispatch costs ~1 ms regardless of size while the multiply-accumulates are + // nearly free: A carries the per-head data side by side along the reduction + // dim and B is block-diagonal, so C comes out with the per-head results side + // by side along N. Per (batch, block) that is 2 dispatches instead of + // 2*numHeads. + struct AttnState { + // The dims this state was built for; a block with different dims declines. + int S = 0; + int numHeads = 0; + int numKVHeads = 0; + int qHeadDim = 0; + int vHeadDim = 0; + + RyzenAIKernel::Engine* engineQK = nullptr; // not owned (shared) + RyzenAIKernel::Engine* enginePV = nullptr; // not owned (shared) + RyzenAIKernel::Weights* weightsQK = nullptr; // owned + RyzenAIKernel::Weights* weightsPV = nullptr; // owned + int KQK = 0; // engine K serving QK^T (>= numHeads*qHeadDim) + int KPV = 0; // engine K serving P*V (>= numHeads*S) + int paddedMQK = 0; // padM(S) on the QK^T engine + int paddedMPV = 0; // padM(S) on the P*V engine + int paddedNQK = 0; // padN(numHeads*S): head h's scores at columns [h*S, (h+1)*S) + int paddedNPV = 0; // padN(numHeads*vHeadDim) + + // Host scratch, dedicated to attention so that the padding regions can be + // zeroed once at (re)size time; per dispatch only the real regions are + // rewritten. (The dense path's hostA/hostC cannot offer that invariant -- + // every dense layer rewrites them to its own shape.) + vector hostAQK; // paddedMQK x KQK; row qi is qBuf[n][qi][:] outright + vector hostAPV; // paddedMPV x KPV; head h's P rows at columns [h*S, (h+1)*S) + vector hostBQK; // KQK x paddedNQK, block-diagonal transposed K + vector hostBPV; // KPV x paddedNPV, block-diagonal V + vector hostC; // max(paddedMQK*paddedNQK, paddedMPV*paddedNPV) + vector scoreRow; // one softmax working row, S floats + + // The softmax between the two GEMMs, when an op compiled for exactly this + // (rows, width) = (numHeads*S, S) padded to (64, 32) exists. Null keeps the + // CPU softmax below. Rows are head-major: row h*S+qi holds head h's scores + // for query qi, so the scatter into hostAPV is a pure copy. + RyzenAIKernel::Op* softmaxOp = nullptr; // owned + int smRows = 0; // the op's compiled rows (>= numHeads*S) + int smWidth = 0; // the op's compiled width (>= S) + vector hostSmIn; // smRows x smWidth, bfloat16 + vector hostSmOut; // same + + // The fused whole-attention op (QK^T + softmax + P*V in one dispatch), + // when one compiled for exactly (numHeads, S) exists. Buffers are the + // pre-tiled host packing: attnQ [heads][48][256] bf16 (8x32 chunks in + // A-tile order, pre-scaled), attnKV [kvHeads][2][12288] bf16 (B-tile + // order, K then V), attnC [heads][48][256] f32 (C-tile order). + RyzenAIKernel::Op* attnOp = nullptr; // owned + vector attnQ; + vector attnKV; + vector attnC; + + bool usable = false; + string why; // set when !usable, for the report + }; + +} // namespace + +namespace { + + +} // namespace + +struct Accel { + Options options; + RyzenAIKernel::Dtype dtype = RyzenAIKernel::Dtype::Auto; + + // K -> engine. Every dense layer with that reduction dim shares one. + map engines; + map infos; + + // Which K values have artifacts, so a layer can be rejected without paying + // for a load attempt. + vector availableK; + + // Keyed by the desc's address, which is stable for the model's lifetime. + map layers; + + // Fused projections (several layers sharing one input, weights concatenated + // along N into one uploaded B), keyed by the first desc's address. A desc + // used as a fusion key must never also be used standalone -- true for + // q/k/vProj and linear1/linearGate, which only ever appear together. + map fusedLayers; + + // SwiGLU-epilogue engines (a separate xclbin per K, so a separate hardware + // context from the plain GEMM engines) and the FFN layers using them, + // keyed by the linear1 desc's address. + map swigluEngines; + map swigluInfos; + vector availableSwigluK; + map swigluLayers; + long long numSwiglu = 0; + long long numSwigluFallback = 0; + + // Scratch, grown on demand: A in bfloat16 padded to (paddedM x K), C in + // float32 padded to (paddedM x paddedN). + vector hostA; + vector hostC; + + // The convolution input, converted to bfloat16 once per layer. A 3x3 window + // reads every input point from up to nine output positions, so converting + // inside the im2col gather did the same float->bf16 arithmetic nine times + // over; with this the gather is a memcpy per tap. + vector hostConvIn; + + long long numAccelerated = 0; + long long numFallback = 0; + + // Attention (QK^T and P*V) routing state and accounting. + AttnState attn; + long long numAttn = 0; + long long numAttnFallback = 0; + double secsAttnPack = 0.0; // A and B host-side builds + double secsAttnUploadB = 0.0; // rewriteWeights (memcpy + sync) + double secsAttnDispatch = 0.0; // runGemm + double secsAttnUnpack = 0.0; // C -> attnOut + double secsAttnSoftmax = 0.0; // on-CPU softmax between the two GEMMs + double secsAttnSoftmaxNpu = 0.0; // NPU softmax dispatch + double secsAttnSoftmaxHost = 0.0; // gather/scatter around the NPU softmax + + // Where the wall clock goes inside tryMatmul, so that the host-side packing + // can be told apart from the NPU's own time. + double secsPackA = 0.0; + double secsGather = 0.0; // im2col, for convolutions with taps + double secsDispatch = 0.0; + double secsUnpackC = 0.0; + + // BatchNorm+Mish fused op state, keyed by (channels, rows-per-dispatch). + // + // The row count is baked into each artifact, and which one is cheapest + // depends on how many rows the call actually has. Measured on b40c768: a + // dispatch costs ~0.73 ms fixed plus ~0.85 us per row, so a batch of one + // board (361 rows) wants the 384-row op (~1.06 ms) while a batch of seven + // (2635 rows) wants the 3072-row one (~3.3 ms in a single dispatch instead + // of seven 384-row dispatches at ~7.4 ms). Picking per call rather than + // latching one height is the whole point - latching is what silently cost + // b40c768 its BN acceleration under batching in the first place. + // constexpr, so no out-of-class definition is needed (C++17 makes it inline). + static constexpr int kBnMishHeights[3] = {384, 1536, 3072}; + + struct BnMishState { + RyzenAIKernel::Op* op = nullptr; // owned + // Why this width is not accelerated, for the report. A layer that simply + // is not Mish is not recorded: that is routing, not a failure. A missing + // artifact is, because it costs real time and is otherwise invisible - + // the CPU path produces identical numbers, just slowly. + string why; + int rowsPad = 0; + int width = 0; + bool tried = false; + vector hostX; // rowsPad x width bf16 + vector hostSB; // 8 x 2*width bf16 ([scale|bias] per core) + vector hostY; // rowsPad x width bf16 + }; + std::map, BnMishState> bnmByShape; // (channels, rows) + long long numBnMish = 0; + double secsBnMish = 0.0; + + // One-time weight preparation: fp32 -> bfloat16, padded, uploaded. This is + // what a persistent cache would replace, so it is measured separately. + double secsPrepareConvert = 0.0; // conversion + padding on the host + double secsPrepareUpload = 0.0; // memcpy into the BO and sync + long long prepareBytes = 0; +}; + +namespace { + inline double nowSecs() { + return std::chrono::duration( + std::chrono::steady_clock::now().time_since_epoch()).count(); + } +} + +namespace { + + // Smallest artifact K that can hold this layer's reduction dim, or the + // single forced one when the caller has asked for a one-context model. + bool pickK(const Accel* accel, int inChannels, int& kOut) { + // forceK is a preference, not a requirement: it collapses every layer it + // can onto one context, and anything needing a larger reduction dim (the + // block-diagonal P*V, whose K is numHeads*S) still gets its own rather than + // dropping to the CPU. One extra context beats losing the whole operator. + if(accel->options.forceK > 0 && accel->options.forceK >= inChannels) { + kOut = accel->options.forceK; + return true; + } + for(size_t i = 0; i < accel->availableK.size(); i++) { + if(accel->availableK[i] >= inChannels) { + kOut = accel->availableK[i]; + return true; + } + } + return false; + } + + RyzenAIKernel::Engine* engineForK(Accel* accel, int K, RyzenAIKernel::EngineInfo& infoOut) { + auto it = accel->engines.find(K); + if(it != accel->engines.end()) { + infoOut = accel->infos[K]; + return it->second; + } + RyzenAIKernel::EngineInfo info; + string err; + RyzenAIKernel::Engine* engine = RyzenAIKernel::loadEngine( + accel->options.artifactDir, accel->options.deviceIdx, accel->dtype, K, + accel->options.maxCols, info, err); + if(engine == nullptr) + return nullptr; + accel->engines[info.K] = engine; + accel->infos[info.K] = info; + infoOut = info; + return engine; + } + + // How a layer's source weights are laid out, and therefore how they have to + // be shuffled into the K x N row-major B the GEMM wants. + enum class WeightForm { + InByOut, // MatMulLayerDesc: w[ic*outC + oc] + OutByIn, // 1x1 ConvLayerDesc: w[oc*inC + ic] + ConvTaps, // ConvLayerDesc with taps: w[(oc*inC + ic)*ky*kx + dy*kx + dx] + }; + + // First use of a layer: pick an engine, then pad and upload its weights. + // numTaps is convY*convX (1 for a dense layer), so the reduction dim is + // numTaps*inChannels. + Layer& prepareLayer( + Accel* accel, const void* key, const float* w, int inChannels, int outChannels, + WeightForm form, int numTaps = 1) { + Layer& layer = accel->layers[key]; + if(layer.engine != nullptr || layer.why.size() > 0) + return layer; + + const int reduceDim = numTaps * inChannels; + int K = 0; + if(!pickK(accel, reduceDim, K)) { + layer.why = "no artifact with K >= " + Global::intToString(reduceDim); + return layer; + } + + RyzenAIKernel::EngineInfo info; + RyzenAIKernel::Engine* engine = engineForK(accel, K, info); + if(engine == nullptr) { + layer.why = "engine for K=" + Global::intToString(K) + " would not load"; + return layer; + } + + const int paddedN = RyzenAIKernel::padN(info, outChannels); + + // B must end up K x N row-major, zero-padded on both axes. Row k of B pairs + // with column k of A, so for a convolution the tap index has to lead: the + // gather below writes tap t's inChannels values at column t*inChannels. + const double tConvert = nowSecs(); + vector b((size_t)info.K * (size_t)paddedN, RyzenAIKernel::floatToBf16(0.0f)); + for(int t = 0; t < numTaps; t++) { + for(int ic = 0; ic < inChannels; ic++) { + uint16_t* dst = b.data() + ((size_t)t * inChannels + ic) * paddedN; + for(int oc = 0; oc < outChannels; oc++) { + float v; + switch(form) { + case WeightForm::InByOut: v = w[(size_t)ic * outChannels + oc]; break; + case WeightForm::OutByIn: v = w[(size_t)oc * inChannels + ic]; break; + default: v = w[((size_t)oc * inChannels + ic) * numTaps + t]; break; + } + dst[oc] = RyzenAIKernel::floatToBf16(v); + } + } + } + + accel->secsPrepareConvert += nowSecs() - tConvert; + accel->prepareBytes += (long long)b.size() * 2; + + const double tUpload = nowSecs(); + string err; + RyzenAIKernel::Weights* weights = RyzenAIKernel::uploadWeights(engine, paddedN, b.data(), err); + accel->secsPrepareUpload += nowSecs() - tUpload; + if(weights == nullptr) { + layer.why = err; + return layer; + } + + layer.engine = engine; + layer.weights = weights; + layer.K = info.K; + layer.paddedN = paddedN; + layer.usable = true; + return layer; + } + +} // namespace + +Accel* create(const Options& options, string& err) { + err.clear(); + + RyzenAIKernel::Dtype dtype = RyzenAIKernel::Dtype::Auto; + if(!RyzenAIKernel::parseDtype(options.dtype, dtype)) { + err = "unrecognized dtype '" + options.dtype + "'"; + return nullptr; + } + + vector ks = RyzenAIKernel::listGemmK(options.artifactDir); + if(ks.empty()) { + err = "no NPU artifacts under " + options.artifactDir; + return nullptr; + } + + Accel* accel = new Accel(); + accel->options = options; + accel->dtype = dtype; + accel->availableK = ks; // listGemmK returns them sorted + accel->availableSwigluK = RyzenAIKernel::listSwigluK(options.artifactDir); // sorted too + return accel; +} + +void free(Accel* accel) { + if(accel == nullptr) + return; + for(auto& entry : accel->layers) + RyzenAIKernel::freeWeights(entry.second.weights); + for(auto& entry : accel->fusedLayers) + RyzenAIKernel::freeWeights(entry.second.weights); + for(auto& entry : accel->swigluLayers) + RyzenAIKernel::freeWeights(entry.second.weights); + RyzenAIKernel::freeWeights(accel->attn.weightsQK); + RyzenAIKernel::freeWeights(accel->attn.weightsPV); + RyzenAIKernel::freeOp(accel->attn.softmaxOp); + RyzenAIKernel::freeOp(accel->attn.attnOp); + for(auto& e : accel->bnmByShape) + RyzenAIKernel::freeOp(e.second.op); + for(auto& entry : accel->engines) + RyzenAIKernel::freeEngine(entry.second); + for(auto& entry : accel->swigluEngines) + RyzenAIKernel::freeEngine(entry.second); + delete accel; +} + +namespace { + +// `in` may be null, meaning the caller has already written the padded bfloat16 +// A into accel->hostA itself (the im2col path does). +// Packs A (unless in == nullptr, meaning the caller already wrote the padded +// bfloat16 A into accel->hostA, as the im2col path does) and dispatches, +// leaving the padded float32 result in accel->hostC. On a dispatch failure the +// layer is dropped to the CPU permanently and false is returned, already +// accounted; the caller must then run its own implementation. +bool dispatchPacked( + Accel* accel, Layer& layer, const float* in, int inC, int numRows) { + const RyzenAIKernel::EngineInfo& info = RyzenAIKernel::engineInfo(layer.engine); + const int paddedM = RyzenAIKernel::padM(info, numRows); + const int K = layer.K; + const int paddedN = layer.paddedN; + + accel->hostA.resize((size_t)paddedM * (size_t)K); + accel->hostC.resize((size_t)paddedM * (size_t)paddedN); + + // A: convert to bfloat16, zero-filling the columns past inChannels and the + // rows past numRows. Those contribute nothing to the real outputs. + const double tPack = nowSecs(); + if(in != nullptr) { + const uint16_t zero = RyzenAIKernel::floatToBf16(0.0f); + for(int r = 0; r < numRows; r++) { + const float* src = in + (size_t)r * inC; + uint16_t* dst = accel->hostA.data() + (size_t)r * K; + RyzenAIKernel::floatToBf16Bulk(src, dst, (size_t)inC); + for(int c = inC; c < K; c++) + dst[c] = zero; + } + if(paddedM > numRows) + std::fill( + accel->hostA.begin() + (size_t)numRows * K, + accel->hostA.begin() + (size_t)paddedM * K, zero); + } + + const double tDispatch = nowSecs(); + accel->secsPackA += tDispatch - tPack; + try { + RyzenAIKernel::runGemm( + layer.engine, layer.weights, paddedM, paddedN, accel->hostA.data(), accel->hostC.data()); + } + catch(const std::exception&) { + layer.usable = false; + layer.why = "dispatch failed at run time"; + accel->numFallback++; + return false; + } + accel->secsDispatch += nowSecs() - tDispatch; + return true; +} + +bool runLayer( + Accel* accel, Layer& layer, float* out, const float* in, int inC, int outC, int numRows, + bool accumulate) { + const int paddedN = layer.paddedN; + if(!dispatchPacked(accel, layer, in, inC, numRows)) + return false; + + const double tUnpack = nowSecs(); + // C: take the real rows and columns out of the padded result. + for(int r = 0; r < numRows; r++) { + const float* src = accel->hostC.data() + (size_t)r * paddedN; + float* dst = out + (size_t)r * outC; + if(accumulate) { + for(int c = 0; c < outC; c++) + dst[c] += src[c]; + } + else { + std::memcpy(dst, src, (size_t)outC * sizeof(float)); + } + } + + accel->secsUnpackC += nowSecs() - tUnpack; + accel->numAccelerated++; + return true; +} + +} // namespace + +bool tryMatmul( + Accel* accel, float* out, const float* in, const MatMulLayerDesc& desc, int numRows) { + if(accel == nullptr || numRows < accel->options.minRows) { + if(accel != nullptr) + accel->numFallback++; + return false; + } + Layer& layer = prepareLayer( + accel, &desc, desc.weights.data(), desc.inChannels, desc.outChannels, WeightForm::InByOut); + if(!layer.usable) { + accel->numFallback++; + return false; + } + return runLayer(accel, layer, out, in, desc.inChannels, desc.outChannels, numRows, false); +} + +namespace { + + // First use of a fused projection: concatenates the descs' weights along N + // into one uploaded B. All descs must share the same inChannels (checked by + // the caller). Column block j holds descs[j]'s outChannels columns, in + // order, so one dispatch produces every output side by side. + Layer& prepareFusedLayer( + Accel* accel, const MatMulLayerDesc* const* descs, int numDescs) { + Layer& layer = accel->fusedLayers[descs[0]]; + if(layer.engine != nullptr || layer.why.size() > 0) + return layer; + + const int inC = descs[0]->inChannels; + int K = 0; + if(!pickK(accel, inC, K)) { + layer.why = "no artifact with K >= " + Global::intToString(inC); + return layer; + } + + RyzenAIKernel::EngineInfo info; + RyzenAIKernel::Engine* engine = engineForK(accel, K, info); + if(engine == nullptr) { + layer.why = "engine for K=" + Global::intToString(K) + " would not load"; + return layer; + } + + int totalOutC = 0; + for(int j = 0; j < numDescs; j++) + totalOutC += descs[j]->outChannels; + const int paddedN = RyzenAIKernel::padN(info, totalOutC); + + const double tConvert = nowSecs(); + vector b((size_t)info.K * (size_t)paddedN, RyzenAIKernel::floatToBf16(0.0f)); + int off = 0; + for(int j = 0; j < numDescs; j++) { + const MatMulLayerDesc* d = descs[j]; + const float* w = d->weights.data(); + for(int ic = 0; ic < inC; ic++) { + uint16_t* dst = b.data() + (size_t)ic * paddedN + off; + const float* src = w + (size_t)ic * d->outChannels; + for(int oc = 0; oc < d->outChannels; oc++) + dst[oc] = RyzenAIKernel::floatToBf16(src[oc]); + } + off += d->outChannels; + } + accel->secsPrepareConvert += nowSecs() - tConvert; + accel->prepareBytes += (long long)b.size() * 2; + + const double tUpload = nowSecs(); + string err; + RyzenAIKernel::Weights* weights = RyzenAIKernel::uploadWeights(engine, paddedN, b.data(), err); + accel->secsPrepareUpload += nowSecs() - tUpload; + if(weights == nullptr) { + layer.why = err; + return layer; + } + + layer.engine = engine; + layer.weights = weights; + layer.K = info.K; + layer.paddedN = paddedN; + layer.usable = true; + return layer; + } + +} // namespace + +bool tryMatmulMulti( + Accel* accel, float* const* outs, const float* in, + const MatMulLayerDesc* const* descs, int numDescs, int numRows) { + if(accel == nullptr || numDescs < 2 || numRows < accel->options.minRows) { + if(accel != nullptr) + accel->numFallback += numDescs; + return false; + } + const int inC = descs[0]->inChannels; + for(int j = 1; j < numDescs; j++) + if(descs[j]->inChannels != inC) + return false; // not fusible; the caller runs each on its own path + + Layer& layer = prepareFusedLayer(accel, descs, numDescs); + if(!layer.usable) { + accel->numFallback += numDescs; + return false; + } + if(!dispatchPacked(accel, layer, in, inC, numRows)) + return false; + + const double tUnpack = nowSecs(); + const int paddedN = layer.paddedN; + int off = 0; + for(int j = 0; j < numDescs; j++) { + const int outC = descs[j]->outChannels; + float* out = outs[j]; + for(int r = 0; r < numRows; r++) + std::memcpy( + out + (size_t)r * outC, accel->hostC.data() + (size_t)r * paddedN + off, + (size_t)outC * sizeof(float)); + off += outC; + } + + accel->secsUnpackC += nowSecs() - tUnpack; + accel->numAccelerated += numDescs; + return true; +} + +namespace { + + // The swiglu-epilogue engines sit on their own hardware contexts, one per K. + RyzenAIKernel::Engine* swigluEngineForK( + Accel* accel, int K, RyzenAIKernel::EngineInfo& infoOut) { + auto it = accel->swigluEngines.find(K); + if(it != accel->swigluEngines.end()) { + infoOut = accel->swigluInfos[K]; + return it->second; + } + RyzenAIKernel::EngineInfo info; + string err; + RyzenAIKernel::Engine* engine = RyzenAIKernel::loadEngineSwiglu( + accel->options.artifactDir, accel->options.deviceIdx, accel->dtype, K, + accel->options.maxCols, info, err); + if(engine == nullptr) + return nullptr; + accel->swigluEngines[info.K] = engine; + accel->swigluInfos[info.K] = info; + infoOut = info; + return engine; + } + + // Which reduction dim the swiglu path can serve this layer on. forceK wins + // only when a swiglu artifact exists at exactly that K -- substituting a + // different one would add yet another hardware context, which the forced-K + // policy exists to eliminate. Without forceK, take the smallest available + // swiglu K that fits (zero-padding the reduction is nearly free). + bool pickSwigluK(const Accel* accel, int inC, int& kOut) { + const vector& ks = accel->availableSwigluK; + if(accel->options.forceK > 0 && accel->options.forceK >= inC) { + if(std::binary_search(ks.begin(), ks.end(), accel->options.forceK)) { + kOut = accel->options.forceK; + return true; + } + return false; + } + for(size_t i = 0; i < ks.size(); i++) { + if(ks[i] >= inC) { + kOut = ks[i]; + return true; + } + } + return false; + } + + // First use of an FFN's linear1/linearGate pair: pad and upload the two + // weight matrices as one B whose columns interleave in groups of 8 -- + // [linear1 ch 0-7, gate ch 0-7, linear1 ch 8-15, ...] -- so that in every + // core's C tile the even 8-column sub-tiles hold linear1 outputs and the odd + // ones the matching gates, which is the pairing the on-chip epilogue + // assumes (see python/ryzenai_kernels/kernels/mm_swiglu_epilogue.cc). + Layer& prepareSwigluLayer( + Accel* accel, const MatMulLayerDesc& linear1, const MatMulLayerDesc& linearGate) { + Layer& layer = accel->swigluLayers[&linear1]; + if(layer.engine != nullptr || layer.why.size() > 0) + return layer; + + const int inC = linear1.inChannels; + const int ffnC = linear1.outChannels; + int K = 0; + if(!pickSwigluK(accel, inC, K)) { + layer.why = "no swiglu-epilogue artifact serving K >= " + Global::intToString(inC); + return layer; + } + + RyzenAIKernel::EngineInfo info; + RyzenAIKernel::Engine* engine = swigluEngineForK(accel, K, info); + if(engine == nullptr) { + layer.why = "swiglu engine for K=" + Global::intToString(K) + " would not load"; + return layer; + } + + const int paddedN = RyzenAIKernel::padN(info, 2 * ffnC); + + const double tConvert = nowSecs(); + vector b((size_t)info.K * (size_t)paddedN, RyzenAIKernel::floatToBf16(0.0f)); + const float* w1 = linear1.weights.data(); + const float* wg = linearGate.weights.data(); + for(int ic = 0; ic < inC; ic++) { + uint16_t* dst = b.data() + (size_t)ic * paddedN; + const float* s1 = w1 + (size_t)ic * ffnC; + const float* sg = wg + (size_t)ic * ffnC; + for(int c = 0; c < ffnC; c++) { + const int base = (c >> 3) << 4; + dst[base + (c & 7)] = RyzenAIKernel::floatToBf16(s1[c]); + dst[base + 8 + (c & 7)] = RyzenAIKernel::floatToBf16(sg[c]); + } + } + accel->secsPrepareConvert += nowSecs() - tConvert; + accel->prepareBytes += (long long)b.size() * 2; + + const double tUpload = nowSecs(); + string err; + RyzenAIKernel::Weights* weights = RyzenAIKernel::uploadWeights(engine, paddedN, b.data(), err); + accel->secsPrepareUpload += nowSecs() - tUpload; + if(weights == nullptr) { + layer.why = err; + return layer; + } + + layer.engine = engine; + layer.weights = weights; + layer.K = info.K; + layer.paddedN = paddedN; + layer.usable = true; + return layer; + } + +} // namespace + +bool tryMatmulSwiglu( + Accel* accel, float* out, const float* in, + const MatMulLayerDesc& linear1, const MatMulLayerDesc& linearGate, int numRows) { + if(accel == nullptr || numRows < accel->options.minRows) { + if(accel != nullptr) + accel->numSwigluFallback++; + return false; + } + // The epilogue pairs adjacent 8-column groups, so the two projections must + // agree on the shape and the channel count must fill whole groups. + if(linear1.inChannels != linearGate.inChannels || + linear1.outChannels != linearGate.outChannels || + linear1.outChannels % 8 != 0) { + accel->numSwigluFallback++; + return false; + } + + Layer& layer = prepareSwigluLayer(accel, linear1, linearGate); + if(!layer.usable) { + accel->numSwigluFallback++; + return false; + } + if(!dispatchPacked(accel, layer, in, linear1.inChannels, numRows)) + return false; + + // C row r holds silu(l1)*gate for channel c at column (c>>3)*16 + (c&7); + // the interleaved gate columns in between are the raw GEMM outputs and are + // simply never read. + const double tUnpack = nowSecs(); + const int paddedN = layer.paddedN; + const int ffnC = linear1.outChannels; + for(int r = 0; r < numRows; r++) { + const float* src = accel->hostC.data() + (size_t)r * paddedN; + float* dst = out + (size_t)r * ffnC; + for(int c = 0; c < ffnC; c++) + dst[c] = src[((c >> 3) << 4) + (c & 7)]; + } + + accel->secsUnpackC += nowSecs() - tUnpack; + accel->numSwiglu++; + return true; +} + +bool tryConv1x1( + Accel* accel, float* out, const float* in, const ConvLayerDesc& desc, int numRows, + bool accumulate) { + if(accel == nullptr || numRows < accel->options.minRows) { + if(accel != nullptr) + accel->numFallback++; + return false; + } + if(desc.convXSize != 1 || desc.convYSize != 1) + return false; // not a fallback, just not this function's business + Layer& layer = prepareLayer( + accel, &desc, desc.weights.data(), desc.inChannels, desc.outChannels, WeightForm::OutByIn); + if(!layer.usable) { + accel->numFallback++; + return false; + } + return runLayer(accel, layer, out, in, desc.inChannels, desc.outChannels, numRows, accumulate); +} + +bool tryConv( + Accel* accel, float* out, const float* in, const ConvLayerDesc& desc, int batchSize, + int nnXLen, int nnYLen, bool accumulate) { + const int numRows = batchSize * nnXLen * nnYLen; + if(accel == nullptr || numRows < accel->options.minRows) { + if(accel != nullptr) + accel->numFallback++; + return false; + } + const int kx = desc.convXSize; + const int ky = desc.convYSize; + if(kx == 1 && ky == 1) + return tryConv1x1(accel, out, in, desc, numRows, accumulate); + // Even kernel sizes would not centre; KataGo only ever uses odd ones. + if(kx <= 0 || ky <= 0 || (kx % 2) == 0 || (ky % 2) == 0) + return false; + + const int numTaps = ky * kx; + Layer& layer = prepareLayer( + accel, &desc, desc.weights.data(), desc.inChannels, desc.outChannels, WeightForm::ConvTaps, + numTaps); + if(!layer.usable) { + accel->numFallback++; + return false; + } + + const RyzenAIKernel::EngineInfo& info = RyzenAIKernel::engineInfo(layer.engine); + const int paddedM = RyzenAIKernel::padM(info, numRows); + const int K = layer.K; + const int inC = desc.inChannels; + const int padX = kx / 2; + const int padY = ky / 2; + const int dilX = desc.dilationX; + const int dilY = desc.dilationY; + + // im2col straight into the A scratch, in bfloat16. Off-board taps and the + // columns past numTaps*inChannels stay zero, which is exactly what the + // convolution's zero padding means. + const double tGather = nowSecs(); + accel->hostA.assign((size_t)paddedM * (size_t)K, RyzenAIKernel::floatToBf16(0.0f)); + + // One pass over the input converts it; the gather below then only moves + // bytes. Same conversion function on the same values, so the bytes handed to + // the NPU are identical to the element-wise version this replaces. + const size_t inCount = (size_t)numRows * (size_t)inC; + if(accel->hostConvIn.size() < inCount) + accel->hostConvIn.resize(inCount); + RyzenAIKernel::floatToBf16Bulk(in, accel->hostConvIn.data(), inCount); + + const uint16_t* convIn = accel->hostConvIn.data(); + const size_t tapBytes = (size_t)inC * sizeof(uint16_t); + for(int n = 0; n < batchSize; n++) { + for(int y = 0; y < nnYLen; y++) { + for(int x = 0; x < nnXLen; x++) { + uint16_t* dstRow = + accel->hostA.data() + (((size_t)n * nnYLen + y) * nnXLen + x) * K; + for(int dy = 0; dy < ky; dy++) { + const int iy = y + (dy - padY) * dilY; + if(iy < 0 || iy >= nnYLen) + continue; + for(int dx = 0; dx < kx; dx++) { + const int ix = x + (dx - padX) * dilX; + if(ix < 0 || ix >= nnXLen) + continue; + const uint16_t* src = convIn + ((((size_t)n * nnYLen + iy) * nnXLen + ix) * inC); + uint16_t* dst = dstRow + (size_t)(dy * kx + dx) * inC; + std::memcpy(dst, src, tapBytes); + } + } + } + } + } + accel->secsGather += nowSecs() - tGather; + + return runLayer(accel, layer, out, nullptr, inC, desc.outChannels, numRows, accumulate); +} + +namespace { + + // First attention block of a given shape: pick engines for the two reduction + // dims (numHeads*qHeadDim for QK^T, numHeads*S for P*V), then allocate and + // zero-fill the host scratch and the two device-resident B buffers. + // Attention shapes are fixed for a (model, geometry) pair, so this runs once + // per Accel. + void prepareAttention( + Accel* accel, int S, int numHeads, int numKVHeads, int qHeadDim, int vHeadDim) { + AttnState& st = accel->attn; + if(st.usable || st.why.size() > 0) + return; + + st.S = S; + st.numHeads = numHeads; + st.numKVHeads = numKVHeads; + st.qHeadDim = qHeadDim; + st.vHeadDim = vHeadDim; + + const int qTot = numHeads * qHeadDim; + const int headsByS = numHeads * S; + int kQK = 0; + int kPV = 0; + if(!pickK(accel, qTot, kQK)) { + st.why = "no artifact with K >= qTot " + Global::intToString(qTot); + return; + } + if(!pickK(accel, headsByS, kPV)) { + st.why = "no artifact with K >= numHeads*S " + Global::intToString(headsByS); + return; + } + + RyzenAIKernel::EngineInfo infoQK; + RyzenAIKernel::EngineInfo infoPV; + st.engineQK = engineForK(accel, kQK, infoQK); + if(st.engineQK == nullptr) { + st.why = "attention engine for K=" + Global::intToString(kQK) + " would not load"; + return; + } + st.enginePV = engineForK(accel, kPV, infoPV); + if(st.enginePV == nullptr) { + st.why = "attention engine for K=" + Global::intToString(kPV) + " would not load"; + return; + } + + st.KQK = infoQK.K; + st.KPV = infoPV.K; + st.paddedMQK = RyzenAIKernel::padM(infoQK, S); + st.paddedMPV = RyzenAIKernel::padM(infoPV, S); + st.paddedNQK = RyzenAIKernel::padN(infoQK, headsByS); + st.paddedNPV = RyzenAIKernel::padN(infoPV, numHeads * vHeadDim); + + // Zero-filled: the padding regions of every buffer (and the off-diagonal + // blocks of the two B buffers) stay zero for the state's lifetime, and + // only the real regions are rewritten per dispatch. + const uint16_t zero = RyzenAIKernel::floatToBf16(0.0f); + st.hostAQK.assign((size_t)st.paddedMQK * st.KQK, zero); + st.hostAPV.assign((size_t)st.paddedMPV * st.KPV, zero); + st.hostBQK.assign((size_t)st.KQK * st.paddedNQK, zero); + st.hostBPV.assign((size_t)st.KPV * st.paddedNPV, zero); + st.hostC.assign( + std::max((size_t)st.paddedMQK * st.paddedNQK, (size_t)st.paddedMPV * st.paddedNPV), 0.0f); + st.scoreRow.assign(S, 0.0f); + + string err; + st.weightsQK = RyzenAIKernel::uploadWeights(st.engineQK, st.paddedNQK, st.hostBQK.data(), err); + if(st.weightsQK == nullptr) { + st.why = err; + return; + } + st.weightsPV = RyzenAIKernel::uploadWeights(st.enginePV, st.paddedNPV, st.hostBPV.data(), err); + if(st.weightsPV == nullptr) { + st.why = err; + return; + } + + // The softmax between the GEMMs goes to the NPU when an op compiled for + // exactly this shape exists; its absence is ordinary (CPU path stays). + // Rows pad to a multiple of 64 (8 cores x 8-row chunks) and columns to a + // multiple of 32 (the kernel's vector width). + st.smRows = ((numHeads * S + 63) / 64) * 64; + st.smWidth = ((S + 31) / 32) * 32; + { + const string base = accel->options.artifactDir + "/ops/softmax_" + + Global::intToString(st.smRows) + "x" + Global::intToString(st.smWidth); + const size_t smBytes = (size_t)st.smRows * (size_t)st.smWidth * sizeof(uint16_t); + string smErr; + st.softmaxOp = RyzenAIKernel::loadOp( + base + ".xclbin", base + ".insts.bin", accel->options.deviceIdx, &smBytes, 1, smBytes, + smErr); + if(st.softmaxOp != nullptr) { + st.hostSmIn.assign(smBytes / sizeof(uint16_t), RyzenAIKernel::floatToBf16(0.0f)); + st.hostSmOut.assign(smBytes / sizeof(uint16_t), 0); + } + } + + // The fused attention op (QK^T + softmax + P*V in one dispatch) replaces + // the whole staged path when present. Its host buffers carry Q/K/V + // pre-tiled into the mmul tile orders; see + // python/ryzenai_kernels/kernels/attention_head.cc for the layout contract. + { + const string attnBase = accel->options.artifactDir + "/ops/attn_h" + + Global::intToString(numHeads) + "_s" + Global::intToString(S); + const size_t qBytes = (size_t)numHeads * st.smWidth * qHeadDim * sizeof(uint16_t); + // K/V are packed per query head (a GQA group head's data is replicated + // onto each of its query heads' slots -- the compiled op's taps are + // per-head). + const size_t kvBytes = (size_t)numHeads * 2 * st.smWidth * qHeadDim * sizeof(uint16_t); + const size_t cBytes = (size_t)numHeads * st.smWidth * vHeadDim * sizeof(float); + const size_t inBytes[2] = {qBytes, kvBytes}; + string attErr; + st.attnOp = RyzenAIKernel::loadOp( + attnBase + ".xclbin", attnBase + ".insts.bin", accel->options.deviceIdx, + inBytes, 2, cBytes, attErr); + if(st.attnOp != nullptr) { + st.attnQ.assign(qBytes / sizeof(uint16_t), RyzenAIKernel::floatToBf16(0.0f)); + st.attnKV.assign(kvBytes / sizeof(uint16_t), RyzenAIKernel::floatToBf16(0.0f)); + st.attnC.assign(cBytes / sizeof(float), 0.0f); + } + } + + st.usable = true; + } + +} // namespace + +bool tryAttention( + Accel* accel, float* attnOut, + const float* qBuf, const float* kBuf, const float* vBuf, const float* mask, + int batchSize, int S, int numHeads, int numKVHeads, int qHeadDim, int vHeadDim, + double* softmaxSecsOut) { + if(softmaxSecsOut != nullptr) + *softmaxSecsOut = 0.0; + if(accel == nullptr) + return false; + prepareAttention(accel, S, numHeads, numKVHeads, qHeadDim, vHeadDim); + AttnState& st = accel->attn; + if(!st.usable || st.S != S || st.numHeads != numHeads || st.numKVHeads != numKVHeads || + st.qHeadDim != qHeadDim || st.vHeadDim != vHeadDim) { + accel->numAttnFallback++; + return false; + } + + const int qTot = numHeads * qHeadDim; + const int kTot = numKVHeads * qHeadDim; + const int vTot = numKVHeads * vHeadDim; + const int oTot = numHeads * vHeadDim; + const int kvGroupSize = numHeads / numKVHeads; + const float scale = 1.0f / sqrtf((float)qHeadDim); + const uint16_t zero16 = RyzenAIKernel::floatToBf16(0.0f); + double softmaxSecs = 0.0; + + // ---- fused path: the whole attention in one dispatch per batch element --- + // The op computes softmax((q*scale) @ K^T) @ V entirely on-chip. It handles + // full boards only (masked positions would need the -inf treatment the + // staged path's gather does), so anything masked falls through below. + if(st.attnOp != nullptr && qHeadDim == 32 && vHeadDim == 32) { + bool fullBoard = true; + for(int i = 0; i < batchSize * S; i++) { + if(mask[i] == 0.0f) { + fullBoard = false; + break; + } + } + if(fullBoard) { + const int sPad = st.smWidth; // the op's padded S (384 for 361) + for(int n = 0; n < batchSize; n++) { + const float* qN = qBuf + (size_t)n * S * qTot; + const float* kN = kBuf + (size_t)n * S * kTot; + const float* vN = vBuf + (size_t)n * S * vTot; + const double tPack = nowSecs(); + + // Each head-row is 32 contiguous floats going to a strided place, so + // convert the 32 in one call and then move plain uint16s. Doing the + // conversion inside the scatter meant 32 branchy scalar conversions per + // row, which is what made packing rival dispatch in the profile. + float scaled[32]; + uint16_t tmp[32]; + + // Q: per-head contiguous 8x32 chunks in A-tile order, pre-scaled. + for(int h = 0; h < numHeads; h++) { + uint16_t* qH = st.attnQ.data() + (size_t)h * sPad * 32; + const float* src = qN + (size_t)h * 32; + for(int qi = 0; qi < S; qi++, src += qTot) { + // within-chunk offset = (rowgroup*4 + row)*8 lanes: rows 4-7 of + // the chunk live 128 elements in, not at (qi&3)*8. + uint16_t* chunk = qH + (size_t)(qi >> 3) * 256 + + (((qi & 7) >> 2) * 128) + ((qi & 3) * 8); + for(int d = 0; d < 32; d++) + scaled[d] = src[d] * scale; + RyzenAIKernel::floatToBf16Bulk(scaled, tmp, 32); + // d's low three bits stay adjacent, so each group of eight is one + // contiguous run at stride 32. + for(int g = 0; g < 4; g++) + std::memcpy(chunk + (size_t)g * 32, tmp + g * 8, 8 * sizeof(uint16_t)); + } + } + // K/V: per head, K then V back to back, each in its B-tile order. + for(int h = 0; h < numHeads; h++) { + const int kvh = h / kvGroupSize; + uint16_t* kvH = st.attnKV.data() + (size_t)h * 2 * sPad * 32; + const float* kSrc = kN + (size_t)kvh * 32; + const float* vSrc = vN + (size_t)kvh * 32; + for(int ki = 0; ki < S; ki++, kSrc += kTot, vSrc += vTot) { + uint16_t* kDst = kvH + (size_t)(ki >> 3) * 256 + (ki & 7) * 8; + RyzenAIKernel::floatToBf16Bulk(kSrc, tmp, 32); + for(int g = 0; g < 4; g++) + std::memcpy(kDst + (size_t)g * 64, tmp + g * 8, 8 * sizeof(uint16_t)); + // V is transposed relative to K, so this one stays a scatter - but + // now it moves already-converted values. + uint16_t* vDst = kvH + (size_t)sPad * 32 + (ki & 7) + (size_t)(ki >> 3) * 64; + RyzenAIKernel::floatToBf16Bulk(vSrc, tmp, 32); + for(int dv = 0; dv < 32; dv++) + vDst[(dv >> 3) * 3072 + (dv & 7) * 8] = tmp[dv]; + } + } + accel->secsAttnPack += nowSecs() - tPack; + + const double tDispatch = nowSecs(); + try { + const void* ins[2] = {st.attnQ.data(), st.attnKV.data()}; + RyzenAIKernel::runOp(st.attnOp, ins, 2, st.attnC.data()); + } + catch(const std::exception&) { + st.attnOp = nullptr; // permanent: staged path from here on + accel->numAttnFallback++; + return false; + } + accel->secsAttnDispatch += nowSecs() - tDispatch; + + // C: per-head 8x32 chunks in C-tile order -> attnOut rows. + const double tUnpack = nowSecs(); + for(int h = 0; h < numHeads; h++) { + const float* cH = st.attnC.data() + (size_t)h * sPad * 32; + float* dst = attnOut + (size_t)n * S * oTot + (size_t)h * 32; + for(int qi = 0; qi < S; qi++) { + const float* chunk = cH + (size_t)(qi >> 3) * 256 + + (((qi & 7) >> 2) * 128) + ((qi & 3) * 8); + float* out = dst + (size_t)qi * oTot; + for(int dv = 0; dv < 32; dv++) + out[dv] = chunk[(dv >> 3) * 32 + (dv & 7)]; + } + } + accel->secsAttnUnpack += nowSecs() - tUnpack; + } + accel->numAttn++; + return true; + } + } + + for(int n = 0; n < batchSize; n++) { + const float* maskN = mask + (size_t)n * S; + + // ---- QK^T for every head in one GEMM ---------------------------------- + // A[qi][h*qHeadDim + d] = qBuf[n][qi][h*qHeadDim + d] -- i.e. the raw + // qBuf row, which already concatenates the heads exactly along the + // reduction dim. + // B is block-diagonal: B[h*qHeadDim + d][h*S + ki] = kBuf[n][ki][kvh*qHeadDim+d] + // (the K matrix of head h, transposed), zero elsewhere, so + // C[qi][h*S + ki] = falls out per head. + const double tPack = nowSecs(); + for(int qi = 0; qi < S; qi++) { + const float* src = qBuf + ((size_t)n * S + qi) * qTot; + uint16_t* dst = st.hostAQK.data() + (size_t)qi * st.KQK; + for(int c = 0; c < qTot; c++) + dst[c] = RyzenAIKernel::floatToBf16(src[c]); + } + for(int h = 0; h < numHeads; h++) { + const int kvh = h / kvGroupSize; + for(int d = 0; d < qHeadDim; d++) { + uint16_t* dst = st.hostBQK.data() + (size_t)(h * qHeadDim + d) * st.paddedNQK + (size_t)h * S; + const float* src = kBuf + (size_t)n * S * kTot + (size_t)kvh * qHeadDim + d; + for(int ki = 0; ki < S; ki++) + dst[ki] = RyzenAIKernel::floatToBf16(src[(size_t)ki * kTot]); + } + } + const double tUpload = nowSecs(); + accel->secsAttnPack += tUpload - tPack; + RyzenAIKernel::rewriteWeights(st.weightsQK, st.hostBQK.data()); + const double tDispatch = nowSecs(); + accel->secsAttnUploadB += tDispatch - tUpload; + try { + RyzenAIKernel::runGemm( + st.engineQK, st.weightsQK, st.paddedMQK, st.paddedNQK, st.hostAQK.data(), + st.hostC.data()); + } + catch(const std::exception&) { + // A dispatch failure is not fatal: drop attention to the CPU + // permanently and let the evaluation finish with correct numbers. + st.usable = false; + st.why = "dispatch failed at run time"; + accel->numAttnFallback++; + return false; + } + accel->secsAttnDispatch += nowSecs() - tDispatch; + + // ---- softmax ------------------------------------------------------------ + // NPU when an op for this exact shape loaded, CPU otherwise. Either way + // the probabilities land in the P*V GEMM's A (bfloat16) at + // A[qi][h*S + ki], and rows of masked-out queries and columns of + // masked-out keys are exactly 0, matching the reference semantics. + if(st.softmaxOp != nullptr) { + const double tGather = nowSecs(); + const uint16_t negInf = RyzenAIKernel::floatToBf16(-1e30f); + for(int h = 0; h < numHeads; h++) { + for(int qi = 0; qi < S; qi++) { + if(maskN[qi] == 0.0f) + continue; // the scatter writes exact zeros for this row + const float* cRow = st.hostC.data() + (size_t)qi * st.paddedNQK + (size_t)h * S; + uint16_t* dst = st.hostSmIn.data() + ((size_t)h * S + qi) * st.smWidth; + for(int ki = 0; ki < S; ki++) + dst[ki] = maskN[ki] == 0.0f ? negInf : RyzenAIKernel::floatToBf16(cRow[ki] * scale); + for(int ki = S; ki < st.smWidth; ki++) + dst[ki] = negInf; + } + } + const double tSmDispatch = nowSecs(); + accel->secsAttnSoftmaxHost += tSmDispatch - tGather; + try { + const void* smIns[1] = {st.hostSmIn.data()}; + RyzenAIKernel::runOp(st.softmaxOp, smIns, 1, st.hostSmOut.data()); + } + catch(const std::exception&) { + st.usable = false; + st.why = "softmax dispatch failed at run time"; + accel->numAttnFallback++; + return false; + } + const double tScatter = nowSecs(); + accel->secsAttnSoftmaxNpu += tScatter - tSmDispatch; + + for(int h = 0; h < numHeads; h++) { + for(int qi = 0; qi < S; qi++) { + uint16_t* dst = st.hostAPV.data() + (size_t)qi * st.KPV + (size_t)h * S; + if(maskN[qi] == 0.0f) { + std::fill(dst, dst + S, zero16); + continue; + } + const uint16_t* src = st.hostSmOut.data() + ((size_t)h * S + qi) * st.smWidth; + for(int ki = 0; ki < S; ki++) + dst[ki] = maskN[ki] == 0.0f ? zero16 : src[ki]; + } + } + accel->secsAttnSoftmaxHost += nowSecs() - tScatter; + } + else { + // ---- softmax on the CPU, byte-for-byte the reference semantics -------- + // Reads the raw scores out of C and writes the probabilities straight + // into the P*V GEMM's A (bfloat16), at A[qi][h*S + ki]. Rows of + // masked-out queries and columns of masked-out keys are exactly 0. + const double tSoftmax = nowSecs(); + for(int h = 0; h < numHeads; h++) { + for(int qi = 0; qi < S; qi++) { + uint16_t* dst = st.hostAPV.data() + (size_t)qi * st.KPV + (size_t)h * S; + if(maskN[qi] == 0.0f) { + std::fill(dst, dst + S, zero16); + continue; + } + const float* cRow = st.hostC.data() + (size_t)qi * st.paddedNQK + (size_t)h * S; + float maxVal = -1e30f; + for(int ki = 0; ki < S; ki++) { + if(maskN[ki] == 0.0f) + continue; + const float acc = cRow[ki] * scale; + st.scoreRow[ki] = acc; + if(acc > maxVal) + maxVal = acc; + } + float sumExp = 0.0f; + for(int ki = 0; ki < S; ki++) { + if(maskN[ki] == 0.0f) + continue; + float e = expf(st.scoreRow[ki] - maxVal); + st.scoreRow[ki] = e; + sumExp += e; + } + float invSum = 1.0f / sumExp; + for(int ki = 0; ki < S; ki++) + dst[ki] = maskN[ki] == 0.0f ? zero16 : RyzenAIKernel::floatToBf16(st.scoreRow[ki] * invSum); + } + } + softmaxSecs += nowSecs() - tSoftmax; + } + + // ---- P*V for every head in one GEMM ----------------------------------- + // A is the softmax output written above. B is block-diagonal: + // B[h*S + ki][h*vHeadDim + dv] = vBuf[n][ki][kvh*vHeadDim + dv], zero + // elsewhere, so C[qi][h*vHeadDim + dv] = sum_ki P_h[qi][ki] * V_h[ki][dv] + // -- i.e. one C row is exactly one attnOut row. + const double tPack2 = nowSecs(); + for(int h = 0; h < numHeads; h++) { + const int kvh = h / kvGroupSize; + for(int ki = 0; ki < S; ki++) { + const float* src = vBuf + ((size_t)n * S + ki) * vTot + (size_t)kvh * vHeadDim; + uint16_t* dst = + st.hostBPV.data() + (size_t)(h * S + ki) * st.paddedNPV + (size_t)h * vHeadDim; + for(int dv = 0; dv < vHeadDim; dv++) + dst[dv] = RyzenAIKernel::floatToBf16(src[dv]); + } + } + const double tUpload2 = nowSecs(); + accel->secsAttnPack += tUpload2 - tPack2; + RyzenAIKernel::rewriteWeights(st.weightsPV, st.hostBPV.data()); + const double tDispatch2 = nowSecs(); + accel->secsAttnUploadB += tDispatch2 - tUpload2; + try { + RyzenAIKernel::runGemm( + st.enginePV, st.weightsPV, st.paddedMPV, st.paddedNPV, st.hostAPV.data(), + st.hostC.data()); + } + catch(const std::exception&) { + st.usable = false; + st.why = "dispatch failed at run time"; + accel->numAttnFallback++; + return false; + } + const double tUnpack = nowSecs(); + accel->secsAttnDispatch += tUnpack - tDispatch2; + + for(int qi = 0; qi < S; qi++) { + float* dst = attnOut + ((size_t)n * S + qi) * oTot; + const float* src = st.hostC.data() + (size_t)qi * st.paddedNPV; + std::memcpy(dst, src, (size_t)oTot * sizeof(float)); + } + accel->secsAttnUnpack += nowSecs() - tUnpack; + } + + accel->numAttn++; + accel->secsAttnSoftmax += softmaxSecs; + if(softmaxSecsOut != nullptr) + *softmaxSecsOut = softmaxSecs; + return true; +} + + + + + +bool tryBnMish( + Accel* accel, float* out, const float* in, const BatchNormLayerDesc& bn, + int activation, int numRows) { + if(accel == nullptr) + return false; + if(activation != ACTIVATION_MISH) + return false; + + const int C = bn.numChannels; + // Smallest shipped height that covers this call in one dispatch, or the + // tallest if none does (which then chunks). Both ends cost: too short pays + // the fixed dispatch cost repeatedly, too tall pays the per-row cost on rows + // that are only padding. Choosing per call is the point - latching a height + // on the first call is what silently cost b40c768 its BN acceleration under + // batching (CPU norms 0.38 s -> 21.55 s). + int rows = Accel::kBnMishHeights[2]; + for(int i = 0; i < 3; i++) { + if(Accel::kBnMishHeights[i] >= numRows) { + rows = Accel::kBnMishHeights[i]; + break; + } + } + Accel::BnMishState& st = accel->bnmByShape[std::make_pair(C, rows)]; + if(!st.tried) { + st.tried = true; + st.width = C; + st.rowsPad = rows; + const string base = accel->options.artifactDir + "/ops/bnmish_" + + Global::intToString(st.rowsPad) + "x" + Global::intToString(st.width); + const size_t xBytes = (size_t)st.rowsPad * st.width * sizeof(uint16_t); + const size_t sbBytes = (size_t)8 * 2 * st.width * sizeof(uint16_t); + const size_t inBytes[2] = {xBytes, sbBytes}; + string err; + st.op = RyzenAIKernel::loadOp( + base + ".xclbin", base + ".insts.bin", accel->options.deviceIdx, + inBytes, 2, xBytes, err); + if(st.op != nullptr) { + st.hostX.assign(xBytes / sizeof(uint16_t), RyzenAIKernel::floatToBf16(0.0f)); + st.hostSB.assign(sbBytes / sizeof(uint16_t), 0); + st.hostY.assign(xBytes / sizeof(uint16_t), 0); + } + else { + st.why = "no " + Global::intToString(st.rowsPad) + "x" + + Global::intToString(st.width) + " artifact (" + err + ")"; + } + } + if(st.op == nullptr) + return false; + + const int W = st.width; + // Row blocks are independent: feeding the op 64 rows at a time instead of + // 384 reproduced the whole raw-nn output byte for byte, partial final block + // included, so this stride is purely a performance knob. + const int rowsPerRun = st.rowsPad; + const double t0 = nowSecs(); + + // scale/bias, replicated per core, [scale | bias] per core. Per layer, not + // per row block, so it is packed once for the whole call. + for(int core = 0; core < 8; core++) { + uint16_t* sb = st.hostSB.data() + (size_t)core * 2 * W; + for(int c = 0; c < W; c++) { + sb[c] = RyzenAIKernel::floatToBf16(bn.mergedScale[c]); + sb[W + c] = RyzenAIKernel::floatToBf16(bn.mergedBias[c]); + } + } + + for(int base = 0; base < numRows; base += rowsPerRun) { + const int rows = std::min(rowsPerRun, numRows - base); + + // X: rows of board points in bf16. A short final block leaves whatever the + // previous block wrote in the tail; those outputs are simply not read back, + // and Mish is elementwise so they cannot disturb the rows that are. + for(int r = 0; r < rows; r++) { + const float* src = in + (size_t)(base + r) * W; + uint16_t* dst = st.hostX.data() + (size_t)r * W; + for(int c = 0; c < W; c++) + dst[c] = RyzenAIKernel::floatToBf16(src[c]); + } + + try { + const void* ins[2] = {st.hostX.data(), st.hostSB.data()}; + RyzenAIKernel::runOp(st.op, ins, 2, st.hostY.data()); + } + catch(const std::exception&) { + RyzenAIKernel::freeOp(st.op); + st.op = nullptr; + // Rows before this block are already written; the caller's contract is + // that a false return means it must redo the whole layer, which + // overwrites them. + return false; + } + + for(int r = 0; r < rows; r++) { + float* dst = out + (size_t)(base + r) * W; + const uint16_t* src = st.hostY.data() + (size_t)r * W; + for(int c = 0; c < W; c++) + dst[c] = RyzenAIKernel::bf16ToFloat(src[c]); + } + accel->numBnMish++; // counts dispatches, so batching shows up here + } + + accel->secsBnMish += nowSecs() - t0; + return true; +} + +string report(const Accel* accel) { if(accel == nullptr) + return "RyzenAI dense layers: accelerator not created"; + + std::ostringstream out; + out << "RyzenAI dense layers: " << accel->numAccelerated << " on NPU, " << accel->numFallback + << " on CPU"; + if(accel->numBnMish > 0) { + char b[128]; + std::snprintf( + b, sizeof(b), "\n bn+mish on NPU: %lld dispatches (%.2f s)", accel->numBnMish, + accel->secsBnMish); + out << b; + } + // A width with no artifact runs on the CPU at full numerical fidelity, so + // nothing looks wrong - it is just slow. Name it, or the next model with an + // unshipped channel count silently loses this acceleration the way batched + // b40c768 did. + for(const auto& e : accel->bnmByShape) { + if(e.second.why.size() > 0) + out << "\n bn+mish NOT on NPU for " << e.first.first << " channels x " + << e.first.second << " rows: " << e.second.why; + } + if(accel->numAccelerated > 0) { + const double total = + accel->secsPackA + accel->secsGather + accel->secsDispatch + accel->secsUnpackC; + char buf[320]; + std::snprintf( + buf, sizeof(buf), + "\n %.2f s total: pack A %.2f s (%.0f%%), im2col %.2f s (%.0f%%), " + "dispatch %.2f s (%.0f%%), unpack C %.2f s (%.0f%%)" + "\n %.3f ms per accelerated layer", + total, accel->secsPackA, 100 * accel->secsPackA / total, + accel->secsGather, 100 * accel->secsGather / total, + accel->secsDispatch, 100 * accel->secsDispatch / total, + accel->secsUnpackC, 100 * accel->secsUnpackC / total, + 1000.0 * total / (double)accel->numAccelerated); + out << buf; + std::snprintf( + buf, sizeof(buf), + "\n one-time weight prep: convert+pad %.3f s, upload %.3f s, %.1f MB", + accel->secsPrepareConvert, accel->secsPrepareUpload, + (double)accel->prepareBytes / (1024.0 * 1024.0)); + out << buf; + } + + if(!accel->engines.empty() || !accel->swigluEngines.empty()) { + out << "\n engines:"; + for(const auto& entry : accel->infos) + out << " K=" << entry.first << "(" << entry.second.cols << "col)"; + for(const auto& entry : accel->swigluInfos) + out << " K=" << entry.first << "(" << entry.second.cols << "col,swiglu)"; + + // Split the dispatch cost, which is what decides whether keeping + // activations resident on the device would pay. + RyzenAIKernel::Timings t; + for(const auto& entry : accel->engines) { + const RyzenAIKernel::Timings& e = RyzenAIKernel::engineTimings(entry.second); + t.secsUploadA += e.secsUploadA; + t.secsExecute += e.secsExecute; + t.secsDownloadC += e.secsDownloadC; + t.numDispatches += e.numDispatches; + } + for(const auto& entry : accel->swigluEngines) { + const RyzenAIKernel::Timings& e = RyzenAIKernel::engineTimings(entry.second); + t.secsUploadA += e.secsUploadA; + t.secsExecute += e.secsExecute; + t.secsDownloadC += e.secsDownloadC; + t.numDispatches += e.numDispatches; + } + if(t.numDispatches > 0) { + char buf[256]; + std::snprintf( + buf, sizeof(buf), + "\n inside dispatch: upload A %.2f s, execute %.2f s, download C %.2f s" + " (%.3f / %.3f / %.3f ms each, %lld dispatches)", + t.secsUploadA, t.secsExecute, t.secsDownloadC, + 1000.0 * t.secsUploadA / (double)t.numDispatches, + 1000.0 * t.secsExecute / (double)t.numDispatches, + 1000.0 * t.secsDownloadC / (double)t.numDispatches, + t.numDispatches); + out << buf; + } + } + + // Attention (QK^T / P*V) routing, reported separately from the dense layers + // because its per-call cost profile is entirely different. + if(accel->numAttn > 0 || accel->numAttnFallback > 0) { + out << "\n attention blocks: " << accel->numAttn << " on NPU, " << accel->numAttnFallback + << " on CPU"; + if(accel->numAttn > 0) { + const double total = + accel->secsAttnPack + accel->secsAttnUploadB + accel->secsAttnDispatch + + accel->secsAttnUnpack; + char buf[448]; + std::snprintf( + buf, sizeof(buf), + "\n %.2f s around the GEMMs: pack %.2f s, upload B %.2f s, dispatch %.2f s, " + "unpack %.2f s (%.3f ms per block)", + total, accel->secsAttnPack, accel->secsAttnUploadB, accel->secsAttnDispatch, + accel->secsAttnUnpack, 1000.0 * total / (double)accel->numAttn); + out << buf; + if(accel->attn.softmaxOp != nullptr) + std::snprintf( + buf, sizeof(buf), + "\n softmax on NPU: dispatch %.2f s, gather/scatter %.2f s", + accel->secsAttnSoftmaxNpu, accel->secsAttnSoftmaxHost); + else + std::snprintf( + buf, sizeof(buf), "\n softmax still on CPU: %.2f s", accel->secsAttnSoftmax); + out << buf; + } + if(!accel->attn.usable && accel->attn.why.size() > 0) + out << "\n attention on CPU: " << accel->attn.why; + } + + // Only the reasons matter, not which layer hit them: a model has at most a + // handful of distinct failure modes and dozens of layers sharing each. + if(accel->numSwiglu > 0 || accel->numSwigluFallback > 0) + out << "\n swiglu epilogue: " << accel->numSwiglu << " FFN blocks on NPU, " + << accel->numSwigluFallback << " on CPU"; + std::map reasons; + for(const auto& entry : accel->layers) { + if(!entry.second.usable && entry.second.why.size() > 0) + reasons[entry.second.why]++; + } + for(const auto& entry : accel->swigluLayers) { + if(!entry.second.usable && entry.second.why.size() > 0) + reasons[entry.second.why]++; + } + for(const auto& entry : reasons) + out << "\n " << entry.second << " layer(s) on CPU: " << entry.first; + + return out.str(); +} + +} // namespace RyzenAIMatMul diff --git a/cpp/neuralnet/ryzenaimatmul.h b/cpp/neuralnet/ryzenaimatmul.h new file mode 100644 index 000000000..5c8d31ccb --- /dev/null +++ b/cpp/neuralnet/ryzenaimatmul.h @@ -0,0 +1,153 @@ +#ifndef NEURALNET_RYZENAI_MATMUL_H_ +#define NEURALNET_RYZENAI_MATMUL_H_ + +// Routes KataGo's dense layers to the NPU, falling back to the caller's CPU +// implementation whenever it cannot help. Also routes the two attention +// matmuls (QK^T and P*V), whose B operands are per-evaluation activations +// rather than resident weights -- see tryAttention below. +// +// KataGo already stores MatMulLayerDesc weights as inChannels x outChannels +// row-major, which is exactly the B operand the GEMM kernel wants, so weights +// need converting to bfloat16 but never transposing. Each layer's B is uploaded +// once and stays resident; only A and C cross the bus per evaluation. +// +// Padding: an xclbin fixes K, and the instruction stream requires M to be a +// multiple of tileM*8 and N a multiple of tileN*cols. Rows and columns beyond +// the real shape are zero-filled and their outputs discarded, so any layer +// shape runs -- at the cost of the wasted multiply-accumulates. + +#include +#include + +struct MatMulLayerDesc; +struct ConvLayerDesc; +struct BatchNormLayerDesc; +struct TransformerAttentionDesc; +struct TransformerFFNDesc; + +namespace RyzenAIMatMul { + + struct Accel; + + struct Options { + std::string artifactDir; + int deviceIdx = -1; // <0 selects the default device + std::string dtype = "auto"; // auto | bf16 | bfp16 + int maxCols = 0; // 0 = as wide as the device allows + // Dense layers whose row count is below this stay on the CPU. A dispatch + // costs on the order of 0.2 ms no matter how small the work is, which + // swamps the batch-row matmuls in the heads (a few dozen rows at most). + int minRows = 128; + // Force every layer onto one reduction dim, so the whole model runs from a + // single xclbin and therefore a single hardware context. Switching contexts + // measured ~0.46 ms per dispatch, which dwarfs the arithmetic these kernels + // do, so paying extra zero-padded multiply-accumulates to avoid it can win + // by a wide margin -- on models whose GEMMs are small. 0 disables it. + int forceK = 0; + bool verbose = false; + }; + + // Returns nullptr (and fills err) when the NPU cannot be used at all, which + // is an ordinary outcome: callers then run entirely on the CPU path. + Accel* create(const Options& options, std::string& err); + void free(Accel* accel); + + // out[numRows][outChannels] = in[numRows][inChannels] * weights, matching + // reference.cpp's matmulRows exactly. Returns false without touching `out` + // if this layer is not eligible or no artifact covers it, in which case the + // caller must run its own implementation. + bool tryMatmul( + Accel* accel, float* out, const float* in, const MatMulLayerDesc& desc, int numRows); + + // Several projections that read the same input (attention's q/k/vProj, the + // FFN's linear1/linearGate) fused into one GEMM: the weights are + // concatenated along N once at upload, so one dispatch replaces numDescs. + // out[j] receives descs[j]'s columns. Returns false without touching any + // output if the group is not eligible; the caller runs each layer itself. + bool tryMatmulMulti( + Accel* accel, float* const* outs, const float* in, + const MatMulLayerDesc* const* descs, int numDescs, int numRows); + + // The transformer FFN's SwiGLU: out = silu(in @ linear1) * (in @ + // linearGate), with both projections fused into ONE GEMM dispatch whose + // epilogue applies the silu and the multiply on chip. Requires a + // gemm_swiglu_bf16 artifact for the layer's reduction dim (a separate + // xclbin, hence a separate hardware context) and outChannels % 8 == 0 -- + // the uploaded B interleaves the two weight matrices in groups of 8 columns + // so each core's C tile holds (linear1, gate) sub-tile pairs. Returns false + // without touching `out` when unavailable; the caller then runs the two + // projections and the elementwise SwiGLU itself. + bool tryMatmulSwiglu( + Accel* accel, float* out, const float* in, + const MatMulLayerDesc& linear1, const MatMulLayerDesc& linearGate, int numRows); + + // A 1x1 convolution is a dense layer over board points, so it takes the same + // path. Declines anything with a larger kernel. ConvLayerDesc stores weights + // as outChannels x inChannels, the transpose of what the GEMM wants, so those + // are transposed once at upload rather than per evaluation. + // + // accumulate adds into `out` instead of overwriting it, matching + // reference.cpp's convNHWC. + bool tryConv1x1( + Accel* accel, float* out, const float* in, const ConvLayerDesc& desc, int numRows, + bool accumulate); + + // BatchNorm + Mish fused op (out = mish(scale*x + bias) per channel), for + // the convolutional model's trunk norms. Only handles Mish and full boards + // (masked positions would need zeroing the staged path does); anything else + // returns false and the caller runs its CPU loop. rows = batchSize*S. + bool tryBnMish( + Accel* accel, float* out, const float* in, const BatchNormLayerDesc& bn, + int activation, int numRows); + + // A convolution with a larger kernel becomes the same GEMM once its input + // patches are gathered into rows: K = convY*convX*inChannels, one row per + // board point ("implicit GEMM"). The gather costs one pass over the input per + // tap, which is far cheaper than the direct convolution it replaces. + // + // Declines when no artifact reaches K, which for a 3x3 means 9*inChannels. + bool tryConv( + Accel* accel, float* out, const float* in, const ConvLayerDesc& desc, int batchSize, + int nnXLen, int nnYLen, bool accumulate); + + // Routes the two attention matmuls (QK^T and P*V) of one transformer + // attention block to the NPU: one GEMM per batch element each way, with all + // heads laid out side by side along A's reduction dim and a block-diagonal + // B built from the K / V activations, so a block costs 2 dispatches per + // batch element instead of 2 per head (a dispatch costs ~1 ms regardless of + // size; the multiply-accumulates are nearly free). The softmax in between + // goes to the NPU too when an op compiled for exactly this (numHeads*S, S) + // shape is present under artifactDir/ops; otherwise it runs on the CPU. + // Either way the semantics are exactly the reference path's (scale on the + // scores, masked-out query rows produce exact zeros, masked-out key columns + // excluded -- as -1e30 through the NPU softmax, whose exp underflows to 0). + // + // Unlike layer weights, the B operands here (the K and V activations) + // change every evaluation, so they are re-uploaded per dispatch through + // RyzenAIKernel::rewriteWeights into BOs that stay resident. + // + // qBuf/kBuf/vBuf are [batchSize][S][qTot/kTot/vTot] with the per-head slices + // at h*qHeadDim and kvh*qHeadDim / kvh*vHeadDim (kvh = h / (numHeads/ + // numKVHeads)); attnOut is [batchSize][S][numHeads*vHeadDim]; mask is + // [batchSize][S] with 1.0f on-board. All exactly as reference.cpp's + // applyTransformerAttentionBlock already lays them out. + // + // softmaxSecsOut, when non-null, accumulates the wall clock spent in the + // on-CPU softmax so the caller's profile can keep attributing it. + // + // Returns false if any piece is not eligible or a dispatch failed. attnOut + // may then be partially written, so the caller must run its own + // implementation for the whole block, which overwrites it fully. + bool tryAttention( + Accel* accel, float* attnOut, + const float* qBuf, const float* kBuf, const float* vBuf, const float* mask, + int batchSize, int S, int numHeads, int numKVHeads, int qHeadDim, int vHeadDim, + double* softmaxSecsOut); + + // Per-layer accounting, for logging: how many dense layers were routed to the + // NPU, how many fell back, and why. + std::string report(const Accel* accel); + +} // namespace RyzenAIMatMul + +#endif // NEURALNET_RYZENAI_MATMUL_H_ diff --git a/cpp/neuralnet/ryzenaireference.cpp b/cpp/neuralnet/ryzenaireference.cpp new file mode 100644 index 000000000..b74a5ac4c --- /dev/null +++ b/cpp/neuralnet/ryzenaireference.cpp @@ -0,0 +1,1361 @@ +/* + * Pure C++ (C++17, standard library only) CPU reference implementation of the + * KataGo neural network forward pass, for the RyzenAI (AMD NPU) backend. + * See reference.h for the API and the exact input/output buffer contracts. + * + * The math here is a direct, loop-level port of cpp/neuralnet/eigenbackend.cpp + * (Winograd convolutions there are replaced by plain direct convolutions, + * which are mathematically identical). Internal layout is NHWC throughout. + * + * No heap allocation happens inside forward(): all scratch is bump-allocated + * from an arena whose exact worst-case size is computed in createWorkspace(). + */ + +#include "../neuralnet/ryzenaireference.h" + +#include +#include +#include +#include +#include + +#include "../neuralnet/activations.h" +#include "../neuralnet/ryzenaimatmul.h" + +#include +#include + +namespace RyzenAIRef { + +namespace { + +// --------------------------------------------------------------------------- +// Precomputed per-attention-block RoPE cos/sin tables (created once per +// Workspace via TransformerAttentionDesc::computeRopeCosSin). +// --------------------------------------------------------------------------- +struct RopeTables { + std::vector cosTable; + std::vector sinTable; +}; + +// --------------------------------------------------------------------------- +// Bump allocator over a preallocated float arena. No heap traffic at forward +// time; alloc() throws if the compile-time-computed capacity is exceeded +// (which would indicate a bug in the size accounting below). +// --------------------------------------------------------------------------- +struct Arena { + float* base; + size_t capacity; + size_t offset; + + float* alloc(size_t numElts) { + if(numElts > capacity - offset) + throw StringError("RyzenAIRef: internal scratch arena overflow"); + float* p = base + offset; + offset += numElts; + return p; + } + size_t mark() const { return offset; } + void rewind(size_t m) { offset = m; } +}; + +// Coarse profile of the parts that are still on the CPU, so that the next +// thing to move onto the NPU is chosen from measurement rather than from +// multiply-accumulate counts (which have already misled once: see +// references/performance.md). Off unless RyzenAIRef::profileEnabled() is set. +struct CpuProfile { + double attnScores = 0.0; // CPU-path attention only (QK^T, softmax, P*V loops) + double softmax = 0.0; // softmax anywhere: nested in the CPU attention path, + // or reported by the NPU attention path + double norms = 0.0; // RMSNorm / BatchNorm / activations + double rope = 0.0; + double swiglu = 0.0; // silu(linear1) * gate elementwise + double residual = 0.0; // masked residual adds + double gpool = 0.0; + double headSmall = 0.0; // heads' batch-row matmuls and pooling + bool enabled = false; +}; +CpuProfile g_profile; + +inline double nowSecs() { + return std::chrono::duration( + std::chrono::steady_clock::now().time_since_epoch()).count(); +} + +// Adds its lifetime to one bucket. +struct ProfileScope { + double* bucket; + double start; + explicit ProfileScope(double* b) + : bucket(g_profile.enabled ? b : nullptr), start(bucket ? nowSecs() : 0.0) {} + ~ProfileScope() { if(bucket) *bucket += nowSecs() - start; } +}; + +// --------------------------------------------------------------------------- +// Per-forward-pass context handed to every block. +// mask is [batchSize][nnYLen*nnXLen] (1.0f on-board, 0.0f padding). +// --------------------------------------------------------------------------- +struct ForwardCtx { + int batchSize; + int nnXLen; + int nnYLen; + const float* mask; + const float* maskSum; + Arena* arena; + const std::map* ropeTables; + RyzenAIMatMul::Accel* accel; // may be null: then everything stays on the CPU +}; + +// --------------------------------------------------------------------------- +// Scalar activation. Mirrors eigenbackend.cpp exactly, including the +// numerically-stable softplus formulation log1p(exp(min(x,20)))+(max(x,20)-20). +// --------------------------------------------------------------------------- +inline float softplusForMish(float x) { + float lo = x < 20.0f ? x : 20.0f; + float hi = x > 20.0f ? x : 20.0f; + return log1pf(expf(lo)) + (hi - 20.0f); +} + +inline float applyActivation(int activation, float x) { + switch(activation) { + case ACTIVATION_IDENTITY: return x; + case ACTIVATION_RELU: return x > 0.0f ? x : 0.0f; + case ACTIVATION_MISH: return x * tanhf(softplusForMish(x)); + case ACTIVATION_SILU: return x / (1.0f + expf(-x)); + // x * tanh(softplus(8x)); not used by the Eigen backend (fp32 only there), + // but supported here so scale8-transformed descs can also be referenced. + case ACTIVATION_MISH_SCALE8: return x * tanhf(softplusForMish(8.0f * x)); + default: throw StringError("RyzenAIRef: unsupported activation " + std::to_string(activation)); + } +} + +void applyActivationInplace(float* data, size_t numElts, int activation) { + if(activation == ACTIVATION_IDENTITY) + return; + for(size_t i = 0; i < numElts; i++) + data[i] = applyActivation(activation, data[i]); +} + +// --------------------------------------------------------------------------- +// Direct zero-padded cross-correlation, NHWC in and out. +// Weight layout (from ConvLayerDesc): w[((oc*inC + ic)*ky + dy)*kx + dx]. +// out[n][y][x][oc] = sum_{ic,dy,dx} in[n][y+(dy-ky/2)*dilY][x+(dx-kx/2)*dilX][ic] * w[...] +// --------------------------------------------------------------------------- +void convNHWC( + float* out, + const float* in, + const ConvLayerDesc& desc, + int batchSize, + int nnXLen, + int nnYLen, + bool accumulate +) { + const int inC = desc.inChannels; + const int outC = desc.outChannels; + const int kx = desc.convXSize; + const int ky = desc.convYSize; + const int padX = kx / 2; + const int padY = ky / 2; + const int dilX = desc.dilationX; + const int dilY = desc.dilationY; + const float* w = desc.weights.data(); + const size_t kernelPosStride = (size_t)ky * kx; // stride of ic within one oc + + for(int n = 0; n < batchSize; n++) { + for(int y = 0; y < nnYLen; y++) { + for(int x = 0; x < nnXLen; x++) { + size_t outBase = (((size_t)n * nnYLen + y) * nnXLen + x) * outC; + for(int oc = 0; oc < outC; oc++) { + const float* wo = w + (size_t)oc * inC * kernelPosStride; + float acc = 0.0f; + for(int dy = 0; dy < ky; dy++) { + int iy = y + (dy - padY) * dilY; + if(iy < 0 || iy >= nnYLen) + continue; + for(int dx = 0; dx < kx; dx++) { + int ix = x + (dx - padX) * dilX; + if(ix < 0 || ix >= nnXLen) + continue; + size_t inBase = (((size_t)n * nnYLen + iy) * nnXLen + ix) * inC; + const float* wi = wo + (size_t)dy * kx + dx; + for(int ic = 0; ic < inC; ic++) + acc += in[inBase + ic] * wi[(size_t)ic * kernelPosStride]; + } + } + if(accumulate) + out[outBase + oc] += acc; + else + out[outBase + oc] = acc; + } + } + } + } +} + +// --------------------------------------------------------------------------- +// BatchNorm (using precomputed mergedScale/mergedBias) + activation, NHWC. +// Positions where mask != 1.0f are zeroed (exactly as eigenbackend's select). +// --------------------------------------------------------------------------- +void batchNormActNHWC( + float* out, + const float* in, + const BatchNormLayerDesc& bn, + int activation, + const float* mask, + int batchSize, + int nnXLen, + int nnYLen +) { + ProfileScope profileScope(&g_profile.norms); + const int C = bn.numChannels; + const size_t S = (size_t)nnXLen * nnYLen; + for(int n = 0; n < batchSize; n++) { + for(size_t s = 0; s < S; s++) { + size_t base = ((size_t)n * S + s) * C; + if(mask[(size_t)n * S + s] == 1.0f) { + for(int c = 0; c < C; c++) + out[base + c] = applyActivation(activation, in[base + c] * bn.mergedScale[c] + bn.mergedBias[c]); + } + else { + for(int c = 0; c < C; c++) + out[base + c] = 0.0f; + } + } + } +} + +// --------------------------------------------------------------------------- +// Lightweight per-position RMSNorm used inside transformer blocks +// (weight only, no bias, no activation). Masked positions are zeroed. +// --------------------------------------------------------------------------- +void transformerRMSNormNHWC( + float* out, + const float* in, + const TransformerRMSNormDesc& desc, + const float* mask, + int batchSize, + int nnXLen, + int nnYLen +) { + ProfileScope profileScope(&g_profile.norms); + const int C = desc.numChannels; + const size_t S = (size_t)nnXLen * nnYLen; + for(int n = 0; n < batchSize; n++) { + for(size_t s = 0; s < S; s++) { + size_t base = ((size_t)n * S + s) * C; + if(mask[(size_t)n * S + s] == 0.0f) { + for(int c = 0; c < C; c++) + out[base + c] = 0.0f; + continue; + } + float sumSq = 0.0f; + for(int c = 0; c < C; c++) { + float v = in[base + c]; + sumSq += v * v; + } + float rms = 1.0f / sqrtf(sumSq / (float)C + desc.epsilon); + for(int c = 0; c < C; c++) + out[base + c] = in[base + c] * rms * desc.weight[c]; + } + } +} + +// --------------------------------------------------------------------------- +// Full RMSNorm for the trunk tip (gamma+beta+activation, spatial or +// non-spatial). Direct port of RMSNormLayer in eigenbackend.cpp. +// Non-spatial: normalize across channels per position. +// Spatial: normalize across channels AND all valid (masked-in) positions. +// --------------------------------------------------------------------------- +void trunkTipRMSNormNHWC( + float* out, + const float* in, + const RMSNormLayerDesc& desc, + int activation, + const float* mask, + int batchSize, + int nnXLen, + int nnYLen +) { + const int C = desc.numChannels; + const size_t S = (size_t)nnXLen * nnYLen; + if(!desc.spatial) { + for(int n = 0; n < batchSize; n++) { + for(size_t s = 0; s < S; s++) { + size_t base = ((size_t)n * S + s) * C; + if(mask[(size_t)n * S + s] == 0.0f) { + for(int c = 0; c < C; c++) + out[base + c] = 0.0f; + continue; + } + float sumSq = 0.0f; + for(int c = 0; c < C; c++) { + float v = in[base + c]; + sumSq += v * v; + } + float rms = 1.0f / sqrtf(sumSq / (float)C + desc.epsilon); + for(int c = 0; c < C; c++) + out[base + c] = applyActivation(activation, in[base + c] * rms * desc.gamma[c] + desc.beta[c]); + } + } + } + else { + for(int n = 0; n < batchSize; n++) { + float sumSq = 0.0f; + size_t count = 0; + for(size_t s = 0; s < S; s++) { + if(mask[(size_t)n * S + s] == 0.0f) + continue; + size_t base = ((size_t)n * S + s) * C; + for(int c = 0; c < C; c++) { + float v = in[base + c]; + sumSq += v * v; + } + count++; + } + float totalElts = (float)count * (float)C; + float rms = 1.0f / sqrtf(sumSq / totalElts + desc.epsilon); + for(size_t s = 0; s < S; s++) { + size_t base = ((size_t)n * S + s) * C; + if(mask[(size_t)n * S + s] == 0.0f) { + for(int c = 0; c < C; c++) + out[base + c] = 0.0f; + continue; + } + for(int c = 0; c < C; c++) + out[base + c] = applyActivation(activation, in[base + c] * rms * desc.gamma[c] + desc.beta[c]); + } + } + } +} + +// --------------------------------------------------------------------------- +// Dense layer over rows: out[r][oc] = sum_ic in[r][ic] * W[ic*outC + oc]. +// Used for all MatMulLayerDesc applications. The "rows" are either batch +// rows ([N][C]) or flattened batch*spatial rows ([N*H*W][C]). +// --------------------------------------------------------------------------- +void matmulRows(float* out, const float* in, const MatMulLayerDesc& desc, int numRows) { + const int inC = desc.inChannels; + const int outC = desc.outChannels; + const float* w = desc.weights.data(); + for(int r = 0; r < numRows; r++) { + const float* inRow = in + (size_t)r * inC; + float* outRow = out + (size_t)r * outC; + for(int oc = 0; oc < outC; oc++) + outRow[oc] = 0.0f; + for(int ic = 0; ic < inC; ic++) { + float iv = inRow[ic]; + const float* wRow = w + (size_t)ic * outC; + for(int oc = 0; oc < outC; oc++) + outRow[oc] += iv * wRow[oc]; + } + } +} + +// Every convolution is offered to the NPU: 1x1 directly as a dense layer, +// larger kernels via implicit GEMM (the accelerator gathers the input patches +// itself). Anything it declines falls through to the direct convolution. +void convNHWCMaybeNpu( + ForwardCtx& ctx, + float* out, + const float* in, + const ConvLayerDesc& desc, + int batchSize, + int nnXLen, + int nnYLen, + bool accumulate +) { + if(RyzenAIMatMul::tryConv(ctx.accel, out, in, desc, batchSize, nnXLen, nnYLen, accumulate)) + return; + convNHWC(out, in, desc, batchSize, nnXLen, nnYLen, accumulate); +} + +// Same, but offers the layer to the NPU first. Used only for the trunk's +// board-sized dense layers; the heads' batch-row matmuls are far too small to +// repay a dispatch and call matmulRows directly. +void matmulRowsMaybeNpu( + ForwardCtx& ctx, float* out, const float* in, const MatMulLayerDesc& desc, int numRows) { + if(RyzenAIMatMul::tryMatmul(ctx.accel, out, in, desc, numRows)) + return; + matmulRows(out, in, desc, numRows); +} + +// Projections that share an input go to the NPU as one fused GEMM; if the +// accelerator declines, each runs the ordinary maybe-NPU path on its own. +void matmulRowsMultiMaybeNpu( + ForwardCtx& ctx, + float* const* outs, + const float* in, + const MatMulLayerDesc* const* descs, + int numDescs, + int numRows +) { + if(RyzenAIMatMul::tryMatmulMulti(ctx.accel, outs, in, descs, numDescs, numRows)) + return; + for(int j = 0; j < numDescs; j++) + matmulRowsMaybeNpu(ctx, outs[j], in, *descs[j], numRows); +} + +// BatchNorm+activation, offered to the NPU first when it's Mish on a full +// board (the fused op handles exactly that; anything else falls through). +void bnActMaybeNpu( + ForwardCtx& ctx, + float* out, + const float* in, + const BatchNormLayerDesc& bn, + int activation, + int batchSize, + int nnXLen, + int nnYLen +) { + const size_t S = (size_t)nnXLen * nnYLen; + bool fullBoard = true; + for(int n = 0; n < batchSize; n++) + if(ctx.maskSum[n] != (float)S) { + fullBoard = false; + break; + } + if(fullBoard && + RyzenAIMatMul::tryBnMish(ctx.accel, out, in, bn, activation, batchSize * (int)S)) + return; + batchNormActNHWC(out, in, bn, activation, ctx.mask, batchSize, nnXLen, nnYLen); +} + +// io[r][c] += bias[c] +void matBiasAddRows(float* io, const MatBiasLayerDesc& desc, int numRows) { + const int C = desc.numChannels; + for(int r = 0; r < numRows; r++) { + float* row = io + (size_t)r * C; + for(int c = 0; c < C; c++) + row[c] += desc.weights[c]; + } +} + +// io[n][y][x][c] += bias[n][c] (addNCBiasInplace in eigenbackend.cpp) +void addPerBatchChannelBiasNHWC( + float* io, + const float* bias, + int C, + int batchSize, + int nnXLen, + int nnYLen +) { + const size_t S = (size_t)nnXLen * nnYLen; + for(int n = 0; n < batchSize; n++) { + const float* biasN = bias + (size_t)n * C; + for(size_t s = 0; s < S; s++) { + float* row = io + ((size_t)n * S + s) * C; + for(int c = 0; c < C; c++) + row[c] += biasN[c]; + } + } +} + +// --------------------------------------------------------------------------- +// Global pooling for gpool residual blocks / policy head. +// in: [N][H][W][C] (must be zero at masked-out positions, which holds because +// this only ever follows a masked BN+activation), out: [N][3*C] with +// [c] = mean over valid positions (denominator = maskSum) +// [C+c] = mean * (sqrt(maskSum) - 14) * 0.1 +// [2*C+c] = max over valid positions +// Direct port of poolRowsGPool in eigenbackend.cpp. +// --------------------------------------------------------------------------- +void poolRowsGPoolNHWC( + float* out, + const float* in, + const float* mask, + const float* maskSum, + int C, + int batchSize, + int nnXLen, + int nnYLen +) { + const size_t S = (size_t)nnXLen * nnYLen; + for(int n = 0; n < batchSize; n++) { + const float* inN = in + (size_t)n * S * C; + const float* maskN = mask + (size_t)n * S; + float* outN = out + (size_t)n * 3 * C; + for(int c = 0; c < C; c++) { + float s = 0.0f; + float m = -1.0f; + for(size_t xy = 0; xy < S; xy++) { + float x = inN[xy * C + c]; + s += x; + // Init to -1.0 and +(mask-1.0) makes padded space effectively -1.0, + // below anything current activations produce (padded inputs are 0). + float xm = x + (maskN[xy] - 1.0f); + if(xm > m) + m = xm; + } + float div = maskSum[n]; + float sqrtdiv = sqrtf(div); + float mean = s / div; + outN[c] = mean; + outN[C + c] = mean * (sqrtdiv - 14.0f) * 0.1f; + outN[2 * C + c] = m; + } + } +} + +// --------------------------------------------------------------------------- +// Global pooling for the value head. out: [N][3*C] with +// [c] = mean +// [C+c] = mean * (sqrt(maskSum) - 14) * 0.1 +// [2*C+c] = mean * ((sqrt(maskSum) - 14)^2 * 0.01 - 0.1) +// Direct port of poolRowsValueHead in eigenbackend.cpp. +// --------------------------------------------------------------------------- +void poolRowsValueHeadNHWC( + float* out, + const float* in, + const float* maskSum, + int C, + int batchSize, + int nnXLen, + int nnYLen +) { + const size_t S = (size_t)nnXLen * nnYLen; + for(int n = 0; n < batchSize; n++) { + const float* inN = in + (size_t)n * S * C; + float* outN = out + (size_t)n * 3 * C; + for(int c = 0; c < C; c++) { + float s = 0.0f; + for(size_t xy = 0; xy < S; xy++) + s += inN[xy * C + c]; + float div = maskSum[n]; + float sqrtdiv = sqrtf(div); + float mean = s / div; + outN[c] = mean; + outN[C + c] = mean * (sqrtdiv - 14.0f) * 0.1f; + outN[2 * C + c] = mean * ((sqrtdiv - 14.0f) * (sqrtdiv - 14.0f) * 0.01f - 0.1f); + } + } +} + +// --------------------------------------------------------------------------- +// Blocks. `trunk` is the [N][H][W][C] residual stream, updated in place. +// `trunkScratch` is a caller-provided buffer of the same shape used for +// norm outputs / projection results. All other intermediates come from the +// arena and are released (rewound) before the block returns. +// --------------------------------------------------------------------------- +void applyBlockStack( + const std::vector>& blocks, + int numBlocks, + ForwardCtx& ctx, + float* trunk, + float* trunkScratch +); + +// ORDINARY_BLOCK_KIND +void applyResidualBlock( + const ResidualBlockDesc& desc, + ForwardCtx& ctx, + float* trunk, + float* trunkScratch +) { + const int N = ctx.batchSize; + const int W = ctx.nnXLen; + const int H = ctx.nnYLen; + const size_t BXY = (size_t)N * W * H; + const int midC = desc.regularConv.outChannels; + + size_t mark = ctx.arena->mark(); + float* midIn = ctx.arena->alloc(BXY * midC); + float* midScratch = ctx.arena->alloc(BXY * midC); + + bnActMaybeNpu(ctx, trunkScratch, trunk, desc.preBN, desc.preActivation.activation, N, W, H); + convNHWCMaybeNpu(ctx, midIn, trunkScratch, desc.regularConv, N, W, H, false); + bnActMaybeNpu(ctx, midScratch, midIn, desc.midBN, desc.midActivation.activation, N, W, H); + convNHWCMaybeNpu(ctx, trunk, midScratch, desc.finalConv, N, W, H, true); + + ctx.arena->rewind(mark); +} + +// GLOBAL_POOLING_BLOCK_KIND +void applyGlobalPoolingResidualBlock( + const GlobalPoolingResidualBlockDesc& desc, + ForwardCtx& ctx, + float* trunk, + float* trunkScratch +) { + const int N = ctx.batchSize; + const int W = ctx.nnXLen; + const int H = ctx.nnYLen; + const size_t BXY = (size_t)N * W * H; + const int regC = desc.regularConv.outChannels; + const int gpoolC = desc.gpoolConv.outChannels; + + size_t mark = ctx.arena->mark(); + float* regularOut = ctx.arena->alloc(BXY * regC); + float* regularScratch = ctx.arena->alloc(BXY * regC); + float* gpoolOut = ctx.arena->alloc(BXY * gpoolC); + float* gpoolOut2 = ctx.arena->alloc(BXY * gpoolC); + float* gpoolConcat = ctx.arena->alloc((size_t)N * 3 * gpoolC); + float* gpoolBias = ctx.arena->alloc((size_t)N * regC); + + bnActMaybeNpu(ctx, trunkScratch, trunk, desc.preBN, desc.preActivation.activation, N, W, H); + convNHWCMaybeNpu(ctx, regularOut, trunkScratch, desc.regularConv, N, W, H, false); + convNHWCMaybeNpu(ctx, gpoolOut, trunkScratch, desc.gpoolConv, N, W, H, false); + bnActMaybeNpu(ctx, gpoolOut2, gpoolOut, desc.gpoolBN, desc.gpoolActivation.activation, N, W, H); + poolRowsGPoolNHWC(gpoolConcat, gpoolOut2, ctx.mask, ctx.maskSum, gpoolC, N, W, H); + matmulRows(gpoolBias, gpoolConcat, desc.gpoolToBiasMul, N); + addPerBatchChannelBiasNHWC(regularOut, gpoolBias, regC, N, W, H); + bnActMaybeNpu(ctx, regularScratch, regularOut, desc.midBN, desc.midActivation.activation, N, W, H); + convNHWCMaybeNpu(ctx, trunk, regularScratch, desc.finalConv, N, W, H, true); + + ctx.arena->rewind(mark); +} + +// NESTED_BOTTLENECK_BLOCK_KIND (inner stack may contain any block kind) +void applyNestedBottleneckResidualBlock( + const NestedBottleneckResidualBlockDesc& desc, + ForwardCtx& ctx, + float* trunk, + float* trunkScratch +) { + const int N = ctx.batchSize; + const int W = ctx.nnXLen; + const int H = ctx.nnYLen; + const size_t BXY = (size_t)N * W * H; + const int bottleC = desc.preConv.outChannels; + size_t mark = ctx.arena->mark(); + float* midIn = ctx.arena->alloc(BXY * bottleC); + float* midScratch = ctx.arena->alloc(BXY * bottleC); + + bnActMaybeNpu(ctx, trunkScratch, trunk, desc.preBN, desc.preActivation.activation, N, W, H); + convNHWCMaybeNpu(ctx, midIn, trunkScratch, desc.preConv, N, W, H, false); + // The inner block stack treats midIn as its residual stream and midScratch + // as its scratch. + applyBlockStack(desc.blocks, desc.numBlocks, ctx, midIn, midScratch); + bnActMaybeNpu(ctx, midScratch, midIn, desc.postBN, desc.postActivation.activation, N, W, H); + convNHWCMaybeNpu(ctx, trunk, midScratch, desc.postConv, N, W, H, true); + + ctx.arena->rewind(mark); +} + +// TRANSFORMER_ATTENTION_BLOCK_KIND +// Multi-head attention with grouped-query KV heads, optional RoPE (learnable +// or fixed), masked softmax. Direct port of TransformerAttentionBlock in +// eigenbackend.cpp. +void applyTransformerAttentionBlock( + const TransformerAttentionDesc& desc, + ForwardCtx& ctx, + float* trunk, + float* trunkScratch +) { + const int N = ctx.batchSize; + const int W = ctx.nnXLen; + const int H = ctx.nnYLen; + const int S = W * H; + const size_t BXY = (size_t)N * S; + const int inC = desc.qProj.inChannels; + const int numHeads = desc.numHeads; + const int numKVHeads = desc.numKVHeads; + const int qHeadDim = desc.qHeadDim; + const int vHeadDim = desc.vHeadDim; + const int qTot = numHeads * qHeadDim; + const int kTot = numKVHeads * qHeadDim; + const int vTot = numKVHeads * vHeadDim; + const int oTot = numHeads * vHeadDim; + + const RopeTables* rope = nullptr; + if(desc.useRope) { + std::map::const_iterator it = ctx.ropeTables->find((const void*)&desc); + if(it == ctx.ropeTables->end()) + throw StringError("RyzenAIRef: missing RoPE tables for attention block " + desc.name); + rope = &it->second; + } + + size_t mark = ctx.arena->mark(); + float* qBuf = ctx.arena->alloc(BXY * qTot); + float* kBuf = ctx.arena->alloc(BXY * kTot); + float* vBuf = ctx.arena->alloc(BXY * vTot); + float* attnOut = ctx.arena->alloc(BXY * oTot); + float* scores = ctx.arena->alloc((size_t)S * S); + + // Step 1: pre-norm (per-position RMSNorm), masked. + transformerRMSNormNHWC(trunkScratch, trunk, desc.preLN, ctx.mask, N, W, H); + + // Step 2: Q/K/V projections; the [N][H][W][C] tensors are treated as + // [N*S][C] row matrices (C innermost, so rows are contiguous). + { + float* qkvOuts[3] = {qBuf, kBuf, vBuf}; + const MatMulLayerDesc* qkvDescs[3] = {&desc.qProj, &desc.kProj, &desc.vProj}; + matmulRowsMultiMaybeNpu(ctx, qkvOuts, trunkScratch, qkvDescs, 3, N * S); + } + + // Step 3: RoPE on Q and K, rotating channel pairs (2p, 2p+1). + { + ProfileScope ropeScope(&g_profile.rope); + if(desc.useRope) { + const int ropeNumPairs = qHeadDim / 2; + for(int which = 0; which < 2; which++) { + float* data = which == 0 ? qBuf : kBuf; + const int numBufHeads = which == 0 ? numHeads : numKVHeads; + const int totalDim = which == 0 ? qTot : kTot; + for(int n = 0; n < N; n++) { + for(int h = 0; h < numBufHeads; h++) { + // For Q heads, map to the corresponding KV head; for K heads, identity. + const int kvh = h * numKVHeads / numBufHeads; + for(int xy = 0; xy < S; xy++) { + size_t rowBase = ((size_t)n * S + xy) * totalDim + (size_t)h * qHeadDim; + for(int p = 0; p < ropeNumPairs; p++) { + size_t tableIdx; + if(desc.learnableRope) + tableIdx = ((size_t)kvh * ropeNumPairs + p) * S + xy; + else + tableIdx = (size_t)p * S + xy; + float cosVal = rope->cosTable[tableIdx]; + float sinVal = rope->sinTable[tableIdx]; + size_t i0 = rowBase + 2 * p; + float x0 = data[i0]; + float x1 = data[i0 + 1]; + data[i0] = x0 * cosVal - x1 * sinVal; + data[i0 + 1] = x0 * sinVal + x1 * cosVal; + } + } + } + } + } + } + + } // ropeScope + + // Step 4: masked scaled dot-product attention, per (batch, head). + { + // Offer the two matmuls (QK^T and P*V) to the NPU first. The softmax + // between them stays on the CPU either way; whatever the accelerator + // declines runs the original CPU loops below, byte-for-byte unchanged + // (and deliberately left at their original indentation). + // + // Profiling note: the NPU path's time is accounted inside matmul.cpp + // (pack/uploadB/dispatch/unpack/softmax), so the attnScores bucket must + // only wrap the CPU loops -- wrapping the dispatch too would double-count + // it against engineTimings' execute window. + double npuSoftmaxSecs = 0.0; + const bool attnOnNpu = RyzenAIMatMul::tryAttention( + ctx.accel, attnOut, qBuf, kBuf, vBuf, ctx.mask, N, S, + numHeads, numKVHeads, qHeadDim, vHeadDim, + g_profile.enabled ? &npuSoftmaxSecs : nullptr); + g_profile.softmax += npuSoftmaxSecs; + if(!attnOnNpu) { + ProfileScope profileScope(&g_profile.attnScores); + const float scale = 1.0f / sqrtf((float)qHeadDim); + const int kvGroupSize = numHeads / numKVHeads; + for(int n = 0; n < N; n++) { + const float* maskN = ctx.mask + (size_t)n * S; + for(int h = 0; h < numHeads; h++) { + const int kvh = h / kvGroupSize; + const float* qHead = qBuf + (size_t)n * S * qTot + (size_t)h * qHeadDim; + const float* kHead = kBuf + (size_t)n * S * kTot + (size_t)kvh * qHeadDim; + const float* vHead = vBuf + (size_t)n * S * vTot + (size_t)kvh * vHeadDim; + float* outHead = attnOut + (size_t)n * S * oTot + (size_t)h * vHeadDim; + + // scores[qi*S + ki] = softmax over valid ki of (scale * ). + // Rows of masked-out queries are exactly 0 (as in eigenbackend). + for(int qi = 0; qi < S; qi++) { + float* scoreRow = scores + (size_t)qi * S; + if(maskN[qi] == 0.0f) { + for(int ki = 0; ki < S; ki++) + scoreRow[ki] = 0.0f; + continue; + } + const float* qRow = qHead + (size_t)qi * qTot; + float maxVal = -1e30f; + for(int ki = 0; ki < S; ki++) { + if(maskN[ki] == 0.0f) { + scoreRow[ki] = 0.0f; + continue; + } + const float* kRow = kHead + (size_t)ki * kTot; + float acc = 0.0f; + for(int d = 0; d < qHeadDim; d++) + acc += qRow[d] * kRow[d]; + acc *= scale; + scoreRow[ki] = acc; + if(acc > maxVal) + maxVal = acc; + } + { + ProfileScope softmaxScope(&g_profile.softmax); + float sumExp = 0.0f; + for(int ki = 0; ki < S; ki++) { + if(maskN[ki] == 0.0f) + continue; + float e = expf(scoreRow[ki] - maxVal); + scoreRow[ki] = e; + sumExp += e; + } + float invSum = 1.0f / sumExp; + for(int ki = 0; ki < S; ki++) { + if(maskN[ki] != 0.0f) + scoreRow[ki] *= invSum; + } + } + } + + // attnOut[qi, h*vHeadDim + dv] = sum_ki scores[qi,ki] * V[ki, kvh*vHeadDim + dv] + for(int qi = 0; qi < S; qi++) { + const float* scoreRow = scores + (size_t)qi * S; + float* outRow = outHead + (size_t)qi * oTot; + for(int dv = 0; dv < vHeadDim; dv++) + outRow[dv] = 0.0f; + for(int ki = 0; ki < S; ki++) { + float wgt = scoreRow[ki]; + if(wgt == 0.0f) + continue; // exact: 0-weight terms contribute nothing + const float* vRow = vHead + (size_t)ki * vTot; + for(int dv = 0; dv < vHeadDim; dv++) + outRow[dv] += wgt * vRow[dv]; + } + } + } + } + } // !attnOnNpu + } + + // Step 5: output projection back to trunk channels. + matmulRowsMaybeNpu(ctx, trunkScratch, attnOut, desc.outProj, N * S); + + // Step 6: residual add, masked (padded positions stay untouched). + ProfileScope residualScope(&g_profile.residual); + for(int n = 0; n < N; n++) { + const float* maskN = ctx.mask + (size_t)n * S; + for(int xy = 0; xy < S; xy++) { + float maskVal = maskN[xy]; + size_t base = ((size_t)n * S + xy) * inC; + for(int c = 0; c < inC; c++) + trunk[base + c] += trunkScratch[base + c] * maskVal; + } + } + + ctx.arena->rewind(mark); +} + +// TRANSFORMER_FFN_BLOCK_KIND (SwiGLU form; useSwiGLU is validated at +// workspace creation time, matching the Eigen backend's restriction). +void applyTransformerFFNBlock( + const TransformerFFNDesc& desc, + ForwardCtx& ctx, + float* trunk, + float* trunkScratch +) { + const int N = ctx.batchSize; + const int W = ctx.nnXLen; + const int H = ctx.nnYLen; + const int S = W * H; + const size_t BXY = (size_t)N * S; + const int C = desc.numChannels; + const int ffnC = desc.ffnChannels; + return; + + size_t mark = ctx.arena->mark(); + float* ffnBuf = ctx.arena->alloc(BXY * ffnC); + float* gateBuf = ctx.arena->alloc(BXY * ffnC); + + // Step 1: pre-norm, masked. + transformerRMSNormNHWC(trunkScratch, trunk, desc.preLN, ctx.mask, N, W, H); + + // Step 2/3: SwiGLU = silu(linear1(x)) * linearGate(x), applied to all rows. + // The NPU path fuses both projections into one GEMM whose epilogue applies + // the silu and the multiply on chip, so ffnBuf comes back holding the + // finished SwiGLU output and the elementwise loop below is skipped. + const bool swigluOnNpu = RyzenAIMatMul::tryMatmulSwiglu( + ctx.accel, ffnBuf, trunkScratch, desc.linear1, desc.linearGate, N * S); + if(!swigluOnNpu) { + { + float* ffnOuts[2] = {ffnBuf, gateBuf}; + const MatMulLayerDesc* ffnDescs[2] = {&desc.linear1, &desc.linearGate}; + matmulRowsMultiMaybeNpu(ctx, ffnOuts, trunkScratch, ffnDescs, 2, N * S); + } + ProfileScope swigluScope(&g_profile.swiglu); + const size_t total = BXY * ffnC; + for(size_t i = 0; i < total; i++) { + float a = ffnBuf[i]; + float siluA = a / (1.0f + expf(-a)); + ffnBuf[i] = siluA * gateBuf[i]; + } + } + + // Step 4: down projection back to trunk channels. + matmulRowsMaybeNpu(ctx, trunkScratch, ffnBuf, desc.linear2, N * S); + + // Step 5: residual add, masked. + ProfileScope residualScope(&g_profile.residual); + for(int n = 0; n < N; n++) { + const float* maskN = ctx.mask + (size_t)n * S; + for(int xy = 0; xy < S; xy++) { + float maskVal = maskN[xy]; + size_t base = ((size_t)n * S + xy) * C; + for(int c = 0; c < C; c++) + trunk[base + c] += trunkScratch[base + c] * maskVal; + } + } + + ctx.arena->rewind(mark); +} + +void applySingleBlock( + int kind, + const void* descPtr, + ForwardCtx& ctx, + float* trunk, + float* trunkScratch +) { + switch(kind) { + case ORDINARY_BLOCK_KIND: + applyResidualBlock(*(const ResidualBlockDesc*)descPtr, ctx, trunk, trunkScratch); + break; + case GLOBAL_POOLING_BLOCK_KIND: + applyGlobalPoolingResidualBlock(*(const GlobalPoolingResidualBlockDesc*)descPtr, ctx, trunk, trunkScratch); + break; + case NESTED_BOTTLENECK_BLOCK_KIND: + applyNestedBottleneckResidualBlock(*(const NestedBottleneckResidualBlockDesc*)descPtr, ctx, trunk, trunkScratch); + break; + case TRANSFORMER_ATTENTION_BLOCK_KIND: + applyTransformerAttentionBlock(*(const TransformerAttentionDesc*)descPtr, ctx, trunk, trunkScratch); + break; + case TRANSFORMER_FFN_BLOCK_KIND: + applyTransformerFFNBlock(*(const TransformerFFNDesc*)descPtr, ctx, trunk, trunkScratch); + break; + default: + throw StringError("RyzenAIRef: unknown block kind " + std::to_string(kind)); + } +} + +void applyBlockStack( + const std::vector>& blocks, + int numBlocks, + ForwardCtx& ctx, + float* trunk, + float* trunkScratch +) { + for(int i = 0; i < numBlocks; i++) + applySingleBlock(blocks[i].first, blocks[i].second.get(), ctx, trunk, trunkScratch); +} + +// --------------------------------------------------------------------------- +// SGF metadata encoder: mul1+bias1+act1, mul2+bias2+act2, mul3. +// input: [N][numInputMetaChannels], output: [N][trunkNumChannels]. +// --------------------------------------------------------------------------- +void applySGFMetadataEncoder( + const SGFMetadataEncoderDesc& desc, + ForwardCtx& ctx, + const float* input, + float* output +) { + const int N = ctx.batchSize; + size_t mark = ctx.arena->mark(); + float* internal1 = ctx.arena->alloc((size_t)N * desc.mul1.outChannels); + float* internal2 = ctx.arena->alloc((size_t)N * desc.mul2.outChannels); + + matmulRows(internal1, input, desc.mul1, N); + matBiasAddRows(internal1, desc.bias1, N); + applyActivationInplace(internal1, (size_t)N * desc.mul1.outChannels, desc.act1.activation); + matmulRows(internal2, internal1, desc.mul2, N); + matBiasAddRows(internal2, desc.bias2, N); + applyActivationInplace(internal2, (size_t)N * desc.mul2.outChannels, desc.act2.activation); + matmulRows(output, internal2, desc.mul3, N); + + ctx.arena->rewind(mark); +} + +// --------------------------------------------------------------------------- +// Policy head. trunk: [N][H][W][trunkC] (post tip-norm). +// policy: [N][H][W][numPolicyChannels] logits, policyPass: [N][numPolicyChannels]. +// --------------------------------------------------------------------------- +void applyPolicyHead( + const PolicyHeadDesc& desc, + ForwardCtx& ctx, + const float* trunk, + float* policyPass, + float* policy +) { + const int N = ctx.batchSize; + const int W = ctx.nnXLen; + const int H = ctx.nnYLen; + const size_t BXY = (size_t)N * W * H; + const int p1C = desc.p1Conv.outChannels; + const int g1C = desc.g1Conv.outChannels; + + size_t mark = ctx.arena->mark(); + float* p1Out = ctx.arena->alloc(BXY * p1C); + float* p1Out2 = ctx.arena->alloc(BXY * p1C); + float* g1Out = ctx.arena->alloc(BXY * g1C); + float* g1Out2 = ctx.arena->alloc(BXY * g1C); + float* g1Concat = ctx.arena->alloc((size_t)N * 3 * g1C); + float* g1Bias = ctx.arena->alloc((size_t)N * p1C); + float* p1Pass = ctx.arena->alloc((size_t)N * p1C); + + convNHWCMaybeNpu(ctx, p1Out, trunk, desc.p1Conv, N, W, H, false); + convNHWCMaybeNpu(ctx, g1Out, trunk, desc.g1Conv, N, W, H, false); + batchNormActNHWC(g1Out2, g1Out, desc.g1BN, desc.g1Activation.activation, ctx.mask, N, W, H); + poolRowsGPoolNHWC(g1Concat, g1Out2, ctx.mask, ctx.maskSum, g1C, N, W, H); + matmulRows(g1Bias, g1Concat, desc.gpoolToBiasMul, N); + addPerBatchChannelBiasNHWC(p1Out, g1Bias, p1C, N, W, H); + batchNormActNHWC(p1Out2, p1Out, desc.p1BN, desc.p1Activation.activation, ctx.mask, N, W, H); + // Raw logits; intentionally NOT masked after the final conv (as eigenbackend). + convNHWCMaybeNpu(ctx, policy, p1Out2, desc.p2Conv, N, W, H, false); + + if(desc.modelVersion >= 15) { + matmulRows(p1Pass, g1Concat, desc.gpoolToPassMul, N); + matBiasAddRows(p1Pass, desc.gpoolToPassBias, N); + applyActivationInplace(p1Pass, (size_t)N * p1C, desc.passActivation.activation); + matmulRows(policyPass, p1Pass, desc.gpoolToPassMul2, N); + } + else { + matmulRows(policyPass, g1Concat, desc.gpoolToPassMul, N); + } + + ctx.arena->rewind(mark); +} + +// --------------------------------------------------------------------------- +// Value head. trunk: [N][H][W][trunkC] (post tip-norm). +// value: [N][numValueChannels] logits, scoreValue: [N][numScoreValueChannels] +// raw, ownership: [N][H][W][numOwnershipChannels] pre-tanh, unmasked. +// --------------------------------------------------------------------------- +void applyValueHead( + const ValueHeadDesc& desc, + ForwardCtx& ctx, + const float* trunk, + float* value, + float* scoreValue, + float* ownership +) { + const int N = ctx.batchSize; + const int W = ctx.nnXLen; + const int H = ctx.nnYLen; + const size_t BXY = (size_t)N * W * H; + const int v1C = desc.v1Conv.outChannels; + const int v2C = desc.v2Mul.outChannels; + + size_t mark = ctx.arena->mark(); + float* v1Out = ctx.arena->alloc(BXY * v1C); + float* v1Out2 = ctx.arena->alloc(BXY * v1C); + float* v1Mean = ctx.arena->alloc((size_t)N * 3 * v1C); + float* v2Out = ctx.arena->alloc((size_t)N * v2C); + + convNHWCMaybeNpu(ctx, v1Out, trunk, desc.v1Conv, N, W, H, false); + batchNormActNHWC(v1Out2, v1Out, desc.v1BN, desc.v1Activation.activation, ctx.mask, N, W, H); + poolRowsValueHeadNHWC(v1Mean, v1Out2, ctx.maskSum, v1C, N, W, H); + matmulRows(v2Out, v1Mean, desc.v2Mul, N); + matBiasAddRows(v2Out, desc.v2Bias, N); + applyActivationInplace(v2Out, (size_t)N * v2C, desc.v2Activation.activation); + matmulRows(value, v2Out, desc.v3Mul, N); + matBiasAddRows(value, desc.v3Bias, N); + matmulRows(scoreValue, v2Out, desc.sv3Mul, N); + matBiasAddRows(scoreValue, desc.sv3Bias, N); + // Raw conv output; intentionally NOT masked or tanh'd (as eigenbackend). + convNHWCMaybeNpu(ctx, ownership, v1Out2, desc.vOwnershipConv, N, W, H, false); + + ctx.arena->rewind(mark); +} + +// --------------------------------------------------------------------------- +// Worst-case arena sizing (in floats), mirroring exactly the buffers each +// code path above holds simultaneously. batchXY = maxBatchSize*nnXLen*nnYLen. +// --------------------------------------------------------------------------- +size_t arenaEltsForBlockStack( + const std::vector>& blocks, + size_t batchXY, + size_t batch, + size_t seqLen +); + +size_t arenaEltsForBlock( + int kind, + const void* descPtr, + size_t batchXY, + size_t batch, + size_t seqLen +) { + switch(kind) { + case ORDINARY_BLOCK_KIND: { + const ResidualBlockDesc* d = (const ResidualBlockDesc*)descPtr; + return 2 * (size_t)d->regularConv.outChannels * batchXY; + } + case GLOBAL_POOLING_BLOCK_KIND: { + const GlobalPoolingResidualBlockDesc* d = (const GlobalPoolingResidualBlockDesc*)descPtr; + size_t regC = (size_t)d->regularConv.outChannels; + size_t gpoolC = (size_t)d->gpoolConv.outChannels; + return (2 * regC + 2 * gpoolC) * batchXY + (3 * gpoolC + regC) * batch; + } + case NESTED_BOTTLENECK_BLOCK_KIND: { + const NestedBottleneckResidualBlockDesc* d = (const NestedBottleneckResidualBlockDesc*)descPtr; + // Outer midIn/midScratch stay live while the inner stack runs. + return 2 * (size_t)d->preConv.outChannels * batchXY + + arenaEltsForBlockStack(d->blocks, batchXY, batch, seqLen); + } + case TRANSFORMER_ATTENTION_BLOCK_KIND: { + const TransformerAttentionDesc* d = (const TransformerAttentionDesc*)descPtr; + size_t qTot = (size_t)d->numHeads * d->qHeadDim; + size_t kTot = (size_t)d->numKVHeads * d->qHeadDim; + size_t vTot = (size_t)d->numKVHeads * d->vHeadDim; + size_t oTot = (size_t)d->numHeads * d->vHeadDim; + return (qTot + kTot + vTot + oTot) * batchXY + seqLen * seqLen; + } + case TRANSFORMER_FFN_BLOCK_KIND: { + const TransformerFFNDesc* d = (const TransformerFFNDesc*)descPtr; + return 2 * (size_t)d->ffnChannels * batchXY; + } + default: + throw StringError("RyzenAIRef: unknown block kind " + std::to_string(kind)); + } +} + +size_t arenaEltsForBlockStack( + const std::vector>& blocks, + size_t batchXY, + size_t batch, + size_t seqLen +) { + size_t maxElts = 0; + for(size_t i = 0; i < blocks.size(); i++) + maxElts = std::max(maxElts, arenaEltsForBlock(blocks[i].first, blocks[i].second.get(), batchXY, batch, seqLen)); + return maxElts; +} + +// --------------------------------------------------------------------------- +// Model validation + RoPE table precomputation (recurses into nested +// bottleneck blocks). Throws on unsupported features. +// --------------------------------------------------------------------------- +void validateAndCollectBlocks( + const std::vector>& blocks, + int nnXLen, + int nnYLen, + std::map& ropeTables +) { + for(size_t i = 0; i < blocks.size(); i++) { + int kind = blocks[i].first; + const void* ptr = blocks[i].second.get(); + if(kind == ORDINARY_BLOCK_KIND || kind == GLOBAL_POOLING_BLOCK_KIND) { + // nothing special + } + else if(kind == NESTED_BOTTLENECK_BLOCK_KIND) { + const NestedBottleneckResidualBlockDesc* d = (const NestedBottleneckResidualBlockDesc*)ptr; + validateAndCollectBlocks(d->blocks, nnXLen, nnYLen, ropeTables); + } + else if(kind == TRANSFORMER_ATTENTION_BLOCK_KIND) { + const TransformerAttentionDesc* d = (const TransformerAttentionDesc*)ptr; + if(d->useRope) { + RopeTables tables; + // paddedNNXYLen == nnXLen*nnYLen (no extra padding), as eigenbackend. + d->computeRopeCosSin(nnXLen, nnYLen, nnXLen * nnYLen, tables.cosTable, tables.sinTable); + ropeTables[ptr] = std::move(tables); + } + } + else if(kind == TRANSFORMER_FFN_BLOCK_KIND) { + const TransformerFFNDesc* d = (const TransformerFFNDesc*)ptr; + if(!d->useSwiGLU) + throw StringError("RyzenAIRef: non-SwiGLU transformer FFN block '" + d->name + "' is not supported"); + } + else { + throw StringError("RyzenAIRef: unknown block kind " + std::to_string(kind)); + } + } +} + +} // namespace + +// --------------------------------------------------------------------------- +// Workspace +// --------------------------------------------------------------------------- +struct Workspace { + const ModelDesc* model; // not owned; must outlive this Workspace + int maxBatchSize; + int nnXLen; + int nnYLen; + + std::vector mask; // [maxBatchSize][nnYLen*nnXLen] + std::vector maskSum; // [maxBatchSize] + std::vector trunkA; // [maxBatchSize][nnYLen*nnXLen][trunkC] + std::vector trunkB; // same; scratch / heads' input + std::vector arenaStorage; + std::map ropeTables; + RyzenAIMatMul::Accel* accel = nullptr; // not owned +}; + +Workspace* createWorkspace( + const ModelDesc& model, + int maxBatchSize, + int nnXLen, + int nnYLen +) { + if(maxBatchSize < 1) + throw StringError("RyzenAIRef: maxBatchSize must be positive"); + if(nnXLen < 1 || nnYLen < 1) + throw StringError("RyzenAIRef: nnXLen/nnYLen must be positive"); + + std::unique_ptr ws(new Workspace()); + ws->model = &model; + ws->maxBatchSize = maxBatchSize; + ws->nnXLen = nnXLen; + ws->nnYLen = nnYLen; + + const TrunkDesc& trunk = model.trunk; + const size_t S = (size_t)nnXLen * nnYLen; + const size_t B = (size_t)maxBatchSize; + const size_t BXY = B * S; + const size_t trunkC = (size_t)trunk.trunkNumChannels; + + // Validates all blocks (recursively) and precomputes RoPE tables. + validateAndCollectBlocks(trunk.blocks, nnXLen, nnYLen, ws->ropeTables); + + // Arena sizing, mirroring the live buffers of each top-level phase. + // Trunk preamble: initial matmul output (+ SGF metadata encoder internals). + size_t preambleElts = (size_t)trunk.initialMatMul.outChannels * B; + if(trunk.metaEncoderVersion > 0) { + const SGFMetadataEncoderDesc& enc = trunk.sgfMetadataEncoder; + size_t encInternal = (size_t)std::max(enc.mul1.outChannels, enc.mul2.outChannels); + preambleElts += 2 * encInternal * B; + } + size_t trunkElts = std::max(preambleElts, arenaEltsForBlockStack(trunk.blocks, BXY, B, S)); + + const PolicyHeadDesc& ph = model.policyHead; + size_t p1C = (size_t)ph.p1Conv.outChannels; + size_t g1C = (size_t)ph.g1Conv.outChannels; + size_t policyElts = (2 * p1C + 2 * g1C) * BXY + (3 * g1C + 2 * p1C) * B; + + const ValueHeadDesc& vh = model.valueHead; + size_t v1C = (size_t)vh.v1Conv.outChannels; + size_t v2C = (size_t)vh.v2Mul.outChannels; + size_t valueElts = 2 * v1C * BXY + (3 * v1C + v2C) * B; + + size_t arenaElts = std::max(trunkElts, std::max(policyElts, valueElts)); + + ws->mask.resize(B * S); + ws->maskSum.resize(B); + ws->trunkA.resize(BXY * trunkC); + ws->trunkB.resize(BXY * trunkC); + ws->arenaStorage.resize(arenaElts); + return ws.release(); +} + +void setProfileEnabled(bool enabled) { + g_profile = CpuProfile(); + g_profile.enabled = enabled; +} + +std::string profileReport() { + if(!g_profile.enabled) + return "RyzenAI CPU profile: not enabled"; + // attnScores covers only the CPU attention path and includes that path's + // softmax, so subtract -- but only what the CPU path itself contributed, + // which is exactly the softmax bucket when attention ran on the CPU and + // zero when it ran on the NPU (the NPU path's softmax is reported there). + char buf[320]; + std::snprintf( + buf, sizeof(buf), + "RyzenAI CPU profile: attention(CPU) %.2f s, softmax %.2f s, norms %.2f s, " + "rope %.2f s, swiglu %.2f s, residual %.2f s", + g_profile.attnScores, g_profile.softmax, g_profile.norms, + g_profile.rope, g_profile.swiglu, g_profile.residual); + return std::string(buf); +} + +void setMatMulAccel(Workspace* workspace, RyzenAIMatMul::Accel* accel) { + workspace->accel = accel; +} + +void freeWorkspace(Workspace* workspace) { + delete workspace; +} + +void forward( + Workspace* workspace, + int batchSize, + const float* spatialInput, + const float* globalInput, + const float* metaInput, + float* policy, + float* policyPass, + float* value, + float* scoreValue, + float* ownership +) { + if(workspace == nullptr) + throw StringError("RyzenAIRef: forward called with null workspace"); + const ModelDesc& model = *workspace->model; + if(batchSize < 1 || batchSize > workspace->maxBatchSize) + throw StringError("RyzenAIRef: batchSize out of range for workspace"); + if(spatialInput == nullptr || globalInput == nullptr) + throw StringError("RyzenAIRef: spatialInput and globalInput must be non-null"); + const bool hasMeta = model.trunk.metaEncoderVersion > 0; + if(hasMeta && metaInput == nullptr) + throw StringError("RyzenAIRef: model has an SGF metadata encoder but metaInput is null"); + if(!hasMeta && metaInput != nullptr) + throw StringError("RyzenAIRef: model has no SGF metadata encoder but metaInput is non-null"); + if(policy == nullptr || policyPass == nullptr || value == nullptr || scoreValue == nullptr || ownership == nullptr) + throw StringError("RyzenAIRef: output buffers must be non-null"); + + const int N = batchSize; + const int W = workspace->nnXLen; + const int H = workspace->nnYLen; + const int S = W * H; + const int inC = model.numInputChannels; + + // Mask = channel 0 of the spatial input (1.0f on-board, 0.0f padding), + // matching eigenbackend's `*mask = input->chip(0,0)` + computeMaskSum. + float* mask = workspace->mask.data(); + float* maskSum = workspace->maskSum.data(); + for(int n = 0; n < N; n++) { + float s = 0.0f; + for(int xy = 0; xy < S; xy++) { + float mv = spatialInput[((size_t)n * S + xy) * inC]; + mask[(size_t)n * S + xy] = mv; + s += mv; + } + maskSum[n] = s; + } + + Arena arena; + arena.base = workspace->arenaStorage.data(); + arena.capacity = workspace->arenaStorage.size(); + arena.offset = 0; + + ForwardCtx ctx; + ctx.batchSize = N; + ctx.nnXLen = W; + ctx.nnYLen = H; + ctx.mask = mask; + ctx.maskSum = maskSum; + ctx.arena = &arena; + ctx.ropeTables = &workspace->ropeTables; + ctx.accel = workspace->accel; + + float* trunkA = workspace->trunkA.data(); // residual stream + float* trunkB = workspace->trunkB.data(); // trunk scratch / heads' input + + const TrunkDesc& trunk = model.trunk; + + // ---- Trunk preamble: initial conv + global projection (+ SGF metadata) ---- + { + size_t mark = arena.mark(); + const int immC = trunk.initialMatMul.outChannels; + float* immOut = arena.alloc((size_t)N * immC); + convNHWCMaybeNpu(ctx, trunkA, spatialInput, trunk.initialConv, N, W, H, false); + matmulRows(immOut, globalInput, trunk.initialMatMul, N); + addPerBatchChannelBiasNHWC(trunkA, immOut, immC, N, W, H); + if(hasMeta) { + applySGFMetadataEncoder(trunk.sgfMetadataEncoder, ctx, metaInput, immOut); + addPerBatchChannelBiasNHWC(trunkA, immOut, immC, N, W, H); + } + arena.rewind(mark); + } + + // ---- Trunk blocks (residual stream in trunkA, trunkB as block scratch) ---- + applyBlockStack(trunk.blocks, trunk.numBlocks, ctx, trunkA, trunkB); + + // ---- Trunk tip norm + activation: trunkA -> trunkB ---- + if(trunk.trunkNormKind == TRUNK_NORM_KIND_STANDARD) { + batchNormActNHWC(trunkB, trunkA, trunk.trunkTipBN, trunk.trunkTipActivation.activation, mask, N, W, H); + } + else { + trunkTipRMSNormNHWC(trunkB, trunkA, trunk.trunkTipRMSNorm, trunk.trunkTipActivation.activation, mask, N, W, H); + } + + // ---- Heads, reading the normalized trunk output in trunkB ---- + applyPolicyHead(model.policyHead, ctx, trunkB, policyPass, policy); + applyValueHead(model.valueHead, ctx, trunkB, value, scoreValue, ownership); +} + +} // namespace RyzenAIRef diff --git a/cpp/neuralnet/ryzenaireference.h b/cpp/neuralnet/ryzenaireference.h new file mode 100644 index 000000000..5a00a6e8f --- /dev/null +++ b/cpp/neuralnet/ryzenaireference.h @@ -0,0 +1,191 @@ +/* + * Pure C++ (C++17, standard library only) CPU reference implementation of the + * KataGo neural network forward pass, for the RyzenAI (AMD NPU) backend. + * + * Purpose: + * - Numerical ground truth for elementwise A/B checking of the accelerated + * NPU/GPU paths, and a per-operator fallback when an operator is not (yet) + * available on device. + * + * Layout contract: + * - ALL internal activations and ALL input/output buffers below are NHWC: + * spatial tensors are [N][nnYLen][nnXLen][C] row-major (C innermost), so a + * per-batch-element slab is [H*W][C] and can be fed directly to a GEMM as + * the A matrix. This is identical to the runtime layout of + * cpp/neuralnet/eigenbackend.cpp (whose Eigen tensors are (C,W,H,N) + * column-major, i.e. the same memory order). + * + * Semantics: + * - Ported 1:1 from cpp/neuralnet/eigenbackend.cpp: mask handling, global + * pooling normalization, RoPE/attention, SwiGLU FFN, and the exact + * boundary between backend outputs and client post-processing. + * - KataGo convention: ALL outputs are raw logits / pre-activation values. + * No softmax, no tanh, no policy-optimism interpolation and no symmetry + * handling is applied by this code. That post-processing is the caller's + * job, exactly as in eigenbackend.cpp's getOutput() (which reads buffers + * with precisely the layouts documented below). + * + * Supported model structure (all block kinds from desc.h): + * - ORDINARY_BLOCK_KIND (0) plain residual block + * - GLOBAL_POOLING_BLOCK_KIND (2) residual block with global-pooling bias + * - NESTED_BOTTLENECK_BLOCK_KIND (3) bottleneck block containing a nested + * stack of any of the block kinds here + * (recursion supported to any depth) + * - TRANSFORMER_ATTENTION_BLOCK_KIND (4) multi-head attention with GQA, + * optional RoPE (learnable rope_freqs or + * fixed rope_theta), TransformerRMSNorm + * - TRANSFORMER_FFN_BLOCK_KIND (5) SwiGLU FFN (linear1/linearGate/linear2) + * - initial conv + initial matmul (global feature projection) + * - SGF metadata encoder (when ModelDesc::metaEncoderVersion > 0) + * - trunk tip norm+activation, both TRUNK_NORM_KIND_STANDARD (BatchNorm) + * and TRUNK_NORM_KIND_RMSNORM (RMSNormLayerDesc, spatial and non-spatial) + * - policy head (both modelVersion >= 15 and older pass branches) + * - value head (value, scoreValue, ownership) + * + * Threading/reentrancy: + * - No global mutable state. A Workspace may only be used by one thread at a + * time (same rule as a ComputeHandle in the other backends). Different + * threads must use different Workspaces; each Workspace is independently + * reentrant across calls. + * - All scratch memory is allocated once in createWorkspace(); forward() + * performs no heap allocation. + */ + +#ifndef NEURALNET_RYZENAI_REFERENCE_H_ +#define NEURALNET_RYZENAI_REFERENCE_H_ + +#include + +#include "../neuralnet/desc.h" + +namespace RyzenAIMatMul { struct Accel; } + +namespace RyzenAIRef { + + // Opaque handle holding all scratch buffers and precomputed tables + // (e.g. RoPE cos/sin) for one (model, maxBatchSize, nnXLen, nnYLen) + // configuration. + struct Workspace; + + // Allocates all scratch space needed by forward() for the given model and + // geometry. Throws StringError on unsupported model features (currently the + // only unsupported feature is a non-SwiGLU transformer FFN). + // + // The ModelDesc is NOT copied: `model` must remain alive and unmodified + // (in particular, do not call releaseWeights() on it) until freeWorkspace(). + // + // nnXLen/nnYLen are the (possibly padded) board dimensions the net is + // evaluated at; boards smaller than this are handled via the mask channel + // of spatialInput (see forward()). + Workspace* createWorkspace( + const ModelDesc& model, + int maxBatchSize, + int nnXLen, + int nnYLen + ); + + void freeWorkspace(Workspace* workspace); + + // Attaches an NPU accelerator for the trunk's dense layers (attention + // projections and FFN linears -- the layers whose row count is the whole + // board, which is where nearly all the arithmetic is). Not owned; it must + // outlive the workspace. nullptr, the default, keeps everything on the CPU. + // + // Anything the accelerator declines runs on the CPU path, so attaching one + // never changes which models work, only how fast they are. + void setMatMulAccel(Workspace* workspace, RyzenAIMatMul::Accel* accel); + + // Coarse timing of the work still done on the CPU, for deciding what to move + // onto the NPU next. Enabling it costs a clock read per region, which is + // negligible next to the regions themselves. Not thread-safe: the counters + // are process-wide, so enable it only on single-threaded runs. + void setProfileEnabled(bool enabled); + std::string profileReport(); + + // Runs one batched forward pass. batchSize must satisfy + // 1 <= batchSize <= workspace's maxBatchSize. + // + // ============================ INPUT BUFFERS ============================ + // + // spatialInput: + // [batchSize][nnYLen][nnXLen][ModelDesc::numInputChannels] row-major. + // Element (n,y,x,c) at spatialInput[((n*nnYLen + y)*nnXLen + x)*C + c]. + // Channel 0 MUST be the on-board mask: exactly 1.0f at positions inside + // the actual board and 0.0f at padding positions (when the board is + // smaller than nnXLen x nnYLen). All global-pooling denominators and all + // masked reductions are computed from this channel, matching + // eigenbackend.cpp (`*mask = input->chip(0,0)`). + // + // globalInput: + // [batchSize][ModelDesc::numInputGlobalChannels] row-major. + // Element (n,c) at globalInput[n*Cg + c]. + // + // metaInput: + // [batchSize][ModelDesc::numInputMetaChannels] row-major. + // Must be non-null iff the model has an SGF metadata encoder + // (ModelDesc::metaEncoderVersion > 0); pass nullptr otherwise. + // + // ============================ OUTPUT BUFFERS =========================== + // All are written fully (for all batchSize rows) by forward(). + // All values are raw network outputs (logits / pre-activation); no final + // softmax/tanh is applied anywhere. Below, PC = ModelDesc::numPolicyChannels, + // VC = ModelDesc::numValueChannels, SVC = ModelDesc::numScoreValueChannels, + // OC = ModelDesc::numOwnershipChannels. + // + // policy: + // [batchSize][nnYLen][nnXLen][PC] row-major (NHWC). + // Element (n,y,x,c) at policy[((n*nnYLen + y)*nnXLen + x)*PC + c]. + // Raw output of the policy head's final conv (p2Conv). Per KataGo + // convention this buffer is NOT masked after the final conv (padded + // positions contain whatever the conv produces; the caller must ignore + // or legalize them, as eigenbackend's getOutput does via the client). + // Channel meaning: + // c=0: policy logit for playing at (y,x). + // c=1: (only if PC == 2 or PC == 4) optimistic-policy logit. + // c=2,3: (only if PC == 4, modelVersion >= 16) auxiliary q-value + // prediction channels. + // The optimism interpolation between channels 0/1 is NOT done here; it is + // part of getOutput()-side post-processing. + // + // policyPass: + // [batchSize][PC] row-major. Element (n,c) at policyPass[n*PC + c]. + // Raw pass-move logits, same channel semantics as `policy`. + // + // value: + // [batchSize][VC] row-major (VC == 3). Element (n,c) at value[n*VC + c]. + // c=0: win logit, c=1: loss logit, c=2: no-result logit, from the + // perspective of the player to move. No softmax applied. + // + // scoreValue: + // [batchSize][SVC] row-major. Element (n,c) at scoreValue[n*SVC + c]. + // Raw linear outputs (no activation). Channel order: + // modelVersion >= 9 (SVC == 6): [scoreMean, scoreMeanSq, lead, + // varTimeLeft, shorttermWinlossError, shorttermScoreError] + // modelVersion == 8 (SVC == 4): first 4 of the above + // 4 <= modelVersion <= 7 (SVC == 2): first 2 of the above + // modelVersion == 3 (SVC == 1): scoreMean only + // + // ownership: + // [batchSize][nnYLen][nnXLen][OC] row-major (OC == 1). + // Element (n,y,x,c) at ownership[((n*nnYLen + y)*nnXLen + x)*OC + c]. + // Raw output of vOwnershipConv: pre-tanh ownership prediction from the + // perspective of the player to move. NOT masked (raw conv output). + // + // The caller-provided output buffers may not alias each other or the input + // buffers. + void forward( + Workspace* workspace, + int batchSize, + const float* spatialInput, + const float* globalInput, + const float* metaInput, + float* policy, + float* policyPass, + float* value, + float* scoreValue, + float* ownership + ); + +} // namespace RyzenAIRef + +#endif // NEURALNET_RYZENAI_REFERENCE_H_ diff --git a/cpp/neuralnet/ryzenaisequence.cpp b/cpp/neuralnet/ryzenaisequence.cpp new file mode 100644 index 000000000..3cef9dc04 --- /dev/null +++ b/cpp/neuralnet/ryzenaisequence.cpp @@ -0,0 +1,329 @@ +// sequence.cpp -- see sequence.h for the module overview. +// +// A stream is a run of independent M-chunks of chunkRows = tileM * 4 * 2 rows +// (4 AIE rows, doubled for ping-pong). Within a chunk each buffer descriptor is +// emitted as +// +// BLOCKWRITE + DDR_PATCH [+ ISSUE_TOKEN] + QUEUE_PUSH +// +// and after the chunks come the WAIT_TCTs. Two things vary between chunks and +// nothing else: the DDR offsets, and which of two buffer-descriptor sets is +// used (chunk 1 double-buffers against chunk 0; chunk 2 onward reuse set A, +// having waited). +// +// The one thing not derivable from (M, K, N, tiles, cols) is which physical +// shim column each descriptor lands on and in what order -- that is IRON's +// placer output. It depends only on the column count, so it is tabulated in +// sequence_layout.h (generated by python/ryzenai_kernels/extract_layout.py) and everything +// numeric is computed here. +// +// Field formulas, with cr = chunkRows and nA = number of A descriptors: +// C: len = cr*N/2/cols, D0=(tileN,1), D1=(cr/2,N), D2.stride=tileN*cols, +// iter=(2, cr*N/2), bufoff = chunk*cr*N*4 + slot*tileN*4 +// A: len = cr*K/2/nA, D0=(tileM,1), D1=(cr/nA,K/2), D2.stride=tileM, +// iter=(1,1), bufoff = chunk*cr*K*2 + slot*cr*K/cols +// B: len = K*tileN/2, D0=(tileN/2,1), D1=(tileK,N/2), D2.stride=tileK*N/2, +// iter=(N/tileN/cols, tileN/2*cols), bufoff = slot*tileN*2 (no chunk term: +// the same B panel feeds every chunk) +// QUEUE_PUSH.repeat = N/(tileN*cols) - 1 on MM2S; S2MM uses 1 with a token +// +// Two bugs were found here by widening the golden set, both of the same shape: +// a formula that aliased with the right answer at the single point where it had +// been checked. B's D1.stride was written K/2 and only a non-square golden +// showed it must be N/2; C's and A's fields were written as functions of M and +// only a golden with M != 2*chunkRows showed they are chunk constants. Any new +// field formula must be checked against goldens that vary that dimension. + +#include "../neuralnet/ryzenaisequence.h" + +#include "../neuralnet/ryzenaisequence_layout.h" + +#include +#include + +namespace RyzenAISequence { + +namespace { + +// Command opcodes (see INSTS_FORMAT.md / FastFlowLM op_headers). +constexpr uint32_t OP_WRITE32 = 0x00; +constexpr uint32_t OP_BLOCKWRITE = 0x01; +constexpr uint32_t OP_MASKWRITE = 0x03; +constexpr uint32_t OP_WAIT_TCT = 0x80; +constexpr uint32_t OP_DDR_PATCH = 0x81; + +// Register addresses within a shim tile. The full location word additionally +// carries the column in bits 31:25 and the row (always 0 here) in bits 24:20. +constexpr uint32_t ADDR_BD_BASE = 0x1D000; // descriptor i at +0x20*i +constexpr uint32_t ADDR_BD_PATCH = 0x1D004; // its address word, for patching +constexpr uint32_t ADDR_QUEUE_S2MM_CH0 = 0x1D204; +constexpr uint32_t ADDR_TOKEN_S2MM_CH0 = 0x1D200; + +constexpr uint32_t BD_OPSIZE_BYTES = 12 * 4; +constexpr uint32_t QUEUE_OPSIZE_BYTES = 6 * 4; +constexpr uint32_t TOKEN_OPSIZE_BYTES = 7 * 4; +constexpr uint32_t WAIT_OPSIZE_BYTES = 4 * 4; + +// Every design in the artifact set uses the 4 compute rows of a column, and +// each row's tile is double-buffered, so one pass over the array consumes +// tileM*4*2 rows of A. IRON rejects any M that is not a whole number of these. +constexpr uint32_t AIE_ROWS = 4; + +void check(bool ok, const char* what) { + if(!ok) + throw std::invalid_argument(std::string("RyzenAISequence: invalid shape: ") + what); +} + +uint32_t loc(uint32_t col, uint32_t addr) { + return (col << 25) | addr; // row is 0: these are all shim-tile registers +} + +void pushBlockWrite( + std::vector& out, + uint32_t burstConst, + uint32_t col, + uint32_t bdId, + uint32_t lenBlocks, + uint32_t bufOffBytes, + uint32_t d0Size, + uint32_t d0Stride, + uint32_t d1Size, + uint32_t d1Stride, + uint32_t d2Stride, + uint32_t iterSize, + uint32_t iterStride) { + out.push_back(OP_BLOCKWRITE); + out.push_back(0); + out.push_back(loc(col, ADDR_BD_BASE + 0x20 * bdId)); + out.push_back(BD_OPSIZE_BYTES); + out.push_back(lenBlocks); + out.push_back(bufOffBytes); + out.push_back(0); // packet disabled + out.push_back((d0Size << 20) | (d0Stride - 1)); + out.push_back(burstConst | (d1Size << 20) | (d1Stride - 1)); + out.push_back((2u << 24) | (d2Stride - 1)); // AxCache=2; D2's size is implied by len + out.push_back(((iterSize - 1) << 20) | (iterStride - 1)); + // valid_bd=1, lock rel_val=128; everything else zero (as in golden streams). + out.push_back((1u << 25) | (128u << 18)); +} + +void pushDdrPatch( + std::vector& out, uint32_t col, uint32_t bdId, uint32_t argIdx, uint32_t argOffBytes) { + out.push_back(OP_DDR_PATCH); + out.push_back(BD_OPSIZE_BYTES); + out.push_back(0); + out.push_back(0); + out.push_back(0); + out.push_back(0); + out.push_back(loc(col, ADDR_BD_PATCH + 0x20 * bdId)); + out.push_back(0); + out.push_back(argIdx); + out.push_back(0); + out.push_back(argOffBytes); + out.push_back(0); +} + +void pushIssueToken(std::vector& out, uint32_t col, uint32_t channel) { + // MASKWRITE on the S2MM queue: controller packet id 15. + out.push_back(OP_MASKWRITE); + out.push_back(0); + out.push_back(loc(col, ADDR_TOKEN_S2MM_CH0 + (channel ? 0x8 : 0))); + out.push_back(0); + out.push_back(15u << 8); + out.push_back(0x00001F00u); + out.push_back(TOKEN_OPSIZE_BYTES); +} + +void pushQueuePush( + std::vector& out, + uint32_t col, + bool mm2s, + uint32_t channel, + uint32_t bdId, + uint32_t repeat, + bool issueToken) { + const uint32_t addr = ADDR_QUEUE_S2MM_CH0 + (mm2s ? 0x10 : 0) + (channel ? 0x8 : 0); + const uint32_t value = (bdId & 0xF) | ((repeat & 0xFF) << 16) | (issueToken ? (1u << 31) : 0); + out.push_back(OP_WRITE32); + out.push_back(0); + out.push_back(loc(col, addr)); + out.push_back(0); + out.push_back(value); + out.push_back(QUEUE_OPSIZE_BYTES); +} + +void pushWaitTct(std::vector& out, uint32_t col, uint32_t channel) { + out.push_back(OP_WAIT_TCT); + out.push_back(WAIT_OPSIZE_BYTES); + out.push_back(col << 16); // row 0, S2MM + out.push_back((channel << 24) | 0x00010100u); +} + +const Layout* findLayout(int cols) { + for(int i = 0; i < NUM_LAYOUTS; i++) { + if(LAYOUTS[i].cols == cols) + return &LAYOUTS[i]; + } + return nullptr; +} + +} // namespace + +bool supportsColumns(int cols) { + return findLayout(cols) != nullptr; +} + +std::vector generateSequence( + Arch arch, int cols, int M, int K, int N, int tileM, int tileK, int tileN) { + GemmShape shape{M, K, N, tileM, tileK, tileN}; + return generateSequence(arch, cols, shape); +} + +std::vector generateSingleColSequence(Arch arch, const GemmShape& shape) { + return generateSequence(arch, 1, shape); +} + +std::vector generateSingleColSequence( + Arch arch, int M, int K, int N, int tileM, int tileK, int tileN) { + return generateSequence(arch, 1, M, K, N, tileM, tileK, tileN); +} + +std::vector generateSequence(Arch arch, int cols, const GemmShape& s) { + const Layout* layout = findLayout(cols); + if(layout == nullptr) + throw std::invalid_argument( + "RyzenAISequence: no descriptor layout for " + std::to_string(cols) + " column(s)"); + + check(s.M > 0 && s.K > 0 && s.N > 0, "M/K/N must be positive"); + check(s.tileM > 0 && s.tileK > 0 && s.tileN > 0, "tiles must be positive"); + check(s.K % s.tileK == 0, "K % tileK != 0"); + check(s.tileN % 2 == 0, "tileN must be even"); + check(s.N % (s.tileN * cols) == 0, "N % (tileN*cols) != 0"); + check((s.N / (s.tileN * cols) - 1) <= 0xFF, "N/(tileN*cols)-1 overflows QUEUE_PUSH.repeat"); + + const uint32_t M = static_cast(s.M); + const uint32_t K = static_cast(s.K); + const uint32_t N = static_cast(s.N); + const uint32_t tm = static_cast(s.tileM); + const uint32_t tk = static_cast(s.tileK); + const uint32_t tn = static_cast(s.tileN); + const uint32_t nCols = static_cast(cols); + + const uint32_t chunkRows = tm * AIE_ROWS * 2; + check(s.M % (int)chunkRows == 0, + "M must be a multiple of tileM*8 (one pass over the 4 double-buffered AIE rows)"); + const uint32_t chunks = M / chunkRows; + + uint32_t numA = 0; + for(int i = 0; i < layout->numSteps; i++) + numA += (layout->steps[i].role == Role::A) ? 1u : 0u; + + // Per-descriptor transfer sizes, in the 4-word blocks the length field counts. + const uint32_t lenC = chunkRows * N / 2 / nCols; + const uint32_t lenA = chunkRows * K / 2 / numA; + const uint32_t lenB = K * tn / 2; + // Units the DDR offsets step by, matching the slot indices in the layout. + const uint32_t unitC = tn * 4; // one tile of float32 output + const uint32_t unitA = chunkRows * K / nCols; + const uint32_t unitB = tn * 2; // one tile of bfloat16 + const uint32_t stripsPerCol = N / (tn * nCols); + const uint32_t repeatMm2s = stripsPerCol - 1; + + // Normally a C descriptor covers one output tile and is re-issued once per + // half-chunk (queue repeat 1, iter walking the two halves). When a column + // owns exactly one tile there is no strip loop left to run, so IRON folds the + // two halves into the descriptor instead: double the length, walk the halves + // with D2, and issue it once. Both encodings move the same bytes. + const bool foldC = stripsPerCol < 2; + const uint32_t lenCEff = foldC ? (chunkRows * N / nCols) : lenC; + const uint32_t d2C = foldC ? (chunkRows * N / 2) : (tn * nCols); + const uint32_t iterSizeC = foldC ? 1u : 2u; + const uint32_t iterStrideC = foldC ? 1u : (chunkRows * N / 2); + const uint32_t repeatS2mm = foldC ? 0u : 1u; + // A one-iteration loop carries no stride. + const uint32_t iterStrideB = (stripsPerCol == 1) ? 1u : (tn / 2 * nCols); + + std::vector out; + out.reserve(4 + chunks * (layout->numSteps * 31 + nCols * 4)); + + // Header: n_rows=6, gen from arch, minor=1, major=0; mem_tile_rows=1. + // The num_cols byte is the device's physical width, not the design's: npu2 + // streams carry 8 even for a 1-column design. npu1 1-column streams carry 1. + const uint32_t gen = static_cast(arch); + const uint32_t physCols = (arch == Arch::NPU1 && cols == 1) ? 1u : (arch == Arch::NPU1 ? 4u : 8u); + out.push_back((6u << 24) | (gen << 16) | (1u << 8)); + out.push_back((1u << 8) | physCols); + out.push_back(0); // command count, patched at the end + out.push_back(0); // total bytes, patched at the end + + // BLOCKWRITE D1 word burst-size constant differs between generations: + // 0xC0000000 on npu2 (aie2p), 0x80000000 on npu1 (aie2). + const uint32_t burstConst = (arch == Arch::NPU1) ? 0x80000000u : 0xC0000000u; + + uint32_t numCommands = 0; + for(uint32_t chunk = 0; chunk < chunks; ++chunk) { + // Chunk 1 is the only one that needs its own descriptor set: it is issued + // before chunk 0's tokens are collected. From chunk 2 on there is always an + // intervening wait, so set A is free again. + const bool setB = (chunk == 1); + + for(int i = 0; i < layout->numSteps; i++) { + const Step& step = layout->steps[i]; + const uint32_t col = step.col; + const uint32_t bd = setB ? step.bdB : step.bdA; + const uint32_t slot = step.slot; + + uint32_t argIdx, off; + switch(step.role) { + case Role::C: + off = chunk * chunkRows * N * 4 + slot * unitC; + argIdx = 2; + pushBlockWrite( + out, burstConst, col, bd, lenCEff, off, tn, 1, chunkRows / 2, N, d2C, iterSizeC, + iterStrideC); + break; + case Role::A: + off = chunk * chunkRows * K * 2 + slot * unitA; + argIdx = 0; + pushBlockWrite( + out, burstConst, col, bd, lenA, off, tm, 1, chunkRows / numA, K / 2, tm, 1, 1); + break; + default: // Role::B -- the same panel is re-read by every chunk + off = slot * unitB; + argIdx = 1; + pushBlockWrite( + out, burstConst, col, bd, lenB, off, tn / 2, 1, tk, N / 2, tk * N / 2, stripsPerCol, + iterStrideB); + break; + } + pushDdrPatch(out, col, bd, argIdx, off); + numCommands += 2; + + if(step.token) { + pushIssueToken(out, col, step.chan); + numCommands++; + } + pushQueuePush( + out, col, step.mm2s, step.chan, bd, step.mm2s ? repeatMm2s : repeatS2mm, step.token); + numCommands++; + } + + // One token per C descriptor per chunk. Chunk 0's are collected together + // with chunk 1's, which is what lets those two chunks overlap. + const uint32_t pending = (chunk == 0 && chunks > 1) ? 0 : (chunk == 1 ? 2 : 1); + for(uint32_t rep = 0; rep < pending; rep++) { + for(int i = 0; i < layout->numSteps; i++) { + if(layout->steps[i].role != Role::C) + continue; + pushWaitTct(out, layout->steps[i].col, layout->steps[i].chan); + numCommands++; + } + } + } + + out[2] = numCommands; + out[3] = static_cast(out.size() * 4); + return out; +} + +} // namespace RyzenAISequence diff --git a/cpp/neuralnet/ryzenaisequence.h b/cpp/neuralnet/ryzenaisequence.h new file mode 100644 index 000000000..7e4753bff --- /dev/null +++ b/cpp/neuralnet/ryzenaisequence.h @@ -0,0 +1,53 @@ +#ifndef NEURALNET_RYZENAI_SEQUENCE_H_ +#define NEURALNET_RYZENAI_SEQUENCE_H_ + +// Builds the NPU instruction stream (the TXN control code that an .insts.bin +// file holds) for a GEMM, in plain C++ with no toolchain of any kind. This is +// what lets an arbitrary model run without Python: the .xclbin bakes in only K, +// so M and N -- which vary per layer, per board size and per batch -- are +// resolved here at run time instead of needing a precompiled artifact each. +// +// Pure C++17, standard library only. No XRT headers, no IRON, no file I/O: +// callers hand the result straight to an xrt::bo. +// +// Verified by byte-for-byte comparison against IRON-compiled goldens; see +// python/ryzenai_kernels/INSTS_FORMAT.md for the decoded format and the field formulas. + +#include +#include + +namespace RyzenAISequence { + +// Header field: which AIE generation the stream targets. npu1 = Phoenix / +// Hawk Point (aie2), npu2 = Strix / Krackan (aie2p). +enum class Arch { NPU1 = 3, NPU2 = 4 }; + +struct GemmShape { + int M; // rows of A and C + int K; // reduction dim -- must match the .xclbin, which bakes K in + int N; // columns of B and C + int tileM; // MMUL micro-kernel tile, from the artifact manifest + int tileK; + int tileN; +}; + +// True if instruction streams can be generated for this column count. The +// per-column descriptor layout comes from IRON's placer and is tabulated in +// sequence_layout.h, so only the tabulated widths are supported. +bool supportsColumns(int cols); + +// Builds the stream for `cols` AIE columns. Throws std::invalid_argument if the +// shape is not realizable (see the checks at the top of the implementation) or +// if the column count has no layout. +std::vector generateSequence(Arch arch, int cols, const GemmShape& shape); +std::vector generateSequence( + Arch arch, int cols, int M, int K, int N, int tileM, int tileK, int tileN); + +// Convenience wrappers for the single-column case. +std::vector generateSingleColSequence(Arch arch, const GemmShape& shape); +std::vector generateSingleColSequence( + Arch arch, int M, int K, int N, int tileM, int tileK, int tileN); + +} // namespace RyzenAISequence + +#endif // NEURALNET_RYZENAI_SEQUENCE_H_ diff --git a/cpp/neuralnet/ryzenaisequence_layout.h b/cpp/neuralnet/ryzenaisequence_layout.h new file mode 100644 index 000000000..a9b08bb9d --- /dev/null +++ b/cpp/neuralnet/ryzenaisequence_layout.h @@ -0,0 +1,123 @@ +// Generated by python/ryzenai_kernels/extract_layout.py -- do not edit by hand. +// +// IRON's placer decides which shim column each buffer descriptor lands on +// and in what order. That decision depends only on the column count, not on +// M/K/N, so it is captured here once per column count and every numeric field +// is computed from the shape at run time. See python/ryzenai_kernels/INSTS_FORMAT.md. + +#ifndef NEURALNET_RYZENAI_SEQUENCE_LAYOUT_H_ +#define NEURALNET_RYZENAI_SEQUENCE_LAYOUT_H_ + +#include + +namespace RyzenAISequence { + +enum class Role : uint8_t { C = 0, A = 1, B = 2 }; + +struct Step { + uint8_t col; // physical shim column + Role role; // which kernel argument this descriptor feeds + uint8_t slot; // index into that role's DDR partition + uint8_t bdA; // buffer descriptor id on even-numbered chunk sets + uint8_t bdB; // ... and on chunk 1, which double-buffers against set A + uint8_t chan; // DMA channel the queue push targets + bool mm2s; // true = host->array, false = array->host + bool token; // emit an ISSUE_TOKEN before the queue push +}; + +// 1 column(s): 5 descriptors per chunk +static const Step LAYOUT_1COL[] = { + {0, Role::C, 0, 0, 5, 0, false, true }, + {0, Role::A, 0, 1, 6, 0, true , false}, + {0, Role::B, 0, 2, 7, 1, true , false}, + {0, Role::A, 1, 3, 8, 0, true , false}, + {0, Role::B, 0, 4, 9, 1, true , false}, +}; + +// 2 column(s): 10 descriptors per chunk +static const Step LAYOUT_2COL[] = { + {0, Role::C, 0, 0, 6, 0, false, true }, + {0, Role::A, 0, 1, 7, 0, true , false}, + {0, Role::B, 0, 2, 8, 1, true , false}, + {0, Role::A, 2, 3, 9, 0, true , false}, + {0, Role::B, 0, 4, 10, 1, true , false}, + {0, Role::C, 1, 5, 11, 1, false, true }, + {1, Role::A, 1, 0, 4, 0, true , false}, + {1, Role::B, 1, 1, 5, 1, true , false}, + {1, Role::A, 3, 2, 6, 0, true , false}, + {1, Role::B, 1, 3, 7, 1, true , false}, +}; + +// 4 column(s): 20 descriptors per chunk +static const Step LAYOUT_4COL[] = { + {1, Role::C, 0, 0, 6, 0, false, true }, + {0, Role::A, 0, 0, 5, 0, true , false}, + {1, Role::B, 0, 1, 7, 1, true , false}, + {0, Role::A, 4, 1, 6, 0, true , false}, + {1, Role::B, 0, 2, 8, 1, true , false}, + {1, Role::C, 1, 3, 9, 1, false, true }, + {1, Role::A, 1, 4, 10, 0, true , false}, + {0, Role::B, 1, 2, 7, 1, true , false}, + {1, Role::A, 5, 5, 11, 0, true , false}, + {0, Role::B, 1, 3, 8, 1, true , false}, + {0, Role::C, 2, 4, 9, 0, false, true }, + {2, Role::A, 2, 0, 5, 0, true , false}, + {2, Role::B, 2, 1, 6, 1, true , false}, + {2, Role::A, 6, 2, 7, 0, true , false}, + {2, Role::B, 2, 3, 8, 1, true , false}, + {2, Role::C, 3, 4, 9, 0, false, true }, + {3, Role::A, 3, 0, 4, 0, true , false}, + {3, Role::B, 3, 1, 5, 1, true , false}, + {3, Role::A, 7, 2, 6, 0, true , false}, + {3, Role::B, 3, 3, 7, 1, true , false}, +}; + +// 8 column(s): 32 descriptors per chunk +static const Step LAYOUT_8COL[] = { + {3, Role::C, 0, 0, 6, 0, false, true }, + {0, Role::A, 0, 0, 2, 0, true , false}, + {3, Role::B, 0, 1, 7, 0, true , false}, + {0, Role::A, 8, 1, 3, 0, true , false}, + {3, Role::B, 0, 2, 8, 0, true , false}, + {3, Role::C, 1, 3, 9, 1, false, true }, + {2, Role::A, 2, 0, 5, 0, true , false}, + {3, Role::B, 1, 4, 10, 1, true , false}, + {2, Role::A, 10, 1, 6, 0, true , false}, + {3, Role::B, 1, 5, 11, 1, true , false}, + {2, Role::C, 2, 2, 7, 0, false, true }, + {4, Role::A, 4, 0, 6, 0, true , false}, + {2, Role::B, 2, 3, 8, 1, true , false}, + {4, Role::A, 12, 1, 7, 0, true , false}, + {2, Role::B, 2, 4, 9, 1, true , false}, + {4, Role::C, 3, 2, 8, 0, false, true }, + {6, Role::A, 6, 0, 5, 0, true , false}, + {4, Role::B, 3, 3, 9, 1, true , false}, + {6, Role::A, 14, 1, 6, 0, true , false}, + {4, Role::B, 3, 4, 10, 1, true , false}, + {4, Role::C, 4, 5, 11, 1, false, true }, + {5, Role::B, 4, 0, 6, 0, true , false}, + {5, Role::B, 4, 1, 7, 0, true , false}, + {5, Role::C, 5, 2, 8, 0, false, true }, + {5, Role::B, 5, 3, 9, 1, true , false}, + {5, Role::B, 5, 4, 10, 1, true , false}, + {5, Role::C, 6, 5, 11, 1, false, true }, + {6, Role::B, 6, 2, 7, 1, true , false}, + {6, Role::B, 6, 3, 8, 1, true , false}, + {6, Role::C, 7, 4, 9, 0, false, true }, + {1, Role::B, 7, 0, 2, 0, true , false}, + {1, Role::B, 7, 1, 3, 0, true , false}, +}; + +struct Layout { int cols; const Step* steps; int numSteps; }; + +static const Layout LAYOUTS[] = { + {1, LAYOUT_1COL, 5}, + {2, LAYOUT_2COL, 10}, + {4, LAYOUT_4COL, 20}, + {8, LAYOUT_8COL, 32}, +}; +static const int NUM_LAYOUTS = 4; + +} // namespace RyzenAISequence + +#endif // NEURALNET_RYZENAI_SEQUENCE_LAYOUT_H_ diff --git a/cpp/neuralnet/ryzenaishapes.cpp b/cpp/neuralnet/ryzenaishapes.cpp new file mode 100644 index 000000000..0619fb808 --- /dev/null +++ b/cpp/neuralnet/ryzenaishapes.cpp @@ -0,0 +1,308 @@ +#include "../neuralnet/ryzenaishapes.h" + +#include "../neuralnet/desc.h" + +#include +#include +#include +#include + +using std::string; +using std::vector; + +namespace RyzenAIShapes { + +const char* rowKindName(RowKind kind) { + switch(kind) { + case RowKind::Spatial: return "spatial"; + case RowKind::Batch: return "batch"; + case RowKind::AttnScore: return "attn"; + } + return "?"; +} + +namespace { + +string blockLabel(const string& prefix, size_t idx) { + std::ostringstream out; + out << prefix << ".b" << idx; + return out.str(); +} + +void addMatMul(vector& uses, const string& path, const MatMulLayerDesc& d, RowKind rows) { + // A zero-channel matmul means the layer is absent (e.g. linearGate without SwiGLU). + if(d.inChannels <= 0 || d.outChannels <= 0) + return; + GemmUse u; + u.path = path; + u.op = "matmul"; + u.convY = 1; + u.convX = 1; + u.inChannels = d.inChannels; + u.outChannels = d.outChannels; + u.K = d.inChannels; + u.N = d.outChannels; + u.rows = rows; + uses.push_back(u); +} + +void addConv(vector& uses, const string& path, const ConvLayerDesc& d) { + if(d.inChannels <= 0 || d.outChannels <= 0) + return; + GemmUse u; + u.path = path; + std::ostringstream op; + op << "conv" << d.convYSize << "x" << d.convXSize; + u.op = op.str(); + u.convY = d.convYSize; + u.convX = d.convXSize; + u.inChannels = d.inChannels; + u.outChannels = d.outChannels; + // Implicit GEMM: one reduction over every tap of every input channel. + u.K = d.convYSize * d.convXSize * d.inChannels; + u.N = d.outChannels; + u.rows = RowKind::Spatial; + uses.push_back(u); +} + +void addAttnScore(vector& uses, const string& path, const string& op, int K, int N) { + GemmUse u; + u.path = path; + u.op = op; + u.convY = 1; + u.convX = 1; + u.inChannels = K; + u.outChannels = N; + u.K = K; + u.N = N; + u.rows = RowKind::AttnScore; + uses.push_back(u); +} + +void walkBlocks( + vector& uses, + const std::vector>& blocks, + const string& prefix, + int nnXY +) { + for(size_t i = 0; i < blocks.size(); i++) { + const int kind = blocks[i].first; + const void* ptr = blocks[i].second.get(); + const string path = blockLabel(prefix, i); + + if(kind == ORDINARY_BLOCK_KIND) { + const ResidualBlockDesc* d = (const ResidualBlockDesc*)ptr; + addConv(uses, path + ".regularConv", d->regularConv); + addConv(uses, path + ".finalConv", d->finalConv); + } + else if(kind == GLOBAL_POOLING_BLOCK_KIND) { + const GlobalPoolingResidualBlockDesc* d = (const GlobalPoolingResidualBlockDesc*)ptr; + addConv(uses, path + ".regularConv", d->regularConv); + addConv(uses, path + ".gpoolConv", d->gpoolConv); + addMatMul(uses, path + ".gpoolToBiasMul", d->gpoolToBiasMul, RowKind::Batch); + addConv(uses, path + ".finalConv", d->finalConv); + } + else if(kind == NESTED_BOTTLENECK_BLOCK_KIND) { + const NestedBottleneckResidualBlockDesc* d = (const NestedBottleneckResidualBlockDesc*)ptr; + addConv(uses, path + ".preConv", d->preConv); + walkBlocks(uses, d->blocks, path, nnXY); + addConv(uses, path + ".postConv", d->postConv); + } + else if(kind == TRANSFORMER_ATTENTION_BLOCK_KIND) { + const TransformerAttentionDesc* d = (const TransformerAttentionDesc*)ptr; + addMatMul(uses, path + ".attn.qProj", d->qProj, RowKind::Spatial); + addMatMul(uses, path + ".attn.kProj", d->kProj, RowKind::Spatial); + addMatMul(uses, path + ".attn.vProj", d->vProj, RowKind::Spatial); + if(nnXY > 0) { + // Per head: scores = Q[nnXY x qHeadDim] * K^T[qHeadDim x nnXY], + // ctx = P[nnXY x nnXY] * V[nnXY x vHeadDim]. + addAttnScore(uses, path + ".attn.qk", "attn.qk", d->qHeadDim, nnXY); + addAttnScore(uses, path + ".attn.pv", "attn.pv", nnXY, d->vHeadDim); + } + addMatMul(uses, path + ".attn.outProj", d->outProj, RowKind::Spatial); + } + else if(kind == TRANSFORMER_FFN_BLOCK_KIND) { + const TransformerFFNDesc* d = (const TransformerFFNDesc*)ptr; + addMatMul(uses, path + ".ffn.linear1", d->linear1, RowKind::Spatial); + if(d->useSwiGLU) + addMatMul(uses, path + ".ffn.linearGate", d->linearGate, RowKind::Spatial); + addMatMul(uses, path + ".ffn.linear2", d->linear2, RowKind::Spatial); + } + // Unknown kinds are skipped rather than fatal: this is a diagnostic, and the + // real forward path in reference.cpp is what must reject them. + } +} + +int roundUpTo(int v, int q) { + return ((v + q - 1) / q) * q; +} + +// Right/left aligned fixed-width cells, so the tables line up without pulling in +// iostream manipulator state. +string padLeft(const string& s, size_t width) { + return s.size() >= width ? s : string(width - s.size(), ' ') + s; +} +string padLeft(int v, size_t width) { + return padLeft(std::to_string(v), width); +} +string padRight(const string& s, size_t width) { + return s.size() >= width ? s : s + string(width - s.size(), ' '); +} + +} // namespace + +vector enumerate(const ModelDesc& desc, int nnXY) { + vector uses; + + addConv(uses, "trunk.initialConv", desc.trunk.initialConv); + addMatMul(uses, "trunk.initialMatMul", desc.trunk.initialMatMul, RowKind::Batch); + if(desc.metaEncoderVersion != 0) { + const SGFMetadataEncoderDesc& m = desc.trunk.sgfMetadataEncoder; + addMatMul(uses, "trunk.meta.mul1", m.mul1, RowKind::Batch); + addMatMul(uses, "trunk.meta.mul2", m.mul2, RowKind::Batch); + addMatMul(uses, "trunk.meta.mul3", m.mul3, RowKind::Batch); + } + walkBlocks(uses, desc.trunk.blocks, "trunk", nnXY); + + const PolicyHeadDesc& p = desc.policyHead; + addConv(uses, "policy.p1Conv", p.p1Conv); + addConv(uses, "policy.g1Conv", p.g1Conv); + addMatMul(uses, "policy.gpoolToBiasMul", p.gpoolToBiasMul, RowKind::Batch); + addConv(uses, "policy.p2Conv", p.p2Conv); + addMatMul(uses, "policy.gpoolToPassMul", p.gpoolToPassMul, RowKind::Batch); + addMatMul(uses, "policy.gpoolToPassMul2", p.gpoolToPassMul2, RowKind::Batch); + + const ValueHeadDesc& v = desc.valueHead; + addConv(uses, "value.v1Conv", v.v1Conv); + addMatMul(uses, "value.v2Mul", v.v2Mul, RowKind::Batch); + addMatMul(uses, "value.v3Mul", v.v3Mul, RowKind::Batch); + addMatMul(uses, "value.sv3Mul", v.sv3Mul, RowKind::Batch); + addConv(uses, "value.vOwnershipConv", v.vOwnershipConv); + + return uses; +} + +int chooseSingleK(const ModelDesc& desc, int nnXLen, int nnYLen, double maxSpread) { + const vector uses = enumerate(desc, nnXLen * nnYLen); + + // Only the spatial layers matter: the head's batch-row matmuls never reach + // the NPU at all (too few rows to repay a dispatch). And among those, only + // the ones carrying real arithmetic -- a policy head's 48-channel 1x1 would + // otherwise drag the spread out by itself while contributing nothing. + // Weight by arithmetic and aggregate per reduction dim before thresholding: + // a single instance of even the busiest layer is a fraction of a percent, so + // the test has to be on the K as a whole, not on one layer. + std::map weightByK; + double total = 0.0; + for(size_t i = 0; i < uses.size(); i++) { + if(uses[i].rows != RowKind::Spatial) + continue; + const double macs = (double)uses[i].K * uses[i].N; + weightByK[uses[i].K] += macs; + total += macs; + } + if(total <= 0.0) + return 0; + + int minK = 0; + int maxK = 0; + for(std::map::const_iterator it = weightByK.begin(); it != weightByK.end(); ++it) { + if(it->second / total < 0.01) + continue; + if(minK == 0) + minK = it->first; + maxK = it->first; + } + if(minK <= 0 || maxK <= 0) + return 0; + if((double)maxK / (double)minK > maxSpread) + return 0; + return maxK; +} + +string report(const ModelDesc& desc, int nnXLen, int nnYLen) { + const int nnXY = nnXLen * nnYLen; + const vector uses = enumerate(desc, nnXY); + + std::ostringstream out; + out << "RyzenAI shape report for model '" << desc.name << "'" + << " (version " << desc.modelVersion << ", board " << nnXLen << "x" << nnYLen << ")\n"; + out << " trunk: " << desc.trunk.numBlocks << " blocks, " + << desc.trunk.trunkNumChannels << " trunk channels, " + << desc.trunk.midNumChannels << " mid channels\n"; + + // ---- distinct (K,N,rows), with occurrence counts and one example ------------- + struct Agg { + int count = 0; + string example; + string op; + }; + std::map, int>, Agg> distinct; + for(size_t i = 0; i < uses.size(); i++) { + const GemmUse& u = uses[i]; + auto key = std::make_pair(std::make_pair(u.K, u.N), (int)u.rows); + Agg& a = distinct[key]; + a.count++; + if(a.example.empty()) { + a.example = u.path; + a.op = u.op; + } + } + + out << "\n distinct (K,N) shapes: " << distinct.size() + << " (total GEMM sites: " << uses.size() << ")\n"; + out << " K N rows uses op example\n"; + for(auto it = distinct.begin(); it != distinct.end(); ++it) { + const int K = it->first.first.first; + const int N = it->first.first.second; + const RowKind rows = (RowKind)it->first.second; + out << " " << padLeft(K, 8) << padLeft(N, 8) << padLeft(rowKindName(rows), 9) + << padLeft(it->second.count, 7) << " " << padRight(it->second.op, 10) + << " " << it->second.example << "\n"; + } + + // ---- how big M actually gets ------------------------------------------------ + out << "\n M per dispatch (rows are independent, so M is tiled, not baked into artifacts):\n"; + out << " spatial: batch * " << nnXY << "\n"; + out << " batch: batch\n"; + out << " attn: batch * numHeads * " << nnXY << "\n"; + + // ---- what a quantized artifact grid would cost ------------------------------ + // K, N and M can all be zero-padded up without changing the result (pad B's + // rows and A's columns for K, drop the extra output columns for N, drop the + // extra output rows for M), so a coarse grid covers every model at the price + // of wasted multiply-accumulates. + out << "\n artifact grid if (K,N) are rounded up to a quantum:\n"; + out << " " << padLeft("quantum", 9) << padLeft("distinct(K,N)", 16) + << padLeft("padded/useful MACs", 22) << "\n"; + const int quanta[] = {16, 32, 64, 128, 256}; + for(size_t qi = 0; qi < sizeof(quanta) / sizeof(quanta[0]); qi++) { + const int q = quanta[qi]; + std::set> padded; + double useful = 0.0; + double actual = 0.0; + for(size_t i = 0; i < uses.size(); i++) { + const GemmUse& u = uses[i]; + if(u.rows != RowKind::Spatial) + continue; // batch/attn rows are a different dispatch story; count the bulk only + const int Kp = roundUpTo(u.K, q); + const int Np = roundUpTo(u.N, q); + padded.insert(std::make_pair(Kp, Np)); + useful += (double)u.K * u.N; + actual += (double)Kp * Np; + } + string waste = "n/a"; + if(useful > 0.0) { + std::ostringstream w; + w.precision(3); + w << (actual / useful) << "x"; + waste = w.str(); + } + out << " " << padLeft(q, 9) << padLeft((int)padded.size(), 16) << padLeft(waste, 22) << "\n"; + } + out << " (grid counts and waste cover spatial GEMMs only - the bulk of the work)\n"; + + return out.str(); +} + +} // namespace RyzenAIShapes diff --git a/cpp/neuralnet/ryzenaishapes.h b/cpp/neuralnet/ryzenaishapes.h new file mode 100644 index 000000000..7b748f095 --- /dev/null +++ b/cpp/neuralnet/ryzenaishapes.h @@ -0,0 +1,68 @@ +#ifndef NEURALNET_RYZENAI_SHAPES_H_ +#define NEURALNET_RYZENAI_SHAPES_H_ + +// Enumerates every matrix multiply a RyzenAI forward pass would want to run, +// straight out of KataGo's own ModelDesc. This exists because the NPU artifacts +// are shape-specific: an .xclbin bakes K into the AIE core program, so the set +// of shapes a model actually needs decides the set of artifacts that must ship. +// See ../../.claude/skills/ryzenai-npu-backend/SKILL.md section 2.1. +// +// Only the reduction dim K and the output dim N are enumerated. M is not a grid +// dimension: rows of a GEMM are independent, so any M is handled by dispatching +// a fixed-M kernel ceil(M/Mkernel) times over row slices, padding only the tail. +// +// Reads shapes only, never weights, so it is cheap and safe to run at startup. + +#include +#include + +struct ModelDesc; + +namespace RyzenAIShapes { + +// Where a GEMM's row count comes from, which decides how big M gets at runtime. +enum class RowKind { + Spatial, // M = batch * nnXLen * nnYLen (one row per board point) + Batch, // M = batch (one row per position, e.g. gpool -> bias) + AttnScore // M = batch * numHeads * nnXY (attention's own QK^T / PV products) +}; + +struct GemmUse { + std::string path; // "trunk.block07.ffn.linear1" + std::string op; // "matmul" | "conv1x1" | "conv3x3" | "attn.qk" | "attn.pv" + int convY; // 1 for a matmul + int convX; + int inChannels; + int outChannels; + int K; // convY * convX * inChannels -- the implicit-GEMM reduction dim + int N; // outChannels + RowKind rows; +}; + +const char* rowKindName(RowKind kind); + +// Every GEMM in model order, recursing into nested-bottleneck stacks. +// nnXY = nnXLen*nnYLen. Attention's own QK^T / PV products have a board-dependent +// K or N, so they are only emitted when nnXY > 0. +std::vector enumerate(const ModelDesc& desc, int nnXY = 0); + +// Human-readable dump: per-layer table, deduplicated (K,N) set, and how many +// artifacts a quantized grid would need at several quantum choices together +// with the compute wasted on padding. This is the input to the M3.5 grid decision. +std::string report(const ModelDesc& desc, int nnXLen, int nnYLen); + +// Picks a single reduction dim to run every spatial layer at, or 0 to keep +// per-layer choices. +// +// Every distinct K is a separate xclbin and therefore a separate hardware +// context, and alternating contexts measured ~0.46 ms per dispatch -- far more +// than these kernels spend on arithmetic. Collapsing onto one K trades +// zero-padded multiply-accumulates for one context, which wins whenever the +// padding stays modest. It does not win on convolution-heavy models, where the +// largest K (9*inChannels) dwarfs the smallest and the arithmetic is real, so +// the spread is bounded before accepting. +int chooseSingleK(const ModelDesc& desc, int nnXLen, int nnYLen, double maxSpread); + +} // namespace RyzenAIShapes + +#endif // NEURALNET_RYZENAI_SHAPES_H_ diff --git a/cpp/program/setup.cpp b/cpp/program/setup.cpp index 98e400d1f..ce4055bb6 100644 --- a/cpp/program/setup.cpp +++ b/cpp/program/setup.cpp @@ -22,6 +22,7 @@ std::vector Setup::getBackendPrefixes() { prefixes.push_back("opencl"); prefixes.push_back("rocm"); prefixes.push_back("eigen"); + prefixes.push_back("ryzenai"); prefixes.push_back("onnx"); prefixes.push_back("dummybackend"); return prefixes; @@ -93,6 +94,8 @@ vector Setup::initializeNNEvaluators( string backendPrefix = "rocm"; #elif defined(USE_EIGEN_BACKEND) string backendPrefix = "eigen"; + #elif defined(USE_RYZENAI_BACKEND) + string backendPrefix = "ryzenai"; #elif defined(USE_ONNX_BACKEND) string backendPrefix = "onnx"; #else diff --git a/docs/releasepackaging/README.txt b/docs/releasepackaging/README.txt index 28cc5d818..9237191ee 100644 --- a/docs/releasepackaging/README.txt +++ b/docs/releasepackaging/README.txt @@ -1,101 +1,101 @@ -KataGo v1.17.2 -https://github.com/lightvector/KataGo - -For neural nets from the latest run, download from here: -https://katagotraining.org/ -For nets from earlier runs, see: -https://katagoarchive.org/ - -For the human SL net (b18c384nbt-humanv0.bin.gz), it was released with: -https://github.com/lightvector/KataGo/releases/tag/v1.15.0 - -For differences between this version and older versions, see releases page at -https://github.com/lightvector/KataGo/releases/ - -On Linux, depending on versions of your libraries and some issues with the libzip library, there may sometimes be problems -getting the precompiled executables to work. However, on Linux, KataGo is usually relatively straighforward to compile from source. -See: https://github.com/lightvector/KataGo/blob/master/Compiling.md - ------------------------------------------------------ -USAGE: ------------------------------------------------------ -KataGo is just an engine and does not have its own graphical interface. So generally you will want to use KataGo along with a GUI or analysis program. -(https://github.com/lightvector/KataGo#guis) - -FIRST: Run a command like this to make sure KataGo is working, with the neural net file you downloaded. On OpenCL, it will also tune for your GPU. - -./katago benchmark # if you have default_gtp.cfg and default_model.bin.gz -./katago benchmark -model .bin.gz # if you have default_gtp.cfg -./katago benchmark -model .bin.gz -config gtp_custom.cfg # use this .bin.gz neural net and this .cfg file - -It will tell you a good number of threads. Edit your .cfg file and set "numSearchThreads" to that many to get best performance. - -OR: Run this command to have KataGo generate a custom gtp config for you based on answering some questions: - -./katago genconfig -model .bin.gz -output gtp_custom.cfg - -NEXT: A command like this will run KataGo's engine. This is the command to give to your [GUI or analysis program](#guis) so that it can run KataGo. - -./katago gtp # if you have default_gtp.cfg and default_model.bin.gz -./katago gtp -model .bin.gz # if you have default_gtp.cfg -./katago gtp -model .bin.gz -config gtp_custom.cfg # use this .bin.gz neural net and this .cfg file - -You may need to specify different paths when entering KataGo's command for a GUI program, e.g.: - -path/to/katago gtp -model path/to/.bin.gz -path/to/katago gtp -model path/to/.bin.gz -config path/to/gtp_custom.cfg - -KataGo should be able to work with any GUI program that supports GTP, as well as any analysis program that supports Leela Zero's `lz-analyze` command, such as Lizzie (https://github.com/featurecat/lizzie) or Sabaki (https://sabaki.yichuanshen.de/). - ------------------------------------------------------ -HUMAN-STYLE PLAY AND ANALYSIS: ------------------------------------------------------ - -You can also have KataGo imitate human play if you download the human SL model b18c384nbt-humanv0.bin.gz from https://github.com/lightvector/KataGo/releases/tag/v1.15.0, and run a command like the following, providing both a normal model and the human SL model: - -./katago.exe gtp -model .bin.gz -human-model b18c384nbt-humanv0.bin.gz -config gtp_human5k_example.cfg - -The gtp_human5k_example.cfg configures KataGo to imitate 5-kyu-level players. You can change it to imitate other ranks too, as well as to do many more things, including making KataGo play in a human style but still at a strong level or analyze in interesting ways. Read the config file itself for documentation on some of these possibilities! - -And see also this guide to using the human SL model, which is written from the perspective of the JSON-based analysis engine mentioned below, but is also applicable to gtp as well. -https://github.com/lightvector/KataGo/blob/master/docs/Analysis_Engine.md#human-sl-analysis-guide - ------------------------------------------------------ -OTHER THINGS YOU CAN DO: ------------------------------------------------------ - -Run a JSON-based analysis engine (https://github.com/lightvector/KataGo/blob/master/docs/Analysis_Engine.md) that can do efficient batched evaluations for a backend Go service: - -./katago analysis -model .gz -config .cfg - -Run a high-performance match engine that will play a pool of bots against each other sharing the same GPU batches and CPUs with each other: - -./katago match -config .cfg -log-file match.log -sgf-output-dir - -Force OpenCL tuner to re-tune: - -./katago tuner -config .cfg - -Print version: - -./katago version - ------------------------------------------------------ -TUNING FOR PERFORMANCE: ------------------------------------------------------ -You will very likely want to tune some of the parameters in `default_gtp.cfg` for your system for good performance, including the number of threads, fp16 usage, NN cache size, pondering settings, and so on. You can also adjust things like KataGo's resign threshold or utility function. Most of the relevant parameters should be be reasonably well documented directly inline in that config. - -There are other a few notes about usage and performance at : https://github.com/lightvector/KataGo - ------------------------------------------------------ -TROUBLESHOOTING: ------------------------------------------------------ -Some common issues are described here: -https://github.com/lightvector/KataGo#common-causes-of-errors - -Or, feel free to hop into the Computer Go discord chat, which has become a general chatroom for a variety of computer Go hobbyists and users, and which you can often find people willing to help. -https://discord.gg/fhDHgfk - - - - +KataGo v1.17.2 +https://github.com/lightvector/KataGo + +For neural nets from the latest run, download from here: +https://katagotraining.org/ +For nets from earlier runs, see: +https://katagoarchive.org/ + +For the human SL net (b18c384nbt-humanv0.bin.gz), it was released with: +https://github.com/lightvector/KataGo/releases/tag/v1.15.0 + +For differences between this version and older versions, see releases page at +https://github.com/lightvector/KataGo/releases/ + +On Linux, depending on versions of your libraries and some issues with the libzip library, there may sometimes be problems +getting the precompiled executables to work. However, on Linux, KataGo is usually relatively straighforward to compile from source. +See: https://github.com/lightvector/KataGo/blob/master/Compiling.md + +----------------------------------------------------- +USAGE: +----------------------------------------------------- +KataGo is just an engine and does not have its own graphical interface. So generally you will want to use KataGo along with a GUI or analysis program. +(https://github.com/lightvector/KataGo#guis) + +FIRST: Run a command like this to make sure KataGo is working, with the neural net file you downloaded. On OpenCL, it will also tune for your GPU. + +./katago benchmark # if you have default_gtp.cfg and default_model.bin.gz +./katago benchmark -model .bin.gz # if you have default_gtp.cfg +./katago benchmark -model .bin.gz -config gtp_custom.cfg # use this .bin.gz neural net and this .cfg file + +It will tell you a good number of threads. Edit your .cfg file and set "numSearchThreads" to that many to get best performance. + +OR: Run this command to have KataGo generate a custom gtp config for you based on answering some questions: + +./katago genconfig -model .bin.gz -output gtp_custom.cfg + +NEXT: A command like this will run KataGo's engine. This is the command to give to your [GUI or analysis program](#guis) so that it can run KataGo. + +./katago gtp # if you have default_gtp.cfg and default_model.bin.gz +./katago gtp -model .bin.gz # if you have default_gtp.cfg +./katago gtp -model .bin.gz -config gtp_custom.cfg # use this .bin.gz neural net and this .cfg file + +You may need to specify different paths when entering KataGo's command for a GUI program, e.g.: + +path/to/katago gtp -model path/to/.bin.gz +path/to/katago gtp -model path/to/.bin.gz -config path/to/gtp_custom.cfg + +KataGo should be able to work with any GUI program that supports GTP, as well as any analysis program that supports Leela Zero's `lz-analyze` command, such as Lizzie (https://github.com/featurecat/lizzie) or Sabaki (https://sabaki.yichuanshen.de/). + +----------------------------------------------------- +HUMAN-STYLE PLAY AND ANALYSIS: +----------------------------------------------------- + +You can also have KataGo imitate human play if you download the human SL model b18c384nbt-humanv0.bin.gz from https://github.com/lightvector/KataGo/releases/tag/v1.15.0, and run a command like the following, providing both a normal model and the human SL model: + +./katago.exe gtp -model .bin.gz -human-model b18c384nbt-humanv0.bin.gz -config gtp_human5k_example.cfg + +The gtp_human5k_example.cfg configures KataGo to imitate 5-kyu-level players. You can change it to imitate other ranks too, as well as to do many more things, including making KataGo play in a human style but still at a strong level or analyze in interesting ways. Read the config file itself for documentation on some of these possibilities! + +And see also this guide to using the human SL model, which is written from the perspective of the JSON-based analysis engine mentioned below, but is also applicable to gtp as well. +https://github.com/lightvector/KataGo/blob/master/docs/Analysis_Engine.md#human-sl-analysis-guide + +----------------------------------------------------- +OTHER THINGS YOU CAN DO: +----------------------------------------------------- + +Run a JSON-based analysis engine (https://github.com/lightvector/KataGo/blob/master/docs/Analysis_Engine.md) that can do efficient batched evaluations for a backend Go service: + +./katago analysis -model .gz -config .cfg + +Run a high-performance match engine that will play a pool of bots against each other sharing the same GPU batches and CPUs with each other: + +./katago match -config .cfg -log-file match.log -sgf-output-dir + +Force OpenCL tuner to re-tune: + +./katago tuner -config .cfg + +Print version: + +./katago version + +----------------------------------------------------- +TUNING FOR PERFORMANCE: +----------------------------------------------------- +You will very likely want to tune some of the parameters in `default_gtp.cfg` for your system for good performance, including the number of threads, fp16 usage, NN cache size, pondering settings, and so on. You can also adjust things like KataGo's resign threshold or utility function. Most of the relevant parameters should be be reasonably well documented directly inline in that config. + +There are other a few notes about usage and performance at : https://github.com/lightvector/KataGo + +----------------------------------------------------- +TROUBLESHOOTING: +----------------------------------------------------- +Some common issues are described here: +https://github.com/lightvector/KataGo#common-causes-of-errors + +Or, feel free to hop into the Computer Go discord chat, which has become a general chatroom for a variety of computer Go hobbyists and users, and which you can often find people willing to help. +https://discord.gg/fhDHgfk + + + + diff --git a/python/ryzenai_kernels/INSTS_FORMAT.md b/python/ryzenai_kernels/INSTS_FORMAT.md new file mode 100644 index 000000000..b2eda2747 --- /dev/null +++ b/python/ryzenai_kernels/INSTS_FORMAT.md @@ -0,0 +1,255 @@ +# `.insts.bin` 指令流格式 + +IRON/aiecc 产出的 `.insts.bin` 是 NPU 的 **TXN 控制码**:一串 32 位命令,配置 shim DMA 的 buffer descriptor 并把它们压进 DMA 队列。`.xclbin` 提供阵列配置(与 shape 无关),这份指令流则编码了具体的 M/K/N。 + +M3 的目标是在 C++ 里按 (arch, cols, M, K, N, tile) 现场生成同样的字节流,从而摆脱对每-shape 预编译产物的依赖。 + +工具:`parse_insts.py`(遍历 `artifacts/manifest.json` 里的全部 golden 并 dump 成可读命令列表)。 +参考实现:`tmp/FastFlowLM/src/include/npu_utils/npu_instr_utils.hpp`(735 行,MIT,可商用)。 + +## 头部(4 个 uint32) + +| 字 | 位域 | 含义 | +|---|---|---| +| w0 | `[31:24]` n_rows | 6 | +| | `[23:16]` gen | **3 = npu1/aie2,4 = npu2/aie2p** | +| | `[15:8]` minor | 1 | +| | `[7:0]` major | 0 | +| w1 | `[15:8]` mem_tile_rows | 1 | +| | `[7:0]` num_cols | **物理列数**(npu1=4、npu2=8),不是设计实际用的列数 | +| w2 | — | 命令条数 | +| w3 | — | 总字节数(与文件大小一致,可用于自检) | + +移位常量与 FastFlowLM `npu_sequence` 的 `dev_n_row_shift=24 / dev_gen_shift=16 / dev_minor_shift=8 / dev_major_shift=0`、`dev_mem_tile_rows_shift=8 / dev_num_cols_shift=0` 完全一致。 + +## 命令类型 + +| op | 名称 | 作用 | +|---|---|---| +| 0 | WRITE32 | 单字写寄存器 | +| 1 | BLOCKWRITE | **写一个 DMA buffer descriptor**(本格式的主体) | +| 3 | MASKWRITE | 带掩码写 | +| 6 | PREEMPT | 抢占级别 | +| 0x80 | WAIT_TCT | 等待 task completion token | +| 0x81 | DDR_PATCH | **把 BD 的地址字段绑定到某个 kernel 参数槽** | +| — | ISSUE_TOKEN / QUEUE_PUSH | 配置 token、把 BD 压进 DMA 通道队列 | + +## 主体结构 + +高度规整,反复出现同一四元组: + +``` +BLOCKWRITE col row bd addr len bufoff D0=(size,stride) D1=(size,stride) D2=(size,stride) iter cache lock +DDR_PATCH col row bd addr arg_idx arg_off <- arg_idx: 0=A, 1=B, 2=C +[ISSUE_TOKEN col row S2MM/MM2S ch pkt_id mask] +QUEUE_PUSH col row MM2S/S2MM ch bd repeat issue_token +``` + +`arg_idx` 与 XRT 的参数槽对应(见 `../manifest.h`:ARG_A=3、ARG_B=4、ARG_C=5,减 3 即为此处的 0/1/2)。 + +**命令条数只取决于 (arch, cols),与 M/K/N 无关**——npu2_1col 恒为 35 条,npu1_4col 恒为 136 条。换 shape 只改字段值,不改结构。这对生成器是极有利的性质。 + +## 字段与 (M, K, N, tile) 的关系式 + +以 **npu2_1col、M=512、bf16→fp32** 为例,横向对比 K=N∈{384,512,768} 得出(三个 shape 全部吻合): + +| 字段 | 公式 | K=384 | K=512 | K=768 | +|---|---|---|---|---| +| BD0 (C, arg_idx=2) `len` | **M·N/4** | 49152 | 65536 | 98304 | +| BD0 `D1.stride` | **N** | 384 | 512 | 768 | +| BD0 `D0.size` | **tile_n** | 48 | 32 | 32 | +| BD1 (A, arg_idx=0) `len` | **M·K/8** | 24576 | 32768 | 49152 | +| BD1 `D1.stride` | **K/2**(bf16 每字打包 2 个) | 192 | 256 | 384 | +| BD3 `bufoff` | **M·K/4** | 98304 | 131072 | 196608 | +| QUEUE_PUSH `repeat` | **N/tile_n − 1** | 7 | 15 | 23 | + +`len` 的单位不是字节也不是字,而是 4 字的块(C 是 fp32:`M·N·4 字节 = M·N 字 = M·N/4 块`;A 是 bf16:`M·K·2 字节 = M·K/2 字 = M·K/8 块`)。 + +**结论:没有任何字段需要 IRON 的内部布局决策,全部可从 (M, K, N, tile) 推导。** 这是 M3 可行性的关键判据。 + +## 多列与两代架构 + +对 K=N=512 横向对比: + +| 列数 | 命令数 | C 的 BD `len` | 用到的 col | +|---|---|---|---| +| 1 | 35 | 65536 | 0 | +| 4 | 137 | 16384 = 65536/4 | 0, 1 | +| 8 | 225 | 8192 = 65536/8 | 0, 3 | + +**`len` 精确按列数等分**:`len = M·N/4/cols`,即每列负责 N/cols 的输出列块。A 的 BD 同理。 + +### ★ 命令体与架构无关 + +npu1 与 npu2 在**相同 (cols, M, K, N, tile)** 下命令体完全相同: + +- npu1_1col 与 npu2_1col:均 35 条,BD0 `len`=65536、BD1 `len`=32768,逐字段一致 +- npu1_4col 与 npu2_4col:均 137 条,首个 BD `len`=16384,一致 + +**两代架构的差异只在头部 w0 的 `gen` 字段(npu1=3、npu2=4)。** 生成器因此不需要为两代写两套逻辑,只需在头部填不同的 gen。 + +## ✅ 多列已解决(2026-08-13,本节推翻下面「关键障碍」一节) + +下面那节的统计是在**没有 chunk 结构认知**的前提下做的,把整条流按列计数、混进了 chunk 的重复,因而得出「每列命令数不对称、不可推导」的错误结论。重新分解后: + +| 列数 | 每 chunk 描述符数 | 构成 | +|---|---|---| +| 1 | 5 | 1×C + 2×A + 2×B | +| 4 | 20 | 4×C + 8×A + 8×B | +| 8 | 32 | 8×C + 8×A + 16×B | + +**唯一不可推导的东西只有「哪个描述符落在哪个物理 shim 列、按什么顺序」**——这是 placer 的输出。而它: + +- **只取决于列数**,与 M/K/N/tile 全部无关 +- **与架构无关**(npu1 与 npu2 的表逐字段相同) +- **与 dtype 无关**(bf16 与 bfp16 的表相同) + +所以把它按列数各存一张表就够了。`kernels/extract_layout.py` 从 golden 里提取并生成 `../sequence_layout.h`(1col 5 条、4col 20 条、8col 32 条,共 108 行),其余全部由 `(M,K,N,tile,cols)` 现场算出。 + +**每个角色的字段公式**(`cr = chunkRows`、`nA` = 表里 A 描述符个数、`sPerCol = N/(tileN·cols)`): + +``` +C: len=cr*N/2/cols D0=(tileN,1) D1=(cr/2,N) D2.stride=tileN*cols + iter=(2, cr*N/2) bufoff=chunk*cr*N*4 + slot*tileN*4 S2MM repeat=1 +A: len=cr*K/2/nA D0=(tileM,1) D1=(cr/nA,K/2) D2.stride=tileM + iter=(1,1) bufoff=chunk*cr*K*2 + slot*cr*K/cols +B: len=K*tileN/2 D0=(tileN/2,1) D1=(tileK,N/2) D2.stride=tileK*N/2 + iter=(sPerCol, tileN/2*cols) bufoff=slot*tileN*2(不随 chunk 前进) +MM2S repeat = sPerCol - 1 +``` + +**边界情形 `sPerCol == 1`**(每列正好一个输出 tile,如 8col + N=384/tileN=48):没有 strip 循环可跑了,IRON 把 chunk 的两个半程折进描述符本身—— +`C.len` 翻倍为 `cr*N/cols`、`D2.stride` 变成 `cr*N/2`、`iter=(1,1)`、S2MM `repeat=0`;同时 `B.iter` 的 stride 也归 1(一次迭代的循环没有步长)。两种编码搬运的字节数完全相同。 + +**WAIT_TCT 不需要单独的表**:它就是 C 描述符的 `(col, ch)` 按表内顺序、每 chunk 重复一遍,`w3 = (ch<<24) | 0x00010100`。发放节奏:chunk0 后 0 条、chunk1 后 2×cols 条、chunk≥2 后各 cols 条。 + +**BD 号**:chunk0 用集 A、chunk1 用集 B(两者重叠执行),chunk≥2 因为前面必有 wait,一律复用集 A。 + +### 验收 + +| 测试 | 结果 | +|---|---| +| 逐字节 vs golden | **35/35**(1/4/8 列 × npu1/npu2 × bf16/bfp16 × M∈{256,512,768,1024} × K∈{384,512,768} × N∈{256,384,512,768} × tileN∈{32,48}) | +| 硬件对拍(生成流,无 golden 的 shape) | **34/34 PASS**,maxAbsErr ≤ 1.2e-05;M 到 5888、N 到 2048 | + +约束:`N % (tileN*cols) == 0`。例如 N=1152 在 8col 下不合法(1152/256=4.5),生成器会明确拒绝,运行时降到 4col 或 1col 即可。 + +--- + +## ⛔ 关键障碍:多列指令流不可纯推导(**已被上一节推翻,保留作教训**) + +按 (列号, 命令类型) 统计 K=N=512: + +| 列数 | BLOCKWRITE | DDR_PATCH | QUEUE_PUSH | ISSUE_TOKEN | WAIT_TCT | 列号分布 | +|---|---|---|---|---|---|---| +| 1 | 10 | 10 | 10 | 2 | 2 | `{0:34}` | +| 4 | 40 | 40 | 40 | 8 | 8 | `{0:34, 1:44, 2:34, 3:24}` | +| 8 | 64 | 64 | 64 | 16 | 16 | `{0:12, 1:12, 2:34, 3:44, 4:44, 5:44, 6:34}` | + +`ISSUE_TOKEN = WAIT_TCT = 2 × cols`,这条干净。但另外两点不干净: + +1. **8 列的设计只用了 7 个列(0–6)**,不是 8 个;每列命令数完全不对称(12/12/34/44/44/44/34)。4 列同样不对称(34/44/34/24)。 +2. **BLOCKWRITE 每列数量不是常数**:1col=10、4col=10/列、8col=8/列。 + +这种不对称说明指令流**不是「按列重复同一段」**,而是 IRON 的 placer 给每列分配了不同角色(某列做广播源、某列只做搬运等)。要逐字节复现就得复现 placer 的启发式决策——**这就是「掺了 IRON 内部布局决策」的风险在多列上的兑现**。 + +**当时的结论(错误)**: +- 1 列:可纯推导 ✓ +- 多列:不可纯推导 ✗ 列角色分配不是 (M,K,N,tile,cols) 的函数 + +⚠️ **错在哪**:结论的后半句其实是对的——列角色分配确实不是 shape 的函数。错的是从这里跳到「所以多列不可生成」。它**是 cols 的函数**,一张 5/20/32 条的表就能钉死,其余全部可算。 + +**教训:区分「不可推导」和「不是所求参数的函数」。** 一个量只要维度足够低、取值足够少,列表化就等于解决。当时先按列做直方图、看到不对称就收手了,如果先按 chunk 分解再看,结构立刻是清楚的。 + +## ★★ M、N、K 的归属已实测分离(2026-08-13) + +| 维度 | 在 xclbin 里? | 判据 | +|---|---|---| +| **K** | **是** | K=512 的 xclbin 驱动 K=768 的 golden 流 → ERT=4 completed 但 maxAbsErr=56.1(静默错误)。xclbin 字节数只随 K 变:K=512→26056、K=768→28872,改 M 或 N 都不变 | +| **M** | 否 | 同一 xclbin 驱动 M=256 / M=768 的 golden 流 → PASS | +| **N** | 否 | 同一 xclbin 驱动 N=256 / N=768 的 golden 流 → PASS;反向用 K=768 的 xclbin 驱动 N=512 与 N=768 也都 PASS | + +**结论:xclbin 由 (器件, 列数, dtype, tile, K) 参数化。M 和 N 完全由指令流决定。** + +## ★ 指令流的 chunk 结构(M 自由的原因) + +以 `chunkRows = tileM × 4 × 2` 行 M 为一个 **chunk**(4 个 AIE 行,×2 是乒乓双缓冲),每 chunk 恒 **17 条命令 / 161 字**: + +``` +BLOCKWRITE BD(C) + DDR_PATCH(arg=C) + ISSUE_TOKEN + QUEUE_PUSH(S2MM) +2× [ BLOCKWRITE BD(A) + DDR_PATCH(arg=A) + QUEUE_PUSH(MM2S ch0) + BLOCKWRITE BD(B) + DDR_PATCH(arg=B) + QUEUE_PUSH(MM2S ch1) ] +WAIT_TCT ×1(但 golden 是每两个 chunk 攒着一起发两条) +``` + +- chunk 之间**除 DDR 偏移外逐字节相同**:实测 M=768 的 chunk0/chunk1 与 M=512 的完全一致 +- BD 号在偶/奇 chunk 间交替 `5*(c%2) + {0..4}`,所以 M 再大也不超过 shim tile 的 16 个 BD +- 命令总数 = 17 × M/chunkRows;字数 = 4 + 161 × M/chunkRows(实测 M=256/512/768 → 165/326/487 字) +- IRON 要求 `M % chunkRows == 0`(报错原文:`M/m/n_aie_rows must be even`) + +**每 chunk 的字段值(都不含总 M)**: +``` +C BD: len=chunkRows*N/2, D1=(chunkRows/2, N), iter=(2, len), bufoff=chunk*chunkRows*N*4 +A BD: len=chunkRows*K/4, D1=(chunkRows/2, K/2), iter=(1,1), bufoff=(2*chunk+half)*chunkRows*K +B BD: len=K*tileN/2, D1=(tileK, N/2), D2.stride=tileK*N/2, iter=(N/tileN, tileN/2), bufoff=0 +``` + +## ⛔ 被这个结构咬到的第二个 bug + +`sequence.cpp` 最初把 C/A 的字段写成 M 的函数(`lenC = M*N/4`、`D1.size = M/4`)。正确形式是上面的 chunk 常量。当时全部 golden 的 M 都是 512 = 2×chunkRows,两种写法**数值恰好相等**,9 个 golden 全过。 + +连同 B 的 `D1.stride` 被 K=N 掩盖那次,**同一类错误已经发生两次**。 + +⚠️ **规则:任何字段公式,必须用「该维度取至少两个不同值」的 golden 验证。** 单点验证等于没验证。 + +## ✅ 采纳方案(2026-08-13 实测后修订) + +**预编译只按 K 一维铺网格(quantum 64);M、N、列数全部由 `sequence.cpp` 现场生成。** + +K 可以零填充抬高(A 补零列、B 补零行),所以一维 K 网格能覆盖**任意**模型,硬约束 C3 完整达成,不需要任何降级。 + +被否决的:逆向 IRON 的 placer 的**启发式**(工作量大、脆弱、上游一改就崩)。实际做法是不逆向启发式,只把它对每个列数的**输出**列成表——上游若改了 placer,重跑 `extract_layout.py` 即可。 + +## 实现后的订正(`../sequence.cpp` 已按 golden 逐字节对齐,9/9 PASS) + +写生成器时发现上面几处推导有误,**以下为准**: + +1. **w1 的 num_cols 不是物理列数**。npu1_1col 的 w1 = `0x00000101`(num_cols=1),npu2_1col 才是 8。对 1 列生成按 golden 直接填:npu1→1、npu2→8。 +2. **A 的 BD `bufoff` = `M·K/2 × 序号`**(字节:0、M·K/2、M·K、3M·K/2),上表写的 `M·K/4` 漏算了 bf16 的 2 字节宽度。 +3. **「命令体与架构无关」有一个例外**:BLOCKWRITE 的 D1 字里有个 burst 常量,npu1 = `0x80000000`、npu2 = `0xC0000000`(D1 的 size/stride 本身仍然一致)。连同头部 gen,两代共 **2 处**差异。 + +## ✅ K≠N 歧义已用非方阵 golden 判定(2026-08-13) + +最初 9 个 golden 全部是 K=N 方阵,三个字段存在等价歧义。用 `M=512, K=384, N=768` 重新编一个 golden 后全部判定: + +| 字段 | 判定 | 被排除的候选 | +|---|---|---| +| B 的 `D1.stride` | **N/2**(=384) | K/2(=192) | +| B 的 `D2.stride` | **tileK·N/2**(=24576) | tileK·K/2 | +| C/A 的 `D1.size` | **M/4**(=128) | — | + +**这次验证抓到了一个真实 bug**:`sequence.cpp` 当时把 B 的 `D1.stride` 写成了 `K/2`,而 9 个方阵 golden 因为 K=N 全部通过,掩盖了错误。非方阵一测立刻在 4 个 B 的 BD 上暴露(4/326 个字不同)。 + +⚠️ **教训:只用方阵验证是不够的。** KataGo 的 attention 投影里 K≠N 是常态(如 QKV 合并投影 K=384、N=1152),这个 bug 若留到 M4 会让 NPU 静默算出错误的 policy 而不报错。今后新增任何字段公式,**必须同时用方阵和非方阵验证**。 + +## 当前验证状态 + +| 测试集 | 结果 | +|---|---| +| 9 个方阵 golden(bf16/npu1_1col、bf16/npu2_1col、bfp16/npu2_1col × 3 shape) | **9/9 逐字节一致** | +| 非方阵 M=512 K=384 N=768(npu2_1col bf16) | **逐字节一致** | + +测试程序:`C:\Temp\seqtest.cpp`(方阵集)、`C:\Temp\nsqtest.cpp`(非方阵)。非方阵 golden 由 +`gemm_bf16.compile_aot('npu2',1,'bf16',512,384,768,32,64,32,...)` 生成,冷编译 30.7 秒。 + +## 尚未验证的部分 + +- `iter`、`cache`、`lock` 在已对比样本里未变化,是否与 shape 相关未知。 +- 关系式表只用 bf16 推导,bfp16 变体未对比(预期只有 tile 几何不同,因为 BFP16 的微内核是 8×8×8 而非 4×8×8)。 +- 1 列情况下 BLOCKWRITE 恒为 10 条,与 M/K/N 无关——需确认更极端的 shape 是否仍然成立(BD 硬件上限是每 shim tile 16 个)。 + +## 下一步 + +1. 把上面的对比扩展到 4col / 8col 和 npu1,补全关系式 +2. 写 `../sequence.{h,cpp}`(命名空间 `RyzenAISequence`),C++17,只用标准库 +3. 对 `artifacts/` 下全部 24 个 golden 逐字节 `memcmp`——**这是唯一的验收标准** diff --git a/python/ryzenai_kernels/README.md b/python/ryzenai_kernels/README.md new file mode 100644 index 000000000..8293de297 --- /dev/null +++ b/python/ryzenai_kernels/README.md @@ -0,0 +1,105 @@ +# RyzenAI NPU kernel generation + +Offline tooling that compiles the `.xclbin` kernels the RyzenAI backend runs on +the NPU. Nothing here is needed to build or run KataGo: the kernels are +committed under `cpp/external/ryzenai_artifacts`, and `cmake --build` copies +them next to `katago.exe`. You only come here to support a network shape that +has no kernel yet. + +## Do you actually need this? + +Usually not. An `.xclbin` bakes in exactly one thing about the network - the +reduction dimension `K` of a matrix multiply - and the shipped grid covers every +`K` up to 6912 in steps of 64. A network whose `K` is not in the grid still +runs: the loader picks the next size up and the extra columns are zero-filled, +costing some wasted arithmetic and nothing else. Everything else about a shape, +including batch size and output width, is generated at run time by +`cpp/neuralnet/ryzenaisequence.cpp`, which is why an arbitrary `.bin.gz` works +with no Python at all. + +What *does* need new kernels is a network using a fused operator geometry that +has not been compiled yet - a head count, board size, channel width or FFN +width outside the shipped set. Those operators are optional: without a matching +one the layer falls back to a slower path that produces identical numbers. + +To find out, run KataGo with the shape report on: + +``` +katago.exe gtp -model .bin.gz -config -override-config ryzenaiShapeReport=true +``` + +It lists every shape the model asks for. With `ryzenaiVerboseDispatch=true` the +log also names any operator that was wanted but missing, e.g. + +``` +bn+mish NOT on NPU for 192 channels x 384 rows: no 384x192 artifact +``` + +## Setting up + +The toolchain is a git checkout of [mlir-aie](https://github.com/Xilinx/mlir-aie), +not just a set of wheels - the GEMM generators compile against kernel sources in +its `aie_kernels` tree. `setup_env.ps1` clones it and runs the installer that +ships inside it, so the environment always matches that checkout: + +``` +.\setup_env.ps1 -Prefix C:\Envs\mlir-aie # report the plan, download nothing +.\setup_env.ps1 -Prefix C:\Envs\mlir-aie -Execute # clone and install +``` + +`-Prefix` is required and has no default - the tree is several gigabytes, so +where it goes is your decision. Any path works. Without `-Execute` the script +only checks prerequisites (git, Python 3.10+, the MSVC C++ toolchain, XRT) and +prints what it would do; it never installs any of those for you. + +It writes `activate_iron.bat` here when it finishes. + +## Generating + +``` +activate_iron.bat +python make_artifacts.py --list --for-model 512 8 # plan only, build nothing +python make_artifacts.py --for-model 512 8 --ffn-hidden 768 # a transformer +python make_artifacts.py --for-model 768 0 # a convnet +python make_artifacts.py --gemm-grid # the shared K grid (hours) +``` + +The positional arguments are trunk channels, attention heads (`0` for a +convnet), and optionally board points (default 361, i.e. 19x19). + +`--ffn-hidden` is the FFN hidden width, read off the shape report. There is no +formula for it - 384 channels goes with 512, but 512 goes with 768 and 768 with +1152 - so it has to be given. Without it the SwiGLU activation runs unfused, +which costs a few percent. + +Artifacts land in `cpp/external/ryzenai_artifacts` in the layout the loader +expects, already-present ones are skipped, and the aiecc work trees are deleted +on the way out. The run ends with a per-directory count of what it added. + +## What each piece is + +| File | Role | +| --- | --- | +| `make_artifacts.py` | The entry point. Works out which artifacts a model geometry needs and calls the builders below. | +| `setup_env.ps1` | Clones mlir-aie and runs its installer. | +| `build_grid.py` | The shared GEMM grid, one binary per (dtype, arch, columns, K). `--reindex` rebuilds `grid.json` from what is on disk without compiling. | +| `build_swiglu_grid.py` | GEMM variants with the SwiGLU activation folded into the epilogue. | +| `build_attention.py` | Fused attention: QK^T, softmax and P*V on-chip, one dispatch per instance. | +| `build_softmax.py` | Standalone softmax rows. | +| `build_bn_mish.py` | Fused BatchNorm + Mish, for convnets. | +| `gemm_bf16.py`, `gemm_swiglu_bf16.py` | The GEMM designs the two grid drivers compile. | +| `kernels/*.cc` | AIE core sources for the fused operators. The plain GEMM uses mlir-aie's own templates instead. | +| `aiecc_cleanup.py` | Deletes the `.prj` work tree aiecc leaves beside each artifact. | +| `extract_layout.py` | Regenerates `cpp/neuralnet/ryzenaisequence_layout.h` from golden instruction streams. Only needed when changing which column counts are supported. | +| `parse_insts.py`, `INSTS_FORMAT.md` | Decoder and format notes for the DMA instruction streams that `ryzenaisequence.cpp` generates. | + +## Notes + +* Each builder can be run directly if you want one specific artifact; + `--xclbin` and `--insts` say where to put it. `make_artifacts.py` exists so + that you do not have to work out the names and geometry by hand. +* `--keep-work` on the operator builders keeps the aiecc `.prj` tree, which is + worth doing when a compile fails - the logs in there are the only record of + why. +* Compiling one operator takes tens of seconds. The full GEMM grid is hundreds + of binaries and takes hours; it is committed precisely so that nobody has to. diff --git a/python/ryzenai_kernels/aiecc_cleanup.py b/python/ryzenai_kernels/aiecc_cleanup.py new file mode 100644 index 000000000..f3654ef95 --- /dev/null +++ b/python/ryzenai_kernels/aiecc_cleanup.py @@ -0,0 +1,24 @@ +"""Remove the work directory aiecc leaves beside a compiled artifact. + +aiecc writes a .prj tree next to whatever --xclbin points at: MLIR at +several lowering stages, one ELF and one linker script per core, .ll files, a +.pdi. For a 32-core design that is a few thousand files and tens of megabytes, +and none of it is an input to anything afterwards - only the .xclbin and the +.insts.bin are. Left behind under cpp/external/ryzenai_artifacts it also gets +copied next to katago.exe by the build, which is how a deployed tree once ended +up carrying several hundred stray files. + +Keep it when a compile fails: the logs in there are the only record of why. +""" + +import shutil +from pathlib import Path + + +def clean(xclbin_path, keep=False): + """Delete the .prj beside xclbin_path. Returns what it removed, or None.""" + prj = Path(xclbin_path).with_suffix(".prj") + if keep or not prj.is_dir(): + return None + shutil.rmtree(prj, ignore_errors=True) + return prj if not prj.exists() else None diff --git a/python/ryzenai_kernels/build_attention.py b/python/ryzenai_kernels/build_attention.py new file mode 100644 index 000000000..85ca188a3 --- /dev/null +++ b/python/ryzenai_kernels/build_attention.py @@ -0,0 +1,183 @@ +# build_attention.py - AOT-compile the fused single-head-per-core attention op. +# +# One attention block instance in one dispatch: each AIE core owns one head, +# keeps K/V resident (host pre-packs each head's K and V back to back, S -> 384 +# rows zero-padded), streams Q in 8-row blocks, and computes +# QK^T -> softmax -> P*V on-chip (f32 out). This replaces 3 dispatches +# (QK^T GEMM, softmax op, P*V GEMM) plus all the host marshaling between them +# with a single dispatch. +# +# A core tile has only two input DMA channels, so K and V travel as one +# packed buffer per head. +# +# Host ABI (opcode-3, like the GEMM/ops): +# arg3: Q [heads][384 x d] bf16, per-head contiguous, host-pre-tiled +# (mmul A-tile order per 8x32 chunk, pad rows zero), PRE-SCALED by +# 1/sqrt(d) -- the kernel applies no attention scale +# arg4: KV [heads][2 x 384 x d] bf16, per head: K then V, host-pre-tiled +# (mmul B-tile order), pad rows zero +# arg5: C [heads][384 x dv] f32, per-head contiguous, C-tile order +# (host un-tiles on readback) +# +# (heads == kv_heads for the models this was built for; GQA would need each +# core's KV tap aimed at its group head -- not implemented here.) +# +# No masking support: masked (smaller-than-geometry) boards must fall back to +# the staged path. RoPE is applied by the caller before packing. +# +# Usage (inside the iron env): +# python build_attention.py --heads 6 --s 361 --xclbin out.xclbin --insts out.insts.bin + +import argparse +import aiecc_cleanup +import time +from pathlib import Path + +import aie.iron as iron +import numpy as np +from aie.helpers.taplib import TensorTiler2D +from aie.iron import CompileTime, In, ObjectFifo, Out, Program, Runtime, Worker +from aie.iron.controlflow import range_ +from aie.iron.device import from_name +from aie.iron.kernel import ExternalFunction +from aie.utils import config +from ml_dtypes import bfloat16 + +KERNEL_CC = str(Path(__file__).parent / "kernels" / "attention_head.cc") + +Q_BLOCK = 8 # query rows per tile (L1 budget: KV resident + 8x384 scores) + + +@iron.jit(aiecc_flags=["--alloc-scheme=basic-sequential"]) +def attention( + q_in: In, + kv_in: In, + c_out: Out, + *, + s_pad: CompileTime[int], + heads: CompileTime[int], + d: CompileTime[int], + dv: CompileTime[int], + s_real: CompileTime[int], + heads_per_core: CompileTime[int], +): + n_cores = heads // heads_per_core # one core's heads are processed serially + q_blocks = s_pad // Q_BLOCK + + q_chunk_ty = np.ndarray[(Q_BLOCK, d), np.dtype[bfloat16]] + kv_head_ty = np.ndarray[(2 * s_pad, d), np.dtype[bfloat16]] # K then V + c_chunk_ty = np.ndarray[(Q_BLOCK, dv), np.dtype[np.float32]] + + q_ty = np.ndarray[(heads * s_pad, d), np.dtype[bfloat16]] + kv_ty = np.ndarray[(heads * 2 * s_pad, d), np.dtype[bfloat16]] + c_ty = np.ndarray[(heads * s_pad, dv), np.dtype[np.float32]] + + # Q's fifo elements are 8-row chunks; the runtime splits each head's + # (s_pad, d) strip tap into the 48 chunk transfers automatically. + of_q = [ObjectFifo(q_chunk_ty, name=f"q_{i}", depth=1) for i in range(n_cores)] + of_kv = [ObjectFifo(kv_head_ty, name=f"kv_{i}", depth=1) for i in range(n_cores)] + of_c = [ObjectFifo(c_chunk_ty, name=f"c_{i}", depth=1) for i in range(n_cores)] + + kern = ExternalFunction( + "attn_block_bf16", + source_file=KERNEL_CC, + arg_types=[ + np.ndarray[(Q_BLOCK, d), np.dtype[bfloat16]], + kv_head_ty, + c_chunk_ty, + ], + compile_flags=[f"-DATTN_S_REAL={s_real}"], + include_dirs=[config.cxx_header_path()], + ) + + # One head's K+V is resident at a time (two heads' would not fit in L1); + # with several heads per core they run one after another, the KV buffer + # released and refilled between them. + def core_fn(ofq, ofkv, ofc, k): + for _ in range_(heads_per_core): + ekv = ofkv.acquire(1) + for _ in range_(q_blocks): + eq = ofq.acquire(1) + eo = ofc.acquire(1) + k(eq, ekv, eo) + ofq.release(1) + ofc.release(1) + ofkv.release(1) + + workers = [ + Worker(core_fn, [of_q[i].cons(), of_kv[i].cons(), of_c[i].prod(), kern]) + for i in range(n_cores) + ] + + # Q/KV/C are all per-head contiguous flat taps. Q/K/V are pre-tiled by the + # host into the mmul tile order the stock template reads (see + # attention_head.cc's layout note); C comes back in C-tile order and the + # host un-tiles it. Core i handles heads [i*heads_per_core, +heads_per_core). + q_taps = TensorTiler2D.simple_tiler((heads * s_pad, d), (s_pad, d)) + kv_taps = TensorTiler2D.simple_tiler((heads * 2 * s_pad, d), (2 * s_pad, d)) + c_taps = TensorTiler2D.simple_tiler((heads * s_pad, dv), (s_pad, dv)) + + def sequence(q, kv, c, q_prods, kv_prods, c_conses): + for i in range(n_cores): + for j in range(heads_per_core): + kv_prods[i].fill(kv, kv_taps[i * heads_per_core + j]) + q_prods[i].fill(q, q_taps[i * heads_per_core + j]) + for i in range(n_cores): + for j in range(heads_per_core): + c_conses[i].drain(c, c_taps[i * heads_per_core + j], wait=True) + + rt = Runtime( + sequence, + [ + q_ty, + kv_ty, + c_ty, + [f.prod() for f in of_q], + [f.prod() for f in of_kv], + [f.cons() for f in of_c], + ], + ) + return Program(iron.get_current_device(), rt, workers=workers).resolve_program() + + +def main(): + p = argparse.ArgumentParser(prog="build_attention") + p.add_argument("--heads", type=int, required=True) + p.add_argument("--d", type=int, default=32, help="qHeadDim = vHeadDim") + p.add_argument("--s", type=int, default=361, help="real sequence length (board points)") + p.add_argument("--heads-per-core", type=int, default=1, + help="heads processed serially per core; >1 needed when heads " + "exceed the shim's DMA channel count (e.g. 12 heads -> 2 per core)") + p.add_argument("--xclbin", type=str, required=True) + p.add_argument("--insts", type=str, required=True) + p.add_argument("--keep-work", action="store_true", + help="keep the aiecc .prj work tree (only useful when debugging a compile)") + args = p.parse_args() + + s_pad = ((args.s + 31) // 32) * 32 # softmax vector width multiple + if s_pad % Q_BLOCK != 0: + p.error(f"padded S {s_pad} must be a multiple of Q_BLOCK {Q_BLOCK}") + if args.d != 32: + p.error("prototype hardcodes head dim 32 (score buffer sizing)") + if args.heads % args.heads_per_core != 0: + p.error("heads must be a multiple of heads-per-core") + + iron.set_current_device(from_name("npu2", n_cols=None)) + start = time.perf_counter() + spec = attention.specialize( + s_pad=s_pad, heads=args.heads, d=args.d, dv=args.d, s_real=args.s, + heads_per_core=args.heads_per_core, + ) + spec.compile(xclbin_path=args.xclbin, inst_path=args.insts) + # Only the .xclbin and .insts.bin are inputs to anything after this; the + # rest of what aiecc wrote is scratch. See aiecc_cleanup. + aiecc_cleanup.clean(args.xclbin, keep=args.keep_work) + secs = time.perf_counter() - start + print(f"attention h{args.heads} d{args.d} S{args.s}->{s_pad} " + f"({args.heads_per_core}/core) compiled in {secs:.1f}s") + print(f" -> {args.xclbin}") + print(f" -> {args.insts}") + + +if __name__ == "__main__": + main() diff --git a/python/ryzenai_kernels/build_bn_mish.py b/python/ryzenai_kernels/build_bn_mish.py new file mode 100644 index 000000000..c470aed4f --- /dev/null +++ b/python/ryzenai_kernels/build_bn_mish.py @@ -0,0 +1,144 @@ +# build_bn_mish.py - AOT-compile the fused BatchNorm+Mish row op. +# +# out[r][c] = mish(scale[c] * x[r][c] + bias[c]), bf16 in/out, f32 internal. +# 8 columns x 1 core; rows are split across cores, the scale/bias vectors are +# replicated per core on the host (each core DMAs its own copy once per +# dispatch and holds it for all its rows). +# +# Host ABI (opcode-3): +# arg3: X [rows_pad x width] bf16 (pad rows zero) +# arg4: scale [8 x width] bf16 (replicated per core) +# arg5: bias [8 x width] bf16 (replicated per core) +# arg6: Y [rows_pad x width] bf16 +# +# Usage: +# python build_bn_mish.py --rows 384 --width 768 --xclbin out.xclbin --insts out.insts.bin + +import argparse +import aiecc_cleanup +import time +from pathlib import Path + +import aie.iron as iron +import numpy as np +from aie.helpers.taplib import TensorTiler2D +from aie.iron import CompileTime, In, ObjectFifo, Out, Program, Runtime, Worker +from aie.iron.controlflow import range_ +from aie.iron.device import from_name +from aie.iron.kernel import ExternalFunction +from aie.utils import config +from ml_dtypes import bfloat16 + +KERNEL_CC = str(Path(__file__).parent / "kernels" / "bn_mish.cc") + +N_CORES = 8 +CHUNK_ROWS = 4 # rows per fifo element + + +@iron.jit(aiecc_flags=["--alloc-scheme=basic-sequential"]) +def bn_mish( + x_in: In, + s_in: In, + b_in: In, + y_out: Out, + *, + rows: CompileTime[int], + width: CompileTime[int], + dumpmode: CompileTime[int] = 0, + n_cores: CompileTime[int], + chunk_rows: CompileTime[int], +): + rows_per_core = rows // n_cores + chunk_ty = np.ndarray[(chunk_rows, width), np.dtype[bfloat16]] + row_ty = np.ndarray[(width,), np.dtype[bfloat16]] # one param row + tensor_ty = np.ndarray[(rows, width), np.dtype[bfloat16]] + param_ty = np.ndarray[(n_cores, 2 * width), np.dtype[bfloat16]] + + sb_row_ty = np.ndarray[(2 * width,), np.dtype[bfloat16]] # [scale | bias] + + of_x = [ObjectFifo(chunk_ty, name=f"x_{i}", depth=2) for i in range(n_cores)] + of_sb = [ObjectFifo(sb_row_ty, name=f"sb_{i}", depth=1) for i in range(n_cores)] + of_y = [ObjectFifo(chunk_ty, name=f"y_{i}", depth=2) for i in range(n_cores)] + + kern = ExternalFunction( + "bn_mish_bf16", + source_file=KERNEL_CC, + arg_types=[chunk_ty, sb_row_ty, chunk_ty, np.int32, np.int32], + compile_flags=[f"-DBNM_DUMPMODE={dumpmode}"] + (["-DBNM_NOCLAMP"] if dumpmode == 3 else []), + include_dirs=[config.cxx_header_path()], + ) + + def core_fn(ofx, ofsb, ofy, k): + esb = ofsb.acquire(1) + for _ in range_(rows_per_core // chunk_rows): + ex = ofx.acquire(1) + ey = ofy.acquire(1) + k(ex, esb, ey, chunk_rows, width) + ofx.release(1) + ofy.release(1) + ofsb.release(1) + + workers = [ + Worker(core_fn, [of_x[i].cons(), of_sb[i].cons(), of_y[i].prod(), kern]) + for i in range(n_cores) + ] + + x_taps = TensorTiler2D.simple_tiler((rows, width), (rows_per_core, width)) + y_taps = TensorTiler2D.simple_tiler((rows, width), (rows_per_core, width)) + p_taps = TensorTiler2D.simple_tiler((n_cores, 2 * width), (1, 2 * width)) + + def sequence(x, sb, y, x_p, sb_p, y_c): + for i in range(n_cores): + sb_p[i].fill(sb, p_taps[i]) + for i in range(n_cores): + x_p[i].fill(x, x_taps[i]) + for i in range(n_cores): + y_c[i].drain(y, y_taps[i], wait=True) + + rt = Runtime( + sequence, + [ + tensor_ty, + param_ty, + tensor_ty, + [f.prod() for f in of_x], + [f.prod() for f in of_sb], + [f.cons() for f in of_y], + ], + ) + return Program(iron.get_current_device(), rt, workers=workers).resolve_program() + + +def main(): + p = argparse.ArgumentParser(prog="build_bn_mish") + p.add_argument("--rows", type=int, required=True, help="padded rows (multiple of 32)") + p.add_argument("--width", type=int, required=True, help="channels (multiple of 16)") + p.add_argument("--xclbin", type=str, required=True) + p.add_argument("--insts", type=str, required=True) + p.add_argument("--keep-work", action="store_true", + help="keep the aiecc .prj work tree (only useful when debugging a compile)") + p.add_argument("--dumpmode", type=int, default=0) + args = p.parse_args() + + if args.rows % (N_CORES * CHUNK_ROWS) != 0: + p.error(f"rows {args.rows} must be a multiple of {N_CORES * CHUNK_ROWS}") + if args.width % 16 != 0: + p.error("width must be a multiple of 16") + + iron.set_current_device(from_name("npu2", n_cols=None)) + start = time.perf_counter() + spec = bn_mish.specialize( + rows=args.rows, width=args.width, n_cores=N_CORES, chunk_rows=CHUNK_ROWS, + dumpmode=args.dumpmode, + ) + spec.compile(xclbin_path=args.xclbin, inst_path=args.insts) + # Only the .xclbin and .insts.bin are inputs to anything after this; the + # rest of what aiecc wrote is scratch. See aiecc_cleanup. + aiecc_cleanup.clean(args.xclbin, keep=args.keep_work) + print(f"bn_mish [{args.rows}x{args.width}] compiled in {time.perf_counter()-start:.1f}s") + print(f" -> {args.xclbin}") + print(f" -> {args.insts}") + + +if __name__ == "__main__": + main() diff --git a/python/ryzenai_kernels/build_grid.py b/python/ryzenai_kernels/build_grid.py new file mode 100644 index 000000000..50fa6c209 --- /dev/null +++ b/python/ryzenai_kernels/build_grid.py @@ -0,0 +1,223 @@ +#!/usr/bin/env python3 +"""Compile the artifact grid. + +An .xclbin bakes in the reduction dim K and nothing else -- M and N ride in the +instruction stream, which sequence.cpp generates at run time (see +INSTS_FORMAT.md for the measurements). So the grid is one dimensional: one +binary per (dtype, arch, columns, K), named for the K alone. + +Each entry is compiled at a canonical (M, N); which one is irrelevant to the +resulting binary, it only has to be legal for the design. + +Must be run inside the activated mlir-aie iron environment, with XRT on PATH so +that aiecc can find xclbinutil: + + set PATH=%LOCALAPPDATA%\\..\\mlir_aie\\bin;C:\\Xilinx\\XRT;%PATH% + python build_grid.py --dtype bf16 --arch npu2 + +Run with --list to see what would be built without building it. +""" + +import argparse +import hashlib +import json +import shutil +import sys +import tempfile +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent)) + +ARTIFACTS = Path(__file__).parent.parent.parent / "cpp" / "external" / "ryzenai_artifacts" + +# K values the four shipped models need, from RyzenAIShapes::report. K is a +# multiple of 64 for every one of them except the initial 3x3 convolution +# (9*22 = 198), which pads up into 256. +# +# b10c384h6 192 384 512 +# b10c512h8 256 512 768 +# b11c768h12 384 768 1152 +# b40c768 384 768 2304 3456 (2304 = 9*256, 3456 = 9*384) +# +# Anything not listed still runs: the loader picks the smallest K above it and +# the caller zero-pads. That is what makes an arbitrary model work without a +# toolchain, at the price of some wasted multiply-accumulates. +MODEL_K = [192, 256, 384, 512, 768, 1152, 2304, 3456] + +# A denser sweep for coverage of models we have never seen. 64 is the tile size, +# so it is the finest grid the design can express. +def sweep_k(lo, hi, step=64): + return list(range(lo, hi + 1, step)) + +ARCH_COLS = {"npu1": [1, 2, 4], "npu2": [1, 2, 4, 8]} + +TILE_M, TILE_K, TILE_N = 32, 64, 32 + + +def canonical_shape(cols): + """A legal (M, N) to compile at. The binary does not depend on either.""" + m = TILE_M * 8 # one chunk + n = TILE_N * cols * 2 # two output strips per column + return m, n + + +def sha256(path): + return hashlib.sha256(Path(path).read_bytes()).hexdigest() + + +def scan_artifacts(): + """Every gemm grid xclbin on disk, as index entries. + + Recovers (dtype, arch, cols, K) from the path, which is the only thing the + loader keys on. compiled_at cannot be recovered and is reported as null -- + it is provenance, and the note in the index already says it constrains + nothing. + """ + entries = [] + for xclbin in sorted(ARTIFACTS.glob("*/*col/gemm_bf16_K*.xclbin")): + variant = xclbin.parent.name # "npu2_4col" + arch, _, cols = variant.rpartition("_") + insts = xclbin.with_suffix("").with_suffix(".insts.bin") + entries.append({ + "dtype": xclbin.parent.parent.name, + "arch": arch, + "n_aie_cols": int(cols[:-3]), + "K": int(xclbin.stem.split("_K")[1]), + "compiled_at": None, + "tile": {"m": TILE_M, "k": TILE_K, "n": TILE_N}, + "xclbin": str(xclbin.relative_to(ARTIFACTS)).replace("\\", "/"), + "xclbin_bytes": xclbin.stat().st_size, + "xclbin_sha256": sha256(xclbin), + "insts_golden": str(insts.relative_to(ARTIFACTS)).replace("\\", "/"), + }) + if not insts.exists(): + print("warning: %s has no .insts.bin beside it" % xclbin.name) + return entries + + +def build(dtypes, arches, ks, dry_run): + # Imported here, not at module scope, so that --reindex (which only reads + # the files already on disk) works outside the mlir-aie iron environment. + import gemm_bf16 + + jobs = [] + for dtype in dtypes: + for arch in arches: + if dtype == "bfp16" and arch != "npu2": + continue # BFP16 is an XDNA2-only micro-kernel + for cols in ARCH_COLS[arch]: + for k in ks: + jobs.append((dtype, arch, cols, k)) + + print("%d artifact(s) to build" % len(jobs)) + if dry_run: + for dtype, arch, cols, k in jobs: + print(" %-5s %-4s %dcol K=%d" % (dtype, arch, cols, k)) + return + + entries = [] + total = 0.0 + for i, (dtype, arch, cols, k) in enumerate(jobs): + subdir = ARTIFACTS / dtype / ("%s_%dcol" % (arch, cols)) + subdir.mkdir(parents=True, exist_ok=True) + xclbin = subdir / ("gemm_bf16_K%d.xclbin" % k) + insts = subdir / ("gemm_bf16_K%d.insts.bin" % k) + m, n = canonical_shape(cols) + + if xclbin.exists(): + print("[%3d/%3d] %-5s %-4s %dcol K=%-5d already present" % + (i + 1, len(jobs), dtype, arch, cols, k)) + else: + # aiecc drops a .prj work directory beside its output, so compile + # into a scratch dir and move only the two files worth keeping. + try: + with tempfile.TemporaryDirectory(prefix="ryzenai_grid_") as work: + tmp_x = Path(work) / xclbin.name + tmp_i = Path(work) / insts.name + secs = gemm_bf16.compile_aot( + arch, cols, dtype, m, k, n, TILE_M, TILE_K, TILE_N, str(tmp_x), str(tmp_i)) + shutil.move(str(tmp_x), str(xclbin)) + shutil.move(str(tmp_i), str(insts)) + except Exception as e: + print("[%3d/%3d] %-5s %-4s %dcol K=%-5d FAILED: %s" % + (i + 1, len(jobs), dtype, arch, cols, k, e)) + continue + total += secs + print("[%3d/%3d] %-5s %-4s %dcol K=%-5d %5.1fs %7d B" % + (i + 1, len(jobs), dtype, arch, cols, k, secs, xclbin.stat().st_size)) + + entries.append({ + "dtype": dtype, + "arch": arch, + "n_aie_cols": cols, + "K": k, + "compiled_at": {"M": m, "N": n}, + "tile": {"m": TILE_M, "k": TILE_K, "n": TILE_N}, + "xclbin": str(xclbin.relative_to(ARTIFACTS)).replace("\\", "/"), + "xclbin_bytes": xclbin.stat().st_size, + "xclbin_sha256": sha256(xclbin), + "insts_golden": str(insts.relative_to(ARTIFACTS)).replace("\\", "/"), + }) + + write_index(entries) + print("(%.1f s of compiling)" % total) + + +def write_index(entries, replace=False): + """Update grid.json. + + Merges into whatever is already on disk rather than replacing it: the grid + is normally filled in over several invocations (one per dtype or K range), + and a plain overwrite left grid.json describing only the last batch while + the earlier xclbins sat there unlisted. Pass replace=True (--reindex) to + make the index exactly the set of entries handed in. + """ + grid_path = ARTIFACTS / "grid.json" + key = lambda e: (e["dtype"], e["arch"], e["n_aie_cols"], e["K"]) + merged = {} + if grid_path.exists() and not replace: + try: + for e in json.loads(grid_path.read_text()).get("artifacts", []): + merged[key(e)] = e + except (ValueError, KeyError) as e: + print("warning: ignoring unreadable %s (%s)" % (grid_path, e)) + from_disk = len(merged) + for e in entries: + merged[key(e)] = e # the caller wins on collision + out = [merged[k] for k in sorted(merged)] + + grid_path.write_text(json.dumps({ + "grid_version": 1, + "generated_by": "python/ryzenai_kernels/build_grid.py", + "note": ("An xclbin depends only on (dtype, arch, n_aie_cols, K, tile). " + "M and N are carried by the instruction stream, which " + "sequence.cpp generates at run time, so compiled_at is " + "provenance only and imposes no constraint on dispatch."), + "artifacts": out, + }, indent=1)) + print("wrote %s: %d entries (%d supplied, %d carried over)" + % (grid_path, len(out), len(entries), from_disk)) + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--dtype", action="append", choices=["bf16", "bfp16"]) + ap.add_argument("--arch", action="append", choices=["npu1", "npu2"]) + ap.add_argument("--k", action="append", type=int, help="explicit K (repeatable)") + ap.add_argument("--sweep", nargs=2, type=int, metavar=("LO", "HI"), + help="dense 64-step K sweep instead of the model list") + ap.add_argument("--list", action="store_true") + ap.add_argument("--reindex", action="store_true", + help="rebuild grid.json from the xclbins on disk, compiling nothing") + args = ap.parse_args() + + if args.reindex: + write_index(scan_artifacts(), replace=True) + return + + ks = args.k if args.k else (sweep_k(*args.sweep) if args.sweep else MODEL_K) + build(args.dtype or ["bf16"], args.arch or ["npu2"], sorted(set(ks)), args.list) + + +if __name__ == "__main__": + main() diff --git a/python/ryzenai_kernels/build_softmax.py b/python/ryzenai_kernels/build_softmax.py new file mode 100644 index 000000000..13a7005b4 --- /dev/null +++ b/python/ryzenai_kernels/build_softmax.py @@ -0,0 +1,128 @@ +# build_softmax.py - AOT-compile the row-wise bf16 softmax op for one shape. +# +# The op computes softmax over each row of a [rows x width] bf16 matrix on +# npu2, 8 columns x 1 core. Width must be a multiple of 32; rows must be a +# multiple of n_cores*chunk_rows (64). The host pads: +# - pad columns with -1e30 (exp underflows to 0: no effect on the row sum) +# - pad rows with 0 (uniform softmax output, discarded) +# Masked-out columns (KataGo's board mask) are likewise written as -1e30 by +# the host, so the kernel needs no mask input. +# +# Origin: adapted from the softmax_bench.py left by the kernel prototyping +# session; that script's JIT path is dead on this mlir-aie version +# (iron.tensor(device="npu") is unsupported), only its AOT path is kept here. +# +# Usage (inside the iron env, see ../README or environment.md): +# python build_softmax.py --rows 2176 --width 384 \ +# --xclbin out.xclbin --insts out.insts.bin + +import argparse +import aiecc_cleanup +import time +from pathlib import Path + +import aie.iron as iron +import numpy as np +from aie.helpers.taplib import TensorTiler2D +from aie.iron import CompileTime, In, ObjectFifo, Out, Program, Runtime, Worker +from aie.iron.controlflow import range_ +from aie.iron.device import from_name +from aie.iron.kernel import ExternalFunction +from aie.utils import config +from ml_dtypes import bfloat16 + +KERNEL_CC = str(Path(__file__).parent / "kernels" / "softmax_rows.cc") + +N_CORES = 8 # 8 columns, one core each +CHUNK_ROWS = 8 # rows per fifo element (8*384*2 B = 6 KiB) + + +@iron.jit(aiecc_flags=["--alloc-scheme=basic-sequential"]) +def softmax_rows( + a_in: In, + b_out: Out, + *, + rows: CompileTime[int], + width: CompileTime[int], + chunk_rows: CompileTime[int], + n_cores: CompileTime[int], +): + rows_per_core = rows // n_cores + chunk_ty = np.ndarray[(chunk_rows, width), np.dtype[bfloat16]] + tensor_ty = np.ndarray[(rows, width), np.dtype[bfloat16]] + + of_ins = [ObjectFifo(chunk_ty, name=f"in_{i}", depth=2) for i in range(n_cores)] + of_outs = [ObjectFifo(chunk_ty, name=f"out_{i}", depth=2) for i in range(n_cores)] + + kern = ExternalFunction( + "softmax_rows_bf16", + source_file=KERNEL_CC, + arg_types=[chunk_ty, chunk_ty, np.int32, np.int32], + include_dirs=[config.cxx_header_path()], + ) + + def core_fn(of_in, of_out, k): + for _ in range_(rows_per_core // chunk_rows): + ei = of_in.acquire(1) + eo = of_out.acquire(1) + k(ei, eo, chunk_rows, width) + of_in.release(1) + of_out.release(1) + + workers = [ + Worker(core_fn, [of_ins[i].cons(), of_outs[i].prod(), kern]) + for i in range(n_cores) + ] + + taps = TensorTiler2D.simple_tiler((rows, width), (rows_per_core, width)) + + def sequence(a, b, in_prods, out_conses): + for i in range(n_cores): + in_prods[i].fill(a, taps[i]) + for i in range(n_cores): + out_conses[i].drain(b, taps[i], wait=True) + + rt = Runtime( + sequence, + [ + tensor_ty, + tensor_ty, + [of_ins[i].prod() for i in range(n_cores)], + [of_outs[i].cons() for i in range(n_cores)], + ], + ) + return Program(iron.get_current_device(), rt, workers=workers).resolve_program() + + +def main(): + p = argparse.ArgumentParser(prog="build_softmax") + p.add_argument("--rows", type=int, required=True, help="padded row count (multiple of 64)") + p.add_argument("--width", type=int, required=True, help="padded width (multiple of 32)") + p.add_argument("--xclbin", type=str, required=True) + p.add_argument("--insts", type=str, required=True) + p.add_argument("--keep-work", action="store_true", + help="keep the aiecc .prj work tree (only useful when debugging a compile)") + args = p.parse_args() + + if args.rows % (N_CORES * CHUNK_ROWS) != 0: + p.error(f"rows {args.rows} must be a multiple of {N_CORES * CHUNK_ROWS}") + if args.width % 32 != 0: + p.error(f"width {args.width} must be a multiple of 32") + + iron.set_current_device(from_name("npu2", n_cols=None)) + start = time.perf_counter() + spec = softmax_rows.specialize( + rows=args.rows, width=args.width, chunk_rows=CHUNK_ROWS, n_cores=N_CORES + ) + spec.compile(xclbin_path=args.xclbin, inst_path=args.insts) + # Only the .xclbin and .insts.bin are inputs to anything after this; the + # rest of what aiecc wrote is scratch. See aiecc_cleanup. + aiecc_cleanup.clean(args.xclbin, keep=args.keep_work) + secs = time.perf_counter() - start + print(f"softmax [{args.rows}x{args.width}] npu2 {N_CORES}col compiled in {secs:.1f}s") + print(f" -> {args.xclbin}") + print(f" -> {args.insts}") + + +if __name__ == "__main__": + main() diff --git a/python/ryzenai_kernels/build_swiglu_grid.py b/python/ryzenai_kernels/build_swiglu_grid.py new file mode 100644 index 000000000..c83d1f1f4 --- /dev/null +++ b/python/ryzenai_kernels/build_swiglu_grid.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 +"""Compile the SwiGLU-epilogue GEMM artifacts. + +Companion to build_grid.py: one gemm_swiglu_bf16_K binary per (arch, cols, +K), into bf16/_col_swiglu/. The binary bakes in only K, exactly +like the plain GEMM; M/N ride in the runtime-generated instruction stream. + +Only the Ks the shipped transformer models' FFN blocks actually use (after the +forceK collapse, see RyzenAIShapes::chooseSingleK) get artifacts; any other +model falls back to the plain fused GEMM + CPU SwiGLU, which is always +correct. SwiGLU is a no-op win, never a requirement. + +Must be run inside the activated mlir-aie iron environment with XRT on PATH. +""" + +import argparse +import shutil +import sys +import tempfile +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent)) +import gemm_swiglu_bf16 + +ARTIFACTS = Path(__file__).parent.parent.parent / "cpp" / "external" / "ryzenai_artifacts" + +# forceK-collapsed FFN reduction dims: b10c384h6 -> 512 (inC 192), +# b10c512h8 -> 768 (inC 256), b11c768h12 -> 1152 (inC 384). b40c768 has no FFN. +MODEL_K = [512, 768, 1152] + +TILE_M, TILE_K, TILE_N = 32, 64, 32 + + +def main(): + ap = argparse.ArgumentParser(prog="build_swiglu_grid") + ap.add_argument("--arch", choices=["npu2"], default="npu2") + ap.add_argument("--cols", type=int, nargs="*", default=[1, 2, 4]) + ap.add_argument("--k", type=int, nargs="*", default=MODEL_K) + args = ap.parse_args() + + jobs = [(c, k) for c in sorted(args.cols) for k in sorted(args.k)] + print("%d swiglu artifact(s) to build" % len(jobs)) + total = 0.0 + for i, (cols, k) in enumerate(jobs): + subdir = ARTIFACTS / "bf16" / ("%s_%dcol_swiglu" % (args.arch, cols)) + subdir.mkdir(parents=True, exist_ok=True) + xclbin = subdir / ("gemm_swiglu_bf16_K%d.xclbin" % k) + insts = subdir / ("gemm_swiglu_bf16_K%d.insts.bin" % k) + if xclbin.exists(): + print("[%d/%d] %dcol K=%d already present" % (i + 1, len(jobs), cols, k)) + continue + m = TILE_M * 8 + n = TILE_N * cols * 2 + try: + with tempfile.TemporaryDirectory(prefix="ryzenai_swg_") as work: + tmp_x = Path(work) / xclbin.name + tmp_i = Path(work) / insts.name + secs = gemm_swiglu_bf16.compile_aot( + args.arch, cols, m, k, n, TILE_M, TILE_K, TILE_N, + str(tmp_x), str(tmp_i)) + shutil.move(str(tmp_x), str(xclbin)) + shutil.move(str(tmp_i), str(insts)) + except Exception as e: + print("[%d/%d] %dcol K=%d FAILED: %s" % (i + 1, len(jobs), cols, k, e)) + continue + total += secs + print("[%d/%d] %dcol K=%d %.1fs %d B" % + (i + 1, len(jobs), cols, k, secs, xclbin.stat().st_size)) + print("done (%.1f s of compiling)" % total) + + +if __name__ == "__main__": + main() diff --git a/python/ryzenai_kernels/extract_layout.py b/python/ryzenai_kernels/extract_layout.py new file mode 100644 index 000000000..7f015795d --- /dev/null +++ b/python/ryzenai_kernels/extract_layout.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python3 +"""Extract the per-column-count command layout from golden instruction streams. + +Everything in a stream except one thing is a closed-form function of +(M, K, N, tiles, cols) -- see INSTS_FORMAT.md. The exception is which physical +shim column each buffer descriptor lands on and in what order, which is IRON's +placer output. That layout turns out to depend only on `cols`, so it can be +extracted once and compiled into sequence.cpp as a small table. + +This script decodes chunk 0 of a golden, resolves every DDR offset into an +integer slot index against the shape-derived unit, and emits sequence_layout.h. + +The goldens it reads must have at least two M-chunks (M >= 2*tileM*8), since +that is what exposes the alternating buffer-descriptor sets. The shipped grid is +compiled at one chunk, so compile dedicated ones first: + + gemm_bf16.compile_aot("npu2", cols, "bf16", 512, 512, 64*cols, 32, 64, 32, ...) + +Run only when adding a new column count: + python extract_layout.py --dir > ../sequence_layout.h +""" + +import argparse +import re +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent)) +import parse_insts as P + +ART = Path(__file__).parent.parent.parent / "cpp" / "external" / "ryzenai_artifacts" + +# One golden per column count is enough: the layout was verified identical +# between npu1 and npu2 and between bf16 and bfp16, and every numeric field is +# recomputed from the shape, so only the placer's ordering is captured here. +COLUMN_COUNTS = [1, 2, 4, 8] +GOLDEN_M, GOLDEN_K = 512, 512 +TILE_M, TILE_K, TILE_N = 32, 64, 32 + +AIE_ROWS = 4 + + +def decode_cmds(path): + return P.decode(P.u32s(Path(path).read_bytes()))[1][1:] + + +def chunk_starts(cmds, chunkCBytes): + starts = [] + for i, l in enumerate(cmds): + m = re.search(r"arg_idx=2 arg_off=(\d+)", l) + if m and int(m.group(1)) % chunkCBytes == 0 and int(m.group(1)) // chunkCBytes == len(starts): + starts.append(i - 1) # the BLOCKWRITE precedes its DDR_PATCH + starts.append(len(cmds)) + return starts + + +def field(line, pat, cast=int): + m = re.search(pat, line) + return cast(m.group(1)) if m else None + + +def extract(name, cols, path, M, K, N, tm, tk, tn): + cmds = decode_cmds(path) + chunkRows = tm * AIE_ROWS * 2 + chunkCBytes = chunkRows * N * 4 + starts = chunk_starts(cmds, chunkCBytes) + if len(starts) < 3: + raise SystemExit("%s: need a golden with at least 2 chunks" % name) + + # Units the DDR offsets are multiples of, derived from the shape. + unitC = tn * 4 # C strips advance one tile of float32 + unitA = chunkRows * K * 2 // (2 * cols) # A slices split the chunk's rows + unitB = tn * 4 // 2 # B panels advance one tile of bfloat16 + + steps = [] + i = starts[0] + while i < starts[1]: + line = cmds[i] + assert "BLOCKWRITE" in line, line + col = field(line, r"col=(\d+)") + bdA = field(line, r"bd=(\d+)") + patch = cmds[i + 1] + assert "DDR_PATCH" in patch, patch + arg = field(patch, r"arg_idx=(\d+)") + off = field(patch, r"arg_off=(\d+)") + role = "C" if arg == 2 else ("A" if arg == 0 else "B") + unit = {"C": unitC, "A": unitA, "B": unitB}[role] + assert off % unit == 0, (name, role, off, unit) + j = i + 2 + token = "ISSUE_TOKEN" in cmds[j] + if token: + j += 1 + push = cmds[j] + assert "QUEUE_PUSH" in push, push + chan = field(push, r"ch=(\d+)") + mm2s = "MM2S" in push + steps.append(dict(col=col, role=role, slot=off // unit, bdA=bdA, + chan=chan, mm2s=mm2s, token=token)) + i = j + 1 + + # Second chunk uses a disjoint BD set; chunks 2+ go back to set A. + bdB = [] + i = starts[1] + while i < starts[2] and len(bdB) < len(steps): + if "BLOCKWRITE" in cmds[i]: + bdB.append(field(cmds[i], r"bd=(\d+)")) + i += 1 + assert len(bdB) == len(steps), (name, len(bdB), len(steps)) + for s, b in zip(steps, bdB): + s["bdB"] = b + + waits = [(field(l, r"col=(\d+)"), field(l, r"ch=(\d+)"), "MM2S" in l, field(l, r"w3=0x([0-9a-f]+)", lambda s: int(s, 16))) + for l in cmds if "WAIT_TCT" in l] + return steps, waits + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--dir", required=True, help="directory of npu2_col.insts.bin goldens") + args = ap.parse_args() + global golden_dir + golden_dir = Path(args.dir) + + out = [] + out.append("// Generated by kernels/extract_layout.py -- do not edit by hand.") + out.append("//") + out.append("// IRON's placer decides which shim column each buffer descriptor lands on") + out.append("// and in what order. That decision depends only on the column count, not on") + out.append("// M/K/N, so it is captured here once per column count and every numeric field") + out.append("// is computed from the shape at run time. See kernels/INSTS_FORMAT.md.") + out.append("") + out.append("#ifndef NEURALNET_RYZENAI_SEQUENCE_LAYOUT_H_") + out.append("#define NEURALNET_RYZENAI_SEQUENCE_LAYOUT_H_") + out.append("") + out.append("#include ") + out.append("") + out.append("namespace RyzenAISequence {") + out.append("") + out.append("enum class Role : uint8_t { C = 0, A = 1, B = 2 };") + out.append("") + out.append("struct Step {") + out.append(" uint8_t col; // physical shim column") + out.append(" Role role; // which kernel argument this descriptor feeds") + out.append(" uint8_t slot; // index into that role's DDR partition") + out.append(" uint8_t bdA; // buffer descriptor id on even-numbered chunk sets") + out.append(" uint8_t bdB; // ... and on chunk 1, which double-buffers against set A") + out.append(" uint8_t chan; // DMA channel the queue push targets") + out.append(" bool mm2s; // true = host->array, false = array->host") + out.append(" bool token; // emit an ISSUE_TOKEN before the queue push") + out.append("};") + out.append("") + + names = [] + for cols in COLUMN_COUNTS: + name = "%dCOL" % cols + path = golden_dir / ("npu2_%dcol.insts.bin" % cols) + if not path.exists(): + raise SystemExit("missing golden %s" % path) + steps, waits = extract( + name, cols, path, GOLDEN_M, GOLDEN_K, TILE_N * 2 * cols, TILE_M, TILE_K, TILE_N) + # The WAIT_TCT list is exactly the C descriptors' (col, channel) repeated + # once per chunk, so it needs no table of its own -- assert that here + # rather than emitting redundant data. + cwait = [(s["col"], s["chan"], False) for s in steps if s["role"] == "C"] + for c in range(len(waits) // len(cwait)): + got = [(w[0], w[1], w[2]) for w in waits[c * len(cwait):(c + 1) * len(cwait)]] + assert got == cwait, (name, c, got, cwait) + names.append((name, cols, len(steps))) + out.append("// %d column(s): %d descriptors per chunk" % (cols, len(steps))) + out.append("static const Step LAYOUT_%s[] = {" % name) + for s in steps: + out.append(" {%d, Role::%s, %2d, %2d, %2d, %d, %-5s, %-5s}," + % (s["col"], s["role"], s["slot"], s["bdA"], s["bdB"], s["chan"], + "true" if s["mm2s"] else "false", + "true" if s["token"] else "false")) + out.append("};") + out.append("") + + out.append("struct Layout { int cols; const Step* steps; int numSteps; };") + out.append("") + out.append("static const Layout LAYOUTS[] = {") + for name, cols, n in names: + out.append(" {%d, LAYOUT_%s, %d}," % (cols, name, n)) + out.append("};") + out.append("static const int NUM_LAYOUTS = %d;" % len(names)) + out.append("") + out.append("} // namespace RyzenAISequence") + out.append("") + out.append("#endif // NEURALNET_RYZENAI_SEQUENCE_LAYOUT_H_") + print("\n".join(out)) + + +if __name__ == "__main__": + main() diff --git a/python/ryzenai_kernels/gemm_bf16.py b/python/ryzenai_kernels/gemm_bf16.py new file mode 100644 index 000000000..fd9af81dc --- /dev/null +++ b/python/ryzenai_kernels/gemm_bf16.py @@ -0,0 +1,672 @@ +# gemm_bf16.py +# +# Multi-core (whole-array) bf16 x bf16 -> fp32 GEMM, AOT-compiled for AMD +# Ryzen AI NPUs: XDNA1 / AIE2 / mlir-aie `npu` (Phoenix/Hawk Point, 4 cols) +# and XDNA2 / AIE2P / mlir-aie `npu2` (Strix/Krackan, 8 cols). +# +# Derived from mlir-aie's +# programming_examples/basic/matrix_multiplication/whole_array/whole_array.py +# (see that file for the design's own documentation). KataGo-specific +# changes: +# * dtypes are fixed to bfloat16 inputs / float32 output (bf16 multiply, +# fp32 accumulate) — the host ABI is unchanged from the previous +# single-core design (plain row-major A/B/C host buffers, same XRT +# dispatch), only the on-chip tiling is parameterized; +# * `--dtype bfp16` selects AIE2P's BFP16-emulated bf16 MMUL +# (`emulate_bf16_mmul_with_bfp16`, mac_dims (8,8,8) instead of (4,8,8)); +# ignored on AIE2, where the flag is not supported; +# * the shape/tile geometry is fully parameterized (arch, n_aie_cols, +# M/K/N, m/k/n) so build_kernels.py can emit the whole artifact matrix. +# +# Tile/DMA constraints (enforced by validate_shape, mirroring the template): +# * M % (m * n_aie_rows) == 0 (n_aie_rows = 4) +# * M / (m * n_aie_rows) must be EVEN (transfer-block ping-pong pairing; +# odd counts fail in TensorTiler2D) +# * K % k == 0 +# * N % (n * n_aie_cols) == 0 +# * (m, k, n) % (r, s, t) == 0 (mac_dims of the MMUL kernel: +# (4,8,8) aie2p bf16, (8,8,8) aie2p +# bfp16-emulated, (4,8,4) aie2) +# * core-local memory 64 KiB: depth-2 A/B tiles + depth-2 C tile + stack +# (0xD00) must fit — rules out e.g. m=k=n=64 with fp32 C. +# +# Host ABI for the pure C++ + XRT loader (see artifacts/manifest.json): +# xrt::kernel(hw_context, "MLIR_AIE") +# arg 0 : uint32 opcode = 3 +# arg 1 : xrt::bo instruction buffer, XCL_BO_FLAGS_CACHEABLE, kernel.group_id(1) +# arg 2 : uint32 n_instr (instruction words, insts_bytes / 4) +# arg 3 : A — M*K bfloat16, row-major, contiguous (XRT_BO_FLAGS_HOST_ONLY, group_id(3)) +# arg 4 : B — K*N bfloat16, row-major, contiguous (XRT_BO_FLAGS_HOST_ONLY, group_id(4)) +# arg 5 : C — M*N float32, row-major, contiguous (XRT_BO_FLAGS_HOST_ONLY, group_id(5)) +# +# Usage (inside the activated mlir-aie iron environment): +# python gemm_bf16.py -M 512 -K 512 -N 512 -m 32 -k 64 -n 32 \ +# --arch npu2 --n-aie-cols 8 --dtype bf16 # compile + run + verify +# python gemm_bf16.py ... --xclbin-path out.xclbin --insts-path out.insts.bin +# # AOT compile only + +import argparse +import time + +import aie.iron as iron +import numpy as np +from aie.helpers.taplib import TensorTiler2D +from aie.iron import ( + CompileTime, + In, + ObjectFifo, + Out, + Program, + Runtime, + StreamDims, + TaskGroup, + Worker, + kernels, + str_to_dtype, +) +from aie.iron.controlflow import range_ +from aie.iron.device import NPU2, from_name +from aie.utils.benchmark import run_iters +from ml_dtypes import bfloat16 + +# --------------------------------------------------------------------------- +# Target configuration +# --------------------------------------------------------------------------- + +# arch name -> (iron device name, aiecc arch, human description, max columns) +ARCHES = { + "npu1": ("npu", "aie2", "XDNA1 (Ryzen AI Phoenix/Hawk Point)", 4), + "npu2": ("npu2", "aie2p", "XDNA2 (Ryzen AI Strix/Krackan)", 8), +} + +N_AIE_ROWS = 4 # compute rows on both generations (mem/shim rows not counted) + +# Host ABI dtypes (fixed): bf16 in, fp32 out/accumulate. +INPUT_DTYPE = bfloat16 +OUTPUT_DTYPE = np.float32 +DTYPE_IN_STR = "bf16" +DTYPE_OUT_STR = "f32" + +# Default tile geometry measured on Strix (see artifacts/manifest.json +# "tile_selection" notes written by build_kernels.py). +DEFAULT_TILE = {"m": 32, "k": 64, "n": 32} + + +def _device_for(arch: str, n_aie_cols: int): + """Iron device for (arch, cols). + + On npu1 pick the matching ColN variant (or the full NPU1 when cols == 4). + On npu2 use the unrestricted device regardless of cols so the placer has + the full 8-column array. + """ + dev_str = ARCHES[arch][0] + return from_name(dev_str, n_cols=n_aie_cols if dev_str == "npu" else None) + + +def set_target_device(arch: str, n_aie_cols: int): + """Explicitly bind the target device for codegen and kernel selection.""" + iron.set_current_device(_device_for(arch, n_aie_cols)) + + +def validate_shape( + arch: str, n_aie_cols: int, M: int, K: int, N: int, m: int, k: int, n: int +) -> None: + """Raise ValueError on any geometry the design cannot express.""" + max_cols = ARCHES[arch][3] + if not 1 <= n_aie_cols <= max_cols: + raise ValueError(f"{arch} supports 1..{max_cols} AIE columns, got {n_aie_cols}") + if M % (m * N_AIE_ROWS) != 0: + raise ValueError( + f"M={M} must be a multiple of m*n_aie_rows ({m}*{N_AIE_ROWS})" + ) + n_row_blocks = M // m // N_AIE_ROWS + if n_row_blocks % 2 != 0: + raise ValueError( + f"M/m/n_aie_rows = {n_row_blocks} must be even (transfer-block " + f"ping-pong pairing); try a different m or M" + ) + if K % k != 0: + raise ValueError(f"K={K} must be a multiple of k={k}") + if N % (n * n_aie_cols) != 0: + raise ValueError( + f"N={N} must be a multiple of n*n_aie_cols ({n}*{n_aie_cols})" + ) + + +# --------------------------------------------------------------------------- +# Design (verbatim copy of whole_array.py's _build_design minus the +# generate_taps visualization mode; b_col_maj/c_col_maj are always 0 for the +# KataGo ABI but the branches are kept faithful to the template) +# --------------------------------------------------------------------------- + + +def _build_design( + dev, + M, + K, + N, + m, + k, + n, + n_aie_cols, + dtype_in_str, + dtype_out_str, + b_col_maj, + c_col_maj, + emulate_bf16_mmul_with_bfp16, + use_chess, + scalar, +): + """Build the whole-array matmul IRON design and resolve to MLIR.""" + dev_str = "npu2" if isinstance(dev, NPU2) else "npu" + + n_aie_rows = N_AIE_ROWS + n_aie_cores = n_aie_rows * n_aie_cols + + dtype_in = str_to_dtype(dtype_in_str) + dtype_out = str_to_dtype(dtype_out_str) + + assert np.issubdtype(dtype_in, np.integer) == np.issubdtype( + dtype_out, np.integer + ), f"Input dtype ({dtype_in}) and output dtype ({dtype_out}) must either both be integral or both be float" + assert ( + np.dtype(dtype_out).itemsize >= np.dtype(dtype_in).itemsize + ), f"Output dtype ({dtype_out}) must be equal or larger to input dtype ({dtype_in})" + + matmul_kernel = kernels.mm( + dim_m=m, + dim_k=k, + dim_n=n, + input_dtype=dtype_in, + output_dtype=dtype_out, + b_col_maj=bool(b_col_maj), + c_col_maj=bool(c_col_maj), + use_chess=use_chess, + emulate_bf16_mmul_with_bfp16=emulate_bf16_mmul_with_bfp16, + vectorized=not scalar, + ) + zero_kernel = matmul_kernel.zero + r, s, t = matmul_kernel.mac_dims + + if dev_str == "npu" and n_aie_cols > 4: + raise AssertionError("Invalid configuration: NPU (Phoenix/Hawk) has 4 columns") + if dev_str == "npu2" and n_aie_cols > 8: + raise AssertionError( + "Invalid configuration: NPU2 (Strix/Strix Halo/Krackan) has 8 columns" + ) + + assert ( + M % (m * n_aie_rows) == 0 + ), "A must be tileable into (m * n_aie_rows, k)-sized blocks" + assert K % k == 0 + assert ( + N % (n * n_aie_cols) == 0 + ), "B must be tileable into (k, n * n_aie_cols)-sized blocks" + assert m % r == 0 + assert k % s == 0 + assert n % t == 0 + + fifo_depth = 2 + n_tiles_per_core = (M // m) * (N // n) // n_aie_cores + + if n_aie_cols > n_aie_rows: + n_shim_mem_A = n_aie_rows + else: + n_shim_mem_A = n_aie_cols + + n_A_tiles_per_shim = n_aie_rows // n_aie_cols if n_aie_cols < 4 else 1 + + A_taps = [] + B_taps = [] + C_taps = [] + + A_ty = np.ndarray[(M * K,), np.dtype[dtype_in]] + B_ty = np.ndarray[(K * N,), np.dtype[dtype_in]] + C_ty = np.ndarray[(M * N,), np.dtype[dtype_out]] + A_l2_ty = np.ndarray[(m * k * n_A_tiles_per_shim,), np.dtype[dtype_in]] + B_l2_ty = np.ndarray[(k * n,), np.dtype[dtype_in]] + C_l2_ty = np.ndarray[(m * n * n_aie_rows,), np.dtype[dtype_out]] + A_l1_ty = np.ndarray[(m, k), np.dtype[dtype_in]] + B_l1_ty = np.ndarray[(k, n), np.dtype[dtype_in]] + C_l1_ty = np.ndarray[(m, n), np.dtype[dtype_out]] + + A_l3l2_fifos: list[ObjectFifo] = [] + A_l2l1_fifos: list[ObjectFifo] = [] + B_l3l2_fifos: list[ObjectFifo] = [] + B_l2l1_fifos: list[ObjectFifo] = [] + C_l1l2_fifos: list[list[ObjectFifo]] = [[] for _ in range(n_aie_rows)] + C_l2l3_fifos: list[ObjectFifo] = [] + + for i in range(n_shim_mem_A): + a_l3l2 = ObjectFifo(A_l2_ty, name=f"A_L3L2_{i}", depth=fifo_depth) + A_l3l2_fifos.append(a_l3l2) + start_row = i * n_A_tiles_per_shim + stop_row = start_row + n_A_tiles_per_shim + of_offsets = [m * k * j for j in range(stop_row - start_row)] + a_dims: list[StreamDims] = [ + [ + (m // r, r * k), + (k // s, s), + (r, k), + (s, 1), + ] + ] * (stop_row - start_row) + a_tmp_fifos = a_l3l2.cons().split( + of_offsets, + obj_types=[A_l1_ty] * (stop_row - start_row), + names=[f"A_L2L1_{row}" for row in range(start_row, stop_row)], + dims_to_stream=a_dims, + ) + A_l2l1_fifos.extend(a_tmp_fifos) + + for col in range(n_aie_cols): + b_l3l2 = ObjectFifo(B_l2_ty, name=f"B_L3L2_{col}", depth=fifo_depth) + B_l3l2_fifos.append(b_l3l2) + b_dims: StreamDims = ( + [(n // t, t * k), (k // s, s), (t, k), (s, 1)] + if b_col_maj + else [(k // s, s * n), (n // t, t), (s, n), (t, 1)] + ) + B_l2l1_fifos.append( + b_l3l2.cons().forward( + obj_type=B_l1_ty, + name=f"B_L2L1_{col}", + dims_to_stream=b_dims, + ) + ) + + c_dims: StreamDims = ( + [(m // r, r * n), (r, t), (n // t, r * t), (t, 1)] + if not c_col_maj + else [(n // t, t * m), (t, r), (m // r, r * t), (r, 1)] + ) + c_l2l3 = ObjectFifo( + C_l2_ty, + name=f"C_L2L3_{col}", + depth=fifo_depth, + dims_to_stream=c_dims, + ) + C_l2l3_fifos.append(c_l2l3) + of_offsets = [m * n * i for i in range(n_aie_rows)] + + c_tmp_fifos = c_l2l3.prod().join( + of_offsets, + obj_types=[C_l1_ty] * n_aie_rows, + names=[f"C_L1L2_{col}_{row}" for row in range(n_aie_rows)], + depths=[fifo_depth] * n_aie_rows, + ) + for j in range(n_aie_rows): + C_l1l2_fifos[j].append(c_tmp_fifos[j]) + + def core_fn(in_a, in_b, out_c, zero, matmul): + loop = range(1) # Workaround for issue #1547 + if n_tiles_per_core > 1: + loop = range_(n_tiles_per_core) + for _ in loop: + elem_out = out_c.acquire(1) + zero(elem_out) + + for _ in range_(K // k): + elem_in_a = in_a.acquire(1) + elem_in_b = in_b.acquire(1) + matmul(elem_in_a, elem_in_b, elem_out) + in_a.release(1) + in_b.release(1) + out_c.release(1) + + workers = Worker.grid( + n_aie_rows, + n_aie_cols, + lambda row, col: Worker( + core_fn, + [ + A_l2l1_fifos[row].cons(), + B_l2l1_fifos[col].cons(), + C_l1l2_fifos[row][col].prod(), + zero_kernel, + matmul_kernel, + ], + stack_size=0xD00, + ), + ) + + tb_max_n_rows = 4 if not c_col_maj else 2 + tb_n_rows = tb_max_n_rows // 2 + + A_tiles = TensorTiler2D.group_tiler( + (M, K), + (m * n_A_tiles_per_shim, k), + (1, K // k), + pattern_repeat=N // n // n_aie_cols, + prune_step=False, + ) + if b_col_maj: + B_tiles = TensorTiler2D.step_tiler( + (N, K), + (n, k), + tile_group_repeats=(N // n // n_aie_cols, K // k), + tile_group_steps=(n_aie_cols, 1), + prune_step=False, + ) + else: + B_tiles = TensorTiler2D.step_tiler( + (K, N), + (k, n), + tile_group_repeats=(K // k, N // n // n_aie_cols), + tile_group_steps=(1, n_aie_cols), + tile_group_col_major=True, + prune_step=False, + ) + if c_col_maj: + # Splitting n_aie_rows out of the tile dim is what lets TensorTiler emit + # the (col-fast, row_block-slow) DMA pattern; iter_col_major matches it. + C_tiles = TensorTiler2D.step_tiler( + (N, M), + (n, m), + tile_group_repeats=(N // n // n_aie_cols, n_aie_rows), + tile_group_steps=(n_aie_cols, 1), + iter_col_major=True, + prune_step=False, + ) + else: + C_tiles = TensorTiler2D.step_tiler( + (M, N), + (m * n_aie_rows, n), + tile_group_repeats=(tb_n_rows, N // n // n_aie_cols), + tile_group_steps=(1, n_aie_cols), + prune_step=False, + ) + flat_workers = [w for row in workers for w in row] + + A_prods = [f.prod() for f in A_l3l2_fifos] + B_prods = [f.prod() for f in B_l3l2_fifos] + C_conses = [f.cons() for f in C_l2l3_fifos] + + def sequence(A, B, C, A_hs, B_hs, C_hs): + c_index = 0 + tg = TaskGroup() + for tb in range(iron.ceildiv(M // m // n_aie_rows, tb_max_n_rows)): + for pingpong in [0, 1]: + if c_index >= len(C_tiles): + break + + row_base = tb * tb_max_n_rows + pingpong * tb_max_n_rows // 2 + current_tb_n_rows = min( + [tb_max_n_rows // 2, M // m // n_aie_rows - row_base] + ) + + for col in range(n_aie_cols): + C_taps.append(C_tiles[c_index]) + C_hs[col].drain( + C, + tap=C_tiles[c_index], + wait=True, + group=tg, + ) + c_index += 1 + + for tile_row in range(current_tb_n_rows): + tile_offset = ( + (row_base + tile_row) * n_shim_mem_A + col + ) % len(A_tiles) + if col < n_aie_rows: + A_hs[col].fill( + A, + tap=A_tiles[tile_offset], + group=tg, + ) + B_hs[col].fill( + B, + tap=B_tiles[col], + group=tg, + ) + A_taps.append(A_tiles[tile_offset]) + B_taps.append(B_tiles[col]) + + if tb > 0 or (tb == 0 and pingpong > 0): + tg.finish() + tg = TaskGroup() + tg.finish() + + rt = Runtime( + sequence, + [A_ty, B_ty, C_ty, A_prods, B_prods, C_conses], + ) + + program = Program(dev, rt, workers=flat_workers) + module = program.resolve_program() + + return module + + +@iron.jit(aiecc_flags=["--alloc-scheme=basic-sequential"]) +def gemm_bf16( + A: In, + B: In, + C: Out, + *, + M: CompileTime[int], + K: CompileTime[int], + N: CompileTime[int], + m: CompileTime[int], + k: CompileTime[int], + n: CompileTime[int], + n_aie_cols: CompileTime[int], + emulate_bf16_mmul_with_bfp16: CompileTime[bool] = False, +): + return _build_design( + iron.get_current_device(), + M, + K, + N, + m, + k, + n, + n_aie_cols, + DTYPE_IN_STR, + DTYPE_OUT_STR, + 0, # b_col_maj + 0, # c_col_maj + emulate_bf16_mmul_with_bfp16, + False, # use_chess + False, # scalar + ) + + +# --------------------------------------------------------------------------- +# Host-side helpers (compile / metadata / verify) +# --------------------------------------------------------------------------- + + +def compile_aot( + arch: str, + n_aie_cols: int, + dtype: str, + M: int, + K: int, + N: int, + m: int, + k: int, + n: int, + xclbin_path: str, + insts_path: str, +) -> float: + """AOT-compile one variant to explicit paths; returns wall-clock seconds. + + Explicit output paths bypass the JIT cache, so this is always a true + cold compile. + """ + validate_shape(arch, n_aie_cols, M, K, N, m, k, n) + set_target_device(arch, n_aie_cols) + start = time.perf_counter() + spec = gemm_bf16.specialize( + M=M, + K=K, + N=N, + m=m, + k=k, + n=n, + n_aie_cols=n_aie_cols, + emulate_bf16_mmul_with_bfp16=(dtype == "bfp16"), + ) + spec.compile(xclbin_path=xclbin_path, inst_path=insts_path) + return time.perf_counter() - start + + +def kernel_info(arch: str, n_aie_cols: int, dtype: str, m: int, k: int, n: int) -> dict: + """Static kernel metadata for the manifest (no design compilation).""" + set_target_device(arch, n_aie_cols) + matmul_kernel = kernels.mm( + dim_m=m, + dim_k=k, + dim_n=n, + input_dtype=INPUT_DTYPE, + output_dtype=OUTPUT_DTYPE, + emulate_bf16_mmul_with_bfp16=(dtype == "bfp16"), + vectorized=True, + ) + return { + "tile": {"m": m, "k": k, "n": n}, + "mac_dims": list(matmul_kernel.mac_dims), + "core_kernel": getattr(matmul_kernel, "_name", "matmul_bf16_f32"), + "zero_kernel": getattr(matmul_kernel.zero, "_name", "zero_f32"), + "input_dtype": "bfloat16", + "output_dtype": "float32", + "iron_device": ARCHES[arch][0], + "aie_arch": ARCHES[arch][1], + } + + +def run_and_verify( + arch: str, + n_aie_cols: int, + dtype: str, + M: int, + K: int, + N: int, + m: int, + k: int, + n: int, + warmup: int = 3, + iters: int = 10, + seed: int = 0, +) -> bool: + """Run one variant on the NPU and compare against a float64 reference.""" + validate_shape(arch, n_aie_cols, M, K, N, m, k, n) + set_target_device(arch, n_aie_cols) + emulate = dtype == "bfp16" + print(f"\n=== Running gemm_bf16 {M}x{K}x{N} {dtype} {arch} cols={n_aie_cols} " + f"tile={m}x{k}x{n} ===") + rng = np.random.default_rng(seed) + a_np = rng.uniform(-1.0, 1.0, size=(M, K)).astype(bfloat16) + b_np = rng.uniform(-1.0, 1.0, size=(K, N)).astype(bfloat16) + + input0 = iron.tensor(a_np, dtype=bfloat16, device="npu") + input1 = iron.tensor(b_np, dtype=bfloat16, device="npu") + output = iron.zeros(M * N, dtype=OUTPUT_DTYPE, device="npu") + + # bf16 x bf16 products are exact in fp32, so a float64 reference from the + # already-rounded bf16 inputs agrees with the NPU up to fp32 accumulation + # ordering (~1e-3 absolute at K=768). + ref = a_np.astype(np.float64) @ b_np.astype(np.float64) + + bench = run_iters( + gemm_bf16, + input0, + input1, + output, + M=M, + K=K, + N=N, + m=m, + k=k, + n=n, + n_aie_cols=n_aie_cols, + emulate_bf16_mmul_with_bfp16=emulate, + warmup=warmup, + iters=iters, + ) + + got = output.numpy().reshape(M, N).astype(np.float64) + abs_err = np.abs(got - ref) + rel_err = abs_err / np.maximum(np.abs(ref), 1e-6) + print( + f" max abs err: {abs_err.max():.6g} " + f"max rel err: {rel_err.max():.6g} " + f"|C| max: {np.abs(ref).max():.6g}" + ) + rtol, atol = 0.02, 0.1 + ok = bool(np.all(abs_err <= atol + rtol * np.abs(ref))) + if bench.npu is not None: + avg_us = bench.npu.avg_us + gflops = 2.0 * M * K * N / (1000.0 * avg_us) + print(f" NPU time avg: {avg_us:.1f} us {gflops:.2f} GFLOPS") + if not ok: + n_bad = int(np.sum(abs_err > atol + rtol * np.abs(ref))) + print(f" FAIL: {n_bad}/{ref.size} elements outside rtol={rtol} atol={atol}") + return False + print(f" PASS (rtol={rtol}, atol={atol})") + return True + + +def main(): + parser = argparse.ArgumentParser(prog="gemm_bf16") + parser.add_argument("--arch", choices=list(ARCHES), default="npu2") + parser.add_argument("--n-aie-cols", type=int, choices=[1, 2, 4, 8], default=8) + parser.add_argument( + "--dtype", + choices=["bf16", "bfp16"], + default="bf16", + help="bf16 = native bf16 MMUL; bfp16 = BFP16-emulated bf16 MMUL " + "(AIE2P only, ~1.4x on Strix)", + ) + parser.add_argument("-M", type=int, required=True) + parser.add_argument("-K", type=int, required=True) + parser.add_argument("-N", type=int, required=True) + parser.add_argument("-m", type=int, default=DEFAULT_TILE["m"]) + parser.add_argument("-k", type=int, default=DEFAULT_TILE["k"]) + parser.add_argument("-n", type=int, default=DEFAULT_TILE["n"]) + parser.add_argument("--xclbin-path", type=str, default=None, + help="compile-only mode: write the xclbin here") + parser.add_argument("--insts-path", type=str, default=None, + help="compile-only mode: write the instruction binary here") + parser.add_argument("--warmup", type=int, default=3) + parser.add_argument("--iters", type=int, default=10) + args = parser.parse_args() + + if (args.xclbin_path is None) != (args.insts_path is None): + parser.error("--xclbin-path and --insts-path must be given together") + if args.dtype == "bfp16" and args.arch != "npu2": + parser.error("--dtype bfp16 (BFP16 emulation) is only supported on npu2") + + try: + validate_shape(args.arch, args.n_aie_cols, args.M, args.K, args.N, + args.m, args.k, args.n) + except ValueError as e: + parser.error(str(e)) + + if args.xclbin_path is not None: + secs = compile_aot( + args.arch, args.n_aie_cols, args.dtype, + args.M, args.K, args.N, args.m, args.k, args.n, + args.xclbin_path, args.insts_path, + ) + print(f"AOT compiled {args.M}x{args.K}x{args.N} {args.dtype} " + f"{args.arch} cols={args.n_aie_cols} tile={args.m}x{args.k}x{args.n} " + f"in {secs:.1f}s -> {args.xclbin_path}, {args.insts_path}") + return + + if args.arch != "npu2": + parser.error("on-hardware verification requires an attached npu2 device; " + "use --xclbin-path/--insts-path for compile-only npu1 builds") + if not run_and_verify( + args.arch, args.n_aie_cols, args.dtype, + args.M, args.K, args.N, args.m, args.k, args.n, + warmup=args.warmup, iters=args.iters, + ): + raise SystemExit(1) + print("PASS!") + + +if __name__ == "__main__": + main() diff --git a/python/ryzenai_kernels/gemm_swiglu_bf16.py b/python/ryzenai_kernels/gemm_swiglu_bf16.py new file mode 100644 index 000000000..d434b0cce --- /dev/null +++ b/python/ryzenai_kernels/gemm_swiglu_bf16.py @@ -0,0 +1,457 @@ +# gemm_swiglu_bf16.py +# +# Variant of gemm_bf16.py whose cores apply a SwiGLU epilogue to the +# accumulated C tile before it leaves the core. Everything else -- the +# whole_array design, the DMA layout, the host ABI (row-major bf16 A/B in, +# row-major f32 C out, same opcode-3 dispatch) -- is identical to the plain +# GEMM, so the same runtime-generated instruction streams drive it. +# +# The epilogue expects B's columns pre-interleaved by the host in groups of 8: +# [linear1 ch 0-7, linearGate ch 0-7, linear1 ch 8-15, ...] and writes +# silu(l1) * gate back over the linear1 positions. The host reads C column +# (c>>3)*16 + (c&7) for out channel c and ignores the gate columns. See +# kernels/mm_swiglu_epilogue.cc. +# +# Compile-only: the on-hardware check goes through the C++ probe in the +# scratchpad (this mlir-aie build's Python side cannot allocate NPU tensors). +# +# Usage (inside the activated mlir-aie iron environment): +# python gemm_swiglu_bf16.py -K 512 --n-aie-cols 4 \ +# --xclbin-path out.xclbin --insts-path out.insts.bin + +import argparse +import time +from pathlib import Path + +import aie.iron as iron +import numpy as np +from aie.helpers.taplib import TensorTiler2D +from aie.iron import ( + CompileTime, + In, + ObjectFifo, + Out, + Program, + Runtime, + StreamDims, + TaskGroup, + Worker, + kernels, + str_to_dtype, +) +from aie.iron.controlflow import range_ +from aie.iron.device import NPU2, from_name +from aie.iron.kernel import ExternalFunction +from aie.utils import config +from ml_dtypes import bfloat16 + +KERNEL_CC = str(Path(__file__).parent / "kernels" / "mm_swiglu_epilogue.cc") + +# --------------------------------------------------------------------------- +# Target configuration (identical to gemm_bf16.py) +# --------------------------------------------------------------------------- + +ARCHES = { + "npu1": ("npu", "aie2", "XDNA1 (Ryzen AI Phoenix/Hawk Point)", 4), + "npu2": ("npu2", "aie2p", "XDNA2 (Ryzen AI Strix/Krackan)", 8), +} + +N_AIE_ROWS = 4 + +INPUT_DTYPE = bfloat16 +OUTPUT_DTYPE = np.float32 +DTYPE_IN_STR = "bf16" +DTYPE_OUT_STR = "f32" + +DEFAULT_TILE = {"m": 32, "k": 64, "n": 32} + + +def _device_for(arch: str, n_aie_cols: int): + dev_str = ARCHES[arch][0] + return from_name(dev_str, n_cols=n_aie_cols if dev_str == "npu" else None) + + +def set_target_device(arch: str, n_aie_cols: int): + iron.set_current_device(_device_for(arch, n_aie_cols)) + + +def validate_shape( + arch: str, n_aie_cols: int, M: int, K: int, N: int, m: int, k: int, n: int +) -> None: + max_cols = ARCHES[arch][3] + if not 1 <= n_aie_cols <= max_cols: + raise ValueError(f"{arch} supports 1..{max_cols} AIE columns, got {n_aie_cols}") + if M % (m * N_AIE_ROWS) != 0: + raise ValueError(f"M={M} must be a multiple of m*n_aie_rows ({m}*{N_AIE_ROWS})") + n_row_blocks = M // m // N_AIE_ROWS + if n_row_blocks % 2 != 0: + raise ValueError( + f"M/m/n_aie_rows = {n_row_blocks} must be even (transfer-block " + f"ping-pong pairing); try a different m or M" + ) + if K % k != 0: + raise ValueError(f"K={K} must be a multiple of k={k}") + if N % (n * n_aie_cols) != 0: + raise ValueError(f"N={N} must be a multiple of n*n_aie_cols ({n}*{n_aie_cols})") + # The epilogue pairs adjacent 8-column sub-tiles, so each core's n-column + # slice must hold whole (l, g) pairs. + if n % 16 != 0: + raise ValueError(f"n={n} must be a multiple of 16 for the swiglu pairing") + + +# --------------------------------------------------------------------------- +# Design: gemm_bf16.py's whole-array build plus the epilogue call in core_fn +# --------------------------------------------------------------------------- + + +def _build_design( + dev, + M, + K, + N, + m, + k, + n, + n_aie_cols, + dtype_in_str, + dtype_out_str, +): + dev_str = "npu2" if isinstance(dev, NPU2) else "npu" + + n_aie_rows = N_AIE_ROWS + n_aie_cores = n_aie_rows * n_aie_cols + + dtype_in = str_to_dtype(dtype_in_str) + dtype_out = str_to_dtype(dtype_out_str) + + matmul_kernel = kernels.mm( + dim_m=m, + dim_k=k, + dim_n=n, + input_dtype=dtype_in, + output_dtype=dtype_out, + b_col_maj=False, + c_col_maj=False, + use_chess=False, + emulate_bf16_mmul_with_bfp16=False, + vectorized=True, + ) + zero_kernel = matmul_kernel.zero + r, s, t = matmul_kernel.mac_dims + + assert M % (m * n_aie_rows) == 0 + assert K % k == 0 + assert N % (n * n_aie_cols) == 0 + assert m % r == 0 + assert k % s == 0 + assert n % t == 0 + + fifo_depth = 2 + n_tiles_per_core = (M // m) * (N // n) // n_aie_cores + + if n_aie_cols > n_aie_rows: + n_shim_mem_A = n_aie_rows + else: + n_shim_mem_A = n_aie_cols + + n_A_tiles_per_shim = n_aie_rows // n_aie_cols if n_aie_cols < 4 else 1 + + A_taps = [] + B_taps = [] + C_taps = [] + + A_ty = np.ndarray[(M * K,), np.dtype[dtype_in]] + B_ty = np.ndarray[(K * N,), np.dtype[dtype_in]] + C_ty = np.ndarray[(M * N,), np.dtype[dtype_out]] + A_l2_ty = np.ndarray[(m * k * n_A_tiles_per_shim,), np.dtype[dtype_in]] + B_l2_ty = np.ndarray[(k * n,), np.dtype[dtype_in]] + C_l2_ty = np.ndarray[(m * n * n_aie_rows,), np.dtype[dtype_out]] + A_l1_ty = np.ndarray[(m, k), np.dtype[dtype_in]] + B_l1_ty = np.ndarray[(k, n), np.dtype[dtype_in]] + C_l1_ty = np.ndarray[(m, n), np.dtype[dtype_out]] + + swiglu_kernel = ExternalFunction( + "mm_swiglu_epilogue_f32", + source_file=KERNEL_CC, + arg_types=[C_l1_ty], + compile_flags=[f"-DDIM_M={m}", f"-DDIM_N={n}"], + include_dirs=[config.cxx_header_path()], + ) + + A_l3l2_fifos: list[ObjectFifo] = [] + A_l2l1_fifos: list[ObjectFifo] = [] + B_l3l2_fifos: list[ObjectFifo] = [] + B_l2l1_fifos: list[ObjectFifo] = [] + C_l1l2_fifos: list[list[ObjectFifo]] = [[] for _ in range(n_aie_rows)] + C_l2l3_fifos: list[ObjectFifo] = [] + + for i in range(n_shim_mem_A): + a_l3l2 = ObjectFifo(A_l2_ty, name=f"A_L3L2_{i}", depth=fifo_depth) + A_l3l2_fifos.append(a_l3l2) + start_row = i * n_A_tiles_per_shim + stop_row = start_row + n_A_tiles_per_shim + of_offsets = [m * k * j for j in range(stop_row - start_row)] + a_dims: list[StreamDims] = [ + [ + (m // r, r * k), + (k // s, s), + (r, k), + (s, 1), + ] + ] * (stop_row - start_row) + a_tmp_fifos = a_l3l2.cons().split( + of_offsets, + obj_types=[A_l1_ty] * (stop_row - start_row), + names=[f"A_L2L1_{row}" for row in range(start_row, stop_row)], + dims_to_stream=a_dims, + ) + A_l2l1_fifos.extend(a_tmp_fifos) + + for col in range(n_aie_cols): + b_l3l2 = ObjectFifo(B_l2_ty, name=f"B_L3L2_{col}", depth=fifo_depth) + B_l3l2_fifos.append(b_l3l2) + b_dims: StreamDims = [(k // s, s * n), (n // t, t), (s, n), (t, 1)] + B_l2l1_fifos.append( + b_l3l2.cons().forward( + obj_type=B_l1_ty, + name=f"B_L2L1_{col}", + dims_to_stream=b_dims, + ) + ) + + c_dims: StreamDims = [(m // r, r * n), (r, t), (n // t, r * t), (t, 1)] + c_l2l3 = ObjectFifo( + C_l2_ty, + name=f"C_L2L3_{col}", + depth=fifo_depth, + dims_to_stream=c_dims, + ) + C_l2l3_fifos.append(c_l2l3) + of_offsets = [m * n * i for i in range(n_aie_rows)] + + c_tmp_fifos = c_l2l3.prod().join( + of_offsets, + obj_types=[C_l1_ty] * n_aie_rows, + names=[f"C_L1L2_{col}_{row}" for row in range(n_aie_rows)], + depths=[fifo_depth] * n_aie_rows, + ) + for j in range(n_aie_rows): + C_l1l2_fifos[j].append(c_tmp_fifos[j]) + + def core_fn(in_a, in_b, out_c, zero, matmul, swiglu): + loop = range(1) + if n_tiles_per_core > 1: + loop = range_(n_tiles_per_core) + for _ in loop: + elem_out = out_c.acquire(1) + zero(elem_out) + + for _ in range_(K // k): + elem_in_a = in_a.acquire(1) + elem_in_b = in_b.acquire(1) + matmul(elem_in_a, elem_in_b, elem_out) + in_a.release(1) + in_b.release(1) + # K reduction done: C tile holds the raw GEMM. Apply silu(l)*g over + # the (l, g) sub-tile pairs in place, then hand the tile off. + swiglu(elem_out) + out_c.release(1) + + workers = Worker.grid( + n_aie_rows, + n_aie_cols, + lambda row, col: Worker( + core_fn, + [ + A_l2l1_fifos[row].cons(), + B_l2l1_fifos[col].cons(), + C_l1l2_fifos[row][col].prod(), + zero_kernel, + matmul_kernel, + swiglu_kernel, + ], + stack_size=0xD00, + ), + ) + + tb_max_n_rows = 4 + tb_n_rows = tb_max_n_rows // 2 + + A_tiles = TensorTiler2D.group_tiler( + (M, K), + (m * n_A_tiles_per_shim, k), + (1, K // k), + pattern_repeat=N // n // n_aie_cols, + prune_step=False, + ) + B_tiles = TensorTiler2D.step_tiler( + (K, N), + (k, n), + tile_group_repeats=(K // k, N // n // n_aie_cols), + tile_group_steps=(1, n_aie_cols), + tile_group_col_major=True, + prune_step=False, + ) + C_tiles = TensorTiler2D.step_tiler( + (M, N), + (m * n_aie_rows, n), + tile_group_repeats=(tb_n_rows, N // n // n_aie_cols), + tile_group_steps=(1, n_aie_cols), + prune_step=False, + ) + flat_workers = [w for row in workers for w in row] + + A_prods = [f.prod() for f in A_l3l2_fifos] + B_prods = [f.prod() for f in B_l3l2_fifos] + C_conses = [f.cons() for f in C_l2l3_fifos] + + def sequence(A, B, C, A_hs, B_hs, C_hs): + c_index = 0 + tg = TaskGroup() + for tb in range(iron.ceildiv(M // m // n_aie_rows, tb_max_n_rows)): + for pingpong in [0, 1]: + if c_index >= len(C_tiles): + break + + row_base = tb * tb_max_n_rows + pingpong * tb_max_n_rows // 2 + current_tb_n_rows = min( + [tb_max_n_rows // 2, M // m // n_aie_rows - row_base] + ) + + for col in range(n_aie_cols): + C_taps.append(C_tiles[c_index]) + C_hs[col].drain( + C, + tap=C_tiles[c_index], + wait=True, + group=tg, + ) + c_index += 1 + + for tile_row in range(current_tb_n_rows): + tile_offset = ( + (row_base + tile_row) * n_shim_mem_A + col + ) % len(A_tiles) + if col < n_aie_rows: + A_hs[col].fill( + A, + tap=A_tiles[tile_offset], + group=tg, + ) + B_hs[col].fill( + B, + tap=B_tiles[col], + group=tg, + ) + A_taps.append(A_tiles[tile_offset]) + B_taps.append(B_tiles[col]) + + if tb > 0 or (tb == 0 and pingpong > 0): + tg.finish() + tg = TaskGroup() + tg.finish() + + rt = Runtime( + sequence, + [A_ty, B_ty, C_ty, A_prods, B_prods, C_conses], + ) + + program = Program(dev, rt, workers=flat_workers) + module = program.resolve_program() + + return module + + +@iron.jit(aiecc_flags=["--alloc-scheme=basic-sequential"]) +def gemm_swiglu_bf16( + A: In, + B: In, + C: Out, + *, + M: CompileTime[int], + K: CompileTime[int], + N: CompileTime[int], + m: CompileTime[int], + k: CompileTime[int], + n: CompileTime[int], + n_aie_cols: CompileTime[int], +): + return _build_design( + iron.get_current_device(), + M, + K, + N, + m, + k, + n, + n_aie_cols, + DTYPE_IN_STR, + DTYPE_OUT_STR, + ) + + +# --------------------------------------------------------------------------- + + +def compile_aot( + arch: str, + n_aie_cols: int, + M: int, + K: int, + N: int, + m: int, + k: int, + n: int, + xclbin_path: str, + insts_path: str, +) -> float: + """AOT-compile one variant to explicit paths; returns wall-clock seconds.""" + validate_shape(arch, n_aie_cols, M, K, N, m, k, n) + set_target_device(arch, n_aie_cols) + start = time.perf_counter() + spec = gemm_swiglu_bf16.specialize( + M=M, + K=K, + N=N, + m=m, + k=k, + n=n, + n_aie_cols=n_aie_cols, + ) + spec.compile(xclbin_path=xclbin_path, inst_path=insts_path) + return time.perf_counter() - start + + +def main(): + parser = argparse.ArgumentParser(prog="gemm_swiglu_bf16") + parser.add_argument("--arch", choices=list(ARCHES), default="npu2") + parser.add_argument("--n-aie-cols", type=int, choices=[1, 2, 4, 8], default=4) + parser.add_argument("-M", type=int, default=256) + parser.add_argument("-K", type=int, required=True) + parser.add_argument("-N", type=int, default=0, help="0 picks n*cols*2") + parser.add_argument("-m", type=int, default=DEFAULT_TILE["m"]) + parser.add_argument("-k", type=int, default=DEFAULT_TILE["k"]) + parser.add_argument("-n", type=int, default=DEFAULT_TILE["n"]) + parser.add_argument("--xclbin-path", type=str, required=True) + parser.add_argument("--insts-path", type=str, required=True) + args = parser.parse_args() + + N = args.N if args.N > 0 else args.n * args.n_aie_cols * 2 + try: + validate_shape(args.arch, args.n_aie_cols, args.M, args.K, N, + args.m, args.k, args.n) + except ValueError as e: + parser.error(str(e)) + + secs = compile_aot( + args.arch, args.n_aie_cols, + args.M, args.K, N, args.m, args.k, args.n, + args.xclbin_path, args.insts_path, + ) + print(f"AOT compiled swiglu-epilogue GEMM {args.M}x{args.K}x{N} " + f"{args.arch} cols={args.n_aie_cols} tile={args.m}x{args.k}x{args.n} " + f"in {secs:.1f}s -> {args.xclbin_path}, {args.insts_path}") + + +if __name__ == "__main__": + main() diff --git a/python/ryzenai_kernels/kernels/attention_head.cc b/python/ryzenai_kernels/kernels/attention_head.cc new file mode 100644 index 000000000..cc014dbb5 --- /dev/null +++ b/python/ryzenai_kernels/kernels/attention_head.cc @@ -0,0 +1,132 @@ +// attention_head.cc - fused single-head attention tile kernel for AIE2P +// (Strix/npu2), bf16 in with f32 accumulation. +// +// One AIE core owns one attention head for a whole dispatch. K and V arrive +// as one packed per-head buffer (a core tile has only two input DMA +// channels), pre-tiled by the host into the mmul tile order the stock +// 2x2_mmul template reads; Q streams through in 8-row blocks, likewise +// pre-tiled. Per 8-row query block: +// +// scores[8 x 384] = Q[8 x 32] @ K^T[32 x 384] (K col-major B) +// scores = softmax(scores) (pad columns forced -1e30) +// out[8 x 32] = P[8 x 384] @ V[384 x 32] (V row-major B, f32 out) +// +// LAYOUT NOTE (the subtle part of this kernel): the stock matmul template +// reads A and B and writes C in mmul tile order -- (4x8) tiles of A, (8x8) +// tiles of B, (4x8) tiles of C, NOT plain row-major. The host pre-tiles Q/K/V +// and un-tiles the output; the score buffer never leaves the core, so the +// softmax here gathers it out of QK^T's C-tile order and scatters the +// probabilities into P*V's A-tile order. The three index mappings below are +// derived from matmul_vectorized_2x2_mmul's pointer arithmetic in mm.cc and +// verified on hardware by attnbench. +// +// Numerics match the staged path: scores are bf16 before the exp (as they +// are when the standalone softmax op reads them), P*V accumulates in f32. +// Pad key columns are set to (row max - 20) before the softmax -- NOT -inf, +// because this kernel's f32 exp2 wraps huge negative inputs to huge positive +// ones -- and then written as exact 0 into P, so they contribute nothing. +// Pad query rows produce finite garbage the host discards. + +#define DIM_M 8 +#define DIM_K 32 +#define DIM_N 384 +#define bf16_bf16_ONLY +#define B_COL_MAJ + +#include "aie_kernels/aie2p/mm.cc" +#include "aie_kernels/aie2p/softmax.cc" + +#ifndef ATTN_S_REAL +#define ATTN_S_REAL 361 +#endif + +namespace { + +// Per-core scratch in L1: QK^T's scores and P*V's probabilities (same +// elements, different tile order), plus one plain row for the softmax. +// Static storage is private to each core (each core links its own ELF). +alignas(64) bfloat16 g_scores[8 * 384]; +bfloat16 g_row[384]; + +// The C-tile order of QK^T and the A-tile order of P*V are the SAME formula +// for these shapes (verified on hardware), so the softmax reads and writes +// g_scores in place through idx_tile -- no separate probability buffer. +int idx_tile(int qi, int ki) { + return (qi >> 2) * 1536 + (ki >> 3) * 32 + (qi & 3) * 8 + (ki & 7); +} + +} // namespace + +extern "C" { + +// One 8-row query block of one head: q = 256 bf16 in A-tile order, kv = the +// head's K then V, each 384x32 bf16 in B-tile order (back to back), out = +// 8x32 f32 in C-tile order (host un-tiles on readback). +void attn_block_bf16(bfloat16 *restrict q, bfloat16 *restrict kv, + float *restrict out) { + const bfloat16 *k = kv; + const bfloat16 *v = kv + (size_t)384 * 32; + + // The 2x2_mmul template accumulates onto C in place (the GEMM design zeroes + // between calls), so both output buffers must be zeroed first. + for (int i = 0; i < 8 * 384; i++) + g_scores[i] = (bfloat16)0.0f; + for (int i = 0; i < 8 * 32; i++) + out[i] = 0.0f; + + // scores = Q @ K^T (K's tile order is the col-major-B one). + matmul_vectorized_2x2_mmul( + q, k, g_scores); + + // Per-row softmax. The tiled score layout keeps one row's 8 columns + // contiguous within each 32-element group, so gather/scatter run as + // 8-wide vector ops. Pad columns get (row max - 20), NOT -inf: this + // softmax kernel computes exp2 in f32 and huge negative inputs wrap the + // exponent field to huge POSITIVE values (measured: -1e30 pads come out as + // ~+7.7e30). max-20 gives exp2(-28.9) ~ 3e-9, negligible and safe. Pad + // columns are stored as exact 0 afterwards. + for (int r = 0; r < 8; r++) { + const int rbase = (r >> 2) * 1536 + (r & 3) * 8; + // Full 8-column chunks are gathered as vectors; the ragged tail (S is not + // a multiple of 8) is gathered element-wise so stale values never leak in. + aie::vector vmax8 = aie::broadcast(-1e30f); + constexpr int fullG = ATTN_S_REAL / 8; + for (int g = 0; g < fullG; g++) { + aie::vector el = aie::load_v<8>(g_scores + rbase + g * 32); + aie::store_v(g_row + g * 8, el); + aie::vector f = aie::accum(el).to_vector(); + vmax8 = aie::max(vmax8, f); + } + float maxVal = aie::reduce_max(vmax8); + for (int ki = fullG * 8; ki < ATTN_S_REAL; ki++) { + const bfloat16 el = g_scores[rbase + (ki >> 3) * 32 + (ki & 7)]; + g_row[ki] = el; + if((float)el > maxVal) + maxVal = (float)el; + } + // Pad columns: row max - 20, NOT -inf (see above about the exp2 wrap). + // Their softmax output is stored as exact 0 below, and V's pad rows are + // host-zeroed, so the pads contribute nothing either way. + for (int ki = ATTN_S_REAL; ki < 384; ki++) + g_row[ki] = (bfloat16)(maxVal - 20.0f); + softmax_simple_bf16(g_row, g_row, 384); + for (int g = 0; g < fullG; g++) + aie::store_v(g_scores + rbase + g * 32, aie::load_v<8>(g_row + g * 8)); + for (int ki = fullG * 8; ki < ATTN_S_REAL; ki++) + g_scores[rbase + (ki >> 3) * 32 + (ki & 7)] = g_row[ki]; + for (int g = (ATTN_S_REAL + 7) / 8; g < 48; g++) + aie::store_v(g_scores + rbase + g * 32, aie::broadcast(0.0f)); + } + + // out = P @ V, f32. V arrives col-major (its host tiling matches the + // col-major B read verified by the PV probe; the row-major read was never + // verified for this shape). + matmul_vectorized_2x2_mmul( + g_scores, v, out); +} + +} // extern "C" diff --git a/python/ryzenai_kernels/kernels/bn_mish.cc b/python/ryzenai_kernels/kernels/bn_mish.cc new file mode 100644 index 000000000..2d5c324f1 --- /dev/null +++ b/python/ryzenai_kernels/kernels/bn_mish.cc @@ -0,0 +1,100 @@ +// bn_mish.cc - fused per-channel BatchNorm scale/bias + Mish activation, +// row-streamed, bf16 in/out, f32 internal, for AIE2P (Strix/npu2). +// +// out[r][c] = mish(scale[c] * x[r][c] + bias[c]) +// +// mish(t) = t * (s^2 + 2s) / (s^2 + 2s + 2) with s = e^t. The division uses +// aie::inv (vector reciprocal). For t > 16 the formula saturates to t +// (mish(16) == 16 to bf16 precision), so the exp argument is clamped at 16 +// and the result selected from the identity branch above the clamp. For +// t < -16 the result is ~t*e^t, already below bf16 resolution. +// +// scale/bias are resident per core (the host replicates the vectors across +// the 8 columns). width must be a multiple of 16. + +#include +#include + +namespace { + +constexpr float kLog2e = 1.44269504089f; + +} // namespace + +extern "C" { + +void bn_mish_bf16(bfloat16 *restrict input, bfloat16 *restrict sb, + bfloat16 *restrict output, const int32_t rows, + const int32_t width) { + // A core tile has only two input DMA channels, so scale and bias arrive as + // one buffer: [scale (width) | bias (width)]. + const bfloat16 *scale = sb; + const bfloat16 *bias = sb + width; + constexpr int V = 16; + const int chunks = width / V; + for (int r = 0; r < rows; r++) { + const bfloat16 *in = input + (size_t)r * width; + bfloat16 *out = output + (size_t)r * width; + for (int i = 0; i < chunks; i++) { + aie::vector xb = aie::load_v(in + i * V); +#ifdef BNM_DUMPMODE + // 1: copy x; 2: output t=x*s+b; else full mish + if(BNM_DUMPMODE == 1) { aie::store_v(out + i * V, xb); continue; } +#endif + aie::vector sb = aie::load_v(scale + i * V); + aie::vector bb = aie::load_v(bias + i * V); + + aie::vector x = aie::accum(xb).to_vector(); + aie::vector sc = aie::accum(sb).to_vector(); + aie::vector bi = aie::accum(bb).to_vector(); + + // t = x*scale + bias. The exp path clamps at +16 (bf16 resolution makes + // mish(16) == 16); anything above the clamp is the identity branch and + // is added back as the excess, so no select/mask is needed: + // out = mish(min(t,16)) + max(t-16, 0) + aie::vector t = aie::add(aie::mul(x, sc), bi); + // Clamp for the exp overflow point. aie::min/max on f32 vectors are + // broken on XDNA2 (they returned garbage -- measured), so the clamp runs + // in bf16 through the proven from_vector/to_vector conversions. The + // excess above the clamp is kept exactly: out = mish(min(t,16)) + (t-tc). + aie::accum tacc; + tacc.from_vector(t); + aie::vector tcb = + aie::min(tacc.to_vector(), aie::broadcast(16.0f)); + aie::accum tcacc; + tcacc.from_vector(tcb); + aie::vector tc = tcacc.to_vector(); + aie::vector over = aie::sub(t, tc); + + // s = e^tc = exp2(tc * log2e). XDNA2's exp2 returns bf16 (f32 return is + // AIE_MLv2-only), which is plenty since the output is bf16 anyway. + aie::vector arg = + aie::mul(tc, aie::broadcast(kLog2e)); + aie::vector sigb = aie::exp2(arg); + aie::vector sig = aie::accum(sigb).to_vector(); + // mish = tc * (s^2+2s)/(s^2+2s+2) = tc * num/(num+2). XDNA2's vector + // reciprocal only takes bf16, so the divide narrows through bf16 -- + // harmless at bf16 output precision. + aie::vector two = aie::broadcast(2.0f); + aie::vector num = aie::add(aie::mul(sig, sig), aie::mul(two, sig)); + aie::vector den = aie::add(num, two); + aie::accum den_acc; + den_acc.from_vector(den); + aie::vector rinv_b = aie::inv(den_acc.to_vector()); + aie::accum rinv_acc; + rinv_acc.from_vector(rinv_b); + aie::vector frac = aie::mul(num, rinv_acc.to_vector()); + aie::vector mish = aie::mul(tc, frac); + aie::vector res = aie::add(mish, over); +#ifdef BNM_DUMPMODE + if(BNM_DUMPMODE == 2) + res = t; // output the pre-activation +#endif + aie::accum rac; + rac.from_vector(res); + aie::store_v(out + i * V, rac.to_vector()); + } + } +} + +} // extern "C" diff --git a/python/ryzenai_kernels/kernels/mm_swiglu_epilogue.cc b/python/ryzenai_kernels/kernels/mm_swiglu_epilogue.cc new file mode 100644 index 000000000..259239f50 --- /dev/null +++ b/python/ryzenai_kernels/kernels/mm_swiglu_epilogue.cc @@ -0,0 +1,79 @@ +// mm_swiglu_epilogue.cc -- SwiGLU epilogue for the whole_array bf16 GEMM core. +// +// Runs on the fully accumulated C tile (DIM_M x DIM_N f32) after the K loop, +// before the tile is released to the output fifo. The host uploaded B with the +// linear1 / linearGate columns interleaved in groups of 8: +// +// B column (c>>3)*16 + (c&7) = linear1 weight for out channel c +// B column (c>>3)*16 + 8 + (c&7) = linearGate weight for out channel c +// +// so inside a core's C tile every even 8-column sub-tile holds linear1 outputs +// and the following odd sub-tile the matching gates. The epilogue computes +// silu(l) * g for each pair and writes it back over the l positions; the gate +// positions keep their raw values and the host simply never reads them. +// +// The C tile's in-memory order is the stock 2x2_mmul template's (r=4, t=8 +// sub-tiles): logical element (i, j) of the tile sits at +// +// offset(i, j) = (i >> 2) * (4 * DIM_N) + (j >> 3) * 32 + (i & 3) * 8 + (j & 7) +// +// (hardware-verified for this template family, see the attention op's probes). +// An (l, g) sub-tile pair is therefore always 32 contiguous f32 apart, and each +// 16-lane chunk within a sub-tile holds whole rows of one pair half. +// +// SiLU follows mm_activation_epilogue.cc: sigmoid built from the tanh SFU as +// 0.5 * (1 + tanh(x/2)), narrowing to bf16 only inside the sigmoid where the +// [0, 1] range is harmless; x, the gate and both multiplies stay f32. + +#include +#include + +#ifndef DIM_M +#define DIM_M 32 +#endif +#ifndef DIM_N +#define DIM_N 32 +#endif + +using namespace aie; + +static inline aie::vector swiglu16(aie::vector l, + aie::vector g) { + const aie::vector halff = aie::broadcast(0.5f); + const aie::vector onef = aie::broadcast(1.0f); + aie::vector half_l = aie::mul(l, halff); + // Only the tanh itself narrows to bf16 (the SFU's output format); the + // 1 + t and the 0.5x stay f32 so they add no further rounding, and x, the + // gate and both multiplies stay f32 as in mm_activation_epilogue.cc. + aie::vector tanh_half = aie::tanh(half_l); + aie::accum tacc; + tacc.from_vector(tanh_half); + aie::vector t = tacc.to_vector(); + aie::vector sig = aie::mul(aie::add(t, onef), halff); + // aie::mul on f32 vectors yields an accumulator, so chain via explicit + // vector temporaries (as mm_activation_epilogue.cc does). + aie::vector ls = aie::mul(l, sig); + return aie::vector(aie::mul(ls, g)); +} + +extern "C" { + +void mm_swiglu_epilogue_f32(float *__restrict c) { + event0(); + static_assert(DIM_M % 4 == 0 && DIM_N % 16 == 0, + "sub-tiles are 4x8 and (l, g) pairs span two of them"); + for (int rb = 0; rb < DIM_M / 4; rb++) { + for (int cg = 0; cg < DIM_N / 8; cg += 2) { + float *__restrict pl = c + rb * (4 * DIM_N) + cg * 32; + float *__restrict pg = pl + 32; + for (int h = 0; h < 2; h++) { // 32 elements per sub-tile = 2 x 16 lanes + aie::vector l = aie::load_v<16>(pl + h * 16); + aie::vector g = aie::load_v<16>(pg + h * 16); + aie::store_v(pl + h * 16, swiglu16(l, g)); + } + } + } + event1(); +} + +} // extern "C" diff --git a/python/ryzenai_kernels/kernels/softmax_rows.cc b/python/ryzenai_kernels/kernels/softmax_rows.cc new file mode 100644 index 000000000..d52446c62 --- /dev/null +++ b/python/ryzenai_kernels/kernels/softmax_rows.cc @@ -0,0 +1,24 @@ +// softmax_rows.cc - multi-row bf16 softmax wrapper for AIE2P (Strix/npu2). +// +// Reuses the stock mlir-aie aie2p kernel (per-row softmax, vector width 32, +// aie::exp2 native exp) and loops it over the rows of one fifo element. +// Width must be a multiple of 32 (the design pads 361 -> 384 on the host; +// pad columns are -1e30 so exp() underflows to exactly 0 and the row sum is +// unaffected). +// +// Origin: written for the KataGo RyzenAI backend's attention softmax +// (rows = numHeads * S). Compiled per shape by build_softmax.py. + +#include "aie_kernels/aie2p/softmax.cc" + +extern "C" { + +void softmax_rows_bf16(bfloat16 *restrict input, bfloat16 *restrict output, + const int32_t n_rows, const int32_t width) { + for (int r = 0; r < n_rows; r++) { + softmax_simple_bf16(input + (size_t)r * width, + output + (size_t)r * width, width); + } +} + +} // extern "C" diff --git a/python/ryzenai_kernels/make_artifacts.py b/python/ryzenai_kernels/make_artifacts.py new file mode 100644 index 000000000..d104cde04 --- /dev/null +++ b/python/ryzenai_kernels/make_artifacts.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python3 +"""Generate the NPU artifacts a model needs, into cpp/external/ryzenai_artifacts. + +Everything the runtime loads is named by its shape, and the loader finds it by +that name alone, so generating for a new model is a matter of naming the shapes +it uses. This wraps the individual builders so that is one command. + + python make_artifacts.py --for-model 512 8 # trunk 512, 8 heads + python make_artifacts.py --for-model 768 0 # a convnet: no heads + python make_artifacts.py --gemm-grid # the K grid (slow) + python make_artifacts.py --list --for-model 512 8 # show, build nothing + +What a model needs: + + gemm one per K it reduces over, shared by every model - the shipped grid + already covers K up to 6912, so a new model normally needs none + bnmish convnets with Mish: one per (rows, channel count) + attn transformers: one per (heads, board points) + softmax transformers: one per (heads * points, points), both padded + swiglu transformers: one per FFN hidden width (--ffn-hidden) + +Run inside the mlir-aie iron environment with XRT on PATH: + + set PATH=C:\\Envs\\mlir-aie\\ironenv\\Lib\\site-packages\\mlir_aie\\bin;C:\\Xilinx\\XRT;%PATH% +""" + +import argparse +import shutil +import subprocess +import sys +import tempfile +from pathlib import Path + +HERE = Path(__file__).parent +ARTIFACTS = HERE.parent.parent / "cpp" / "external" / "ryzenai_artifacts" +OPS = ARTIFACTS / "ops" + +# Rows per dispatch that the C++ side knows about. bnmish picks per call among +# these (matmul.cpp Accel::kBnMishHeights), so all three want to exist for any +# channel count that carries real work. +BNMISH_ROWS = [384, 1536, 3072] + + +def pad(n, to): + return ((n + to - 1) // to) * to + + +def plan(trunk_c, heads, points): + """Artifacts for one model geometry, as (builder, args, output stem).""" + jobs = [] + # nbt convnets normalise on several widths, not just the trunk: the + # bottleneck is trunk/2 and the heads run narrower still. Covering the + # usual set costs a few minutes and saves a silent fallback later. + widths = sorted({trunk_c, trunk_c // 2, trunk_c // 4, 256, 384}) + for w in widths: + for rows in BNMISH_ROWS: + # Only the trunk-sized widths ever see batched rows worth the tall + # variants; the narrow head layers stay small. + if rows > 384 and w < trunk_c // 2: + continue + jobs.append(("build_bn_mish.py", + ["--rows", str(rows), "--width", str(w)], + f"bnmish_{rows}x{w}")) + if heads > 0: + s_pad = pad(points, 32) + # 12 heads exceed the shim's DMA channel budget one head per core, so + # those run two heads per core (see SKILL.md pit #18). + per_core = 2 if heads > 8 else 1 + jobs.append(("build_attention.py", + ["--heads", str(heads), "--s", str(points), + "--heads-per-core", str(per_core)], + f"attn_h{heads}_s{points}")) + jobs.append(("build_softmax.py", + ["--rows", str(pad(heads * points, 64)), "--width", str(s_pad)], + f"softmax_{pad(heads * points, 64)}x{s_pad}")) + return jobs + + +def run(jobs, list_only, force): + OPS.mkdir(parents=True, exist_ok=True) + todo = [j for j in jobs if force or not (OPS / (j[2] + ".xclbin")).exists()] + have = len(jobs) - len(todo) + print("%d artifact(s): %d already present, %d to build" % (len(jobs), have, len(todo))) + for _, _, stem in todo: + print(" " + stem) + if list_only or not todo: + return 0 + + failed = [] + for i, (script, args, stem) in enumerate(todo): + # Builders drop an aiecc .prj work directory beside their output, so + # build into scratch and move only the two files worth keeping. + with tempfile.TemporaryDirectory(prefix="ryzenai_op_") as work: + x, b = Path(work) / (stem + ".xclbin"), Path(work) / (stem + ".insts.bin") + cmd = [sys.executable, str(HERE / script)] + args + \ + ["--xclbin", str(x), "--insts", str(b)] + print("[%d/%d] %s" % (i + 1, len(todo), stem), flush=True) + if subprocess.call(cmd, cwd=str(HERE)) != 0 or not x.exists(): + print(" FAILED") + failed.append(stem) + continue + shutil.move(str(x), str(OPS / x.name)) + shutil.move(str(b), str(OPS / b.name)) + + print("\ndone: %d built, %d failed" % (len(todo) - len(failed), len(failed))) + for f in failed: + print(" failed: " + f) + return 1 if failed else 0 + + +def snapshot(): + return {p.relative_to(ARTIFACTS).as_posix() + for p in ARTIFACTS.rglob("*") + if p.suffix in (".xclbin", ".bin")} + + +def audit(before): + """Report where this run's artifacts landed, and that nothing else did. + + The builders write to three different places - ops/ for the fused ops, and + bf16|bfp16/_col[_swiglu]/ for the GEMM grids - so a per-directory + count is the only way to see that a run produced what was asked for. It also + catches an aiecc .prj work directory left inside the artifact tree, which + happened once and quietly added a few hundred files to the deployed build. + """ + after = snapshot() + added = sorted(after - before) + print("\nartifact tree: %d files (%d new this run)" % (len(after), len(added))) + by_dir = {} + for a in added: + by_dir.setdefault(a.rsplit("/", 1)[0] if "/" in a else ".", []).append(a) + for d in sorted(by_dir): + print(" %-44s %d" % (d + "/", len(by_dir[d]))) + strays = [p for p in ARTIFACTS.rglob("*.prj") if p.is_dir()] + if strays: + print("WARNING: aiecc work directories left in the artifact tree - delete these:") + for p in strays: + print(" " + p.relative_to(ARTIFACTS).as_posix()) + return 1 + return 0 + + +def main(): + ap = argparse.ArgumentParser( + description="Build NPU artifacts into cpp/external/ryzenai_artifacts/ops") + ap.add_argument("--for-model", nargs="+", metavar="N", type=int, + help="trunk channels, heads (0 for a convnet), " + "and optionally board points (default 361)") + ap.add_argument("--ffn-hidden", type=int, metavar="K", + help="FFN hidden width, for the SwiGLU epilogue GEMM. There is no reliable " + "formula for it (384->512 but 512->768 and 768->1152), so read it off " + "the model: run katago with ryzenaiShapeReport=true and take the N of " + "the ffn.linear1 row. Omitted means skip the SwiGLU artifacts.") + ap.add_argument("--gemm-grid", action="store_true", + help="rebuild the shared K grid instead (slow; see build_grid.py)") + ap.add_argument("--list", action="store_true", help="show the plan, build nothing") + ap.add_argument("--force", action="store_true", help="rebuild artifacts that exist") + args = ap.parse_args() + + before = snapshot() + + if args.gemm_grid: + rc = subprocess.call( + [sys.executable, str(HERE / "build_grid.py"), "--arch", "npu2", + "--dtype", "bf16", "--dtype", "bfp16"], cwd=str(HERE)) + return audit(before) or rc + + if not args.for_model: + ap.error("give --for-model TRUNK HEADS [POINTS], or --gemm-grid") + trunk = args.for_model[0] + heads = args.for_model[1] if len(args.for_model) > 1 else 0 + points = args.for_model[2] if len(args.for_model) > 2 else 361 + print("model: trunk %d, %d head(s), %d board points" % (trunk, heads, points)) + rc = run(plan(trunk, heads, points), args.list, args.force) + + # The SwiGLU epilogue variants live under bf16/_col_swiglu/ rather than ops/, and + # build_swiglu_grid.py already puts them there and skips what exists, so hand off to it. + if heads > 0 and args.ffn_hidden: + print("\nSwiGLU epilogue GEMM for FFN hidden %d" % args.ffn_hidden) + cmd = [sys.executable, str(HERE / "build_swiglu_grid.py"), "--k", str(args.ffn_hidden)] + if args.list: + print(" would run: " + " ".join(cmd[1:])) + else: + rc = subprocess.call(cmd, cwd=str(HERE)) or rc + elif heads > 0: + print("\nNote: --ffn-hidden not given, so no SwiGLU epilogue artifact was considered.\n" + " Without one the FFN still runs, just without the fused activation.") + + if not args.list: + rc = audit(before) or rc + return rc + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/python/ryzenai_kernels/parse_insts.py b/python/ryzenai_kernels/parse_insts.py new file mode 100644 index 000000000..b152746cf --- /dev/null +++ b/python/ryzenai_kernels/parse_insts.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +# parse_insts.py -- decode KataGo ryzenai golden .insts.bin (TXN control code) +# Field layouts follow FastFlowLM npu_utils/instr_utils/*.hpp (MIT). +import json, struct, sys, os +from pathlib import Path + +ROOT = Path(r"c:\Users\lizel\OneDrive\Desktop\Codes\Github\KataGo-Multi-backends") +ART = ROOT / "cpp/neuralnet/ryzenai/artifacts" + +OP = { + 0: "WRITE32", + 1: "BLOCKWRITE", + 3: "MASKWRITE", + 6: "PREEMPT", + 0x80: "WAIT_TCT", + 0x81: "DDR_PATCH", +} + +def u32s(data): + return list(struct.unpack("<%dI" % (len(data)//4), data)) + +def decode(words, verbose=True): + out = [] + w0, w1, ncmd, nbytes = words[0], words[1], words[2], words[3] + hdr = dict(n_rows=w0>>24, gen=(w0>>16)&0xFF, minor=(w0>>8)&0xFF, major=w0&0xFF, + mem_tile_rows=(w1>>8)&0xFF, num_cols=w1&0xFF, n_cmds=ncmd, n_bytes=nbytes) + out.append(f"HDR rows={hdr['n_rows']} gen={hdr['gen']} minor={hdr['minor']} major={hdr['major']} " + f"mem_tile_rows={hdr['mem_tile_rows']} num_cols={hdr['num_cols']} n_cmds={ncmd} n_bytes={nbytes}") + i = 4 + cmd_idx = 0 + while i < len(words): + op = words[i] + if op == 1: # BLOCKWRITE: 12 words + bd = words[i:i+12] + loc = bd[2] + col = (loc>>25)&0x7F; row=(loc>>20)&0x1F; bd_id=(loc>>5)&0xF; addr = loc & 0x1FFFF + opsize = bd[3]>>2 + buflen = bd[4]; bufoff = bd[5] + pkt = bd[6] + en_pkt = (pkt>>30)&1; ooo=(pkt>>24)&0x3F; pkt_id=(pkt>>19)&0x1F; pkt_ty=(pkt>>16)&7 + d0 = bd[7]; d1 = bd[8]; d2 = bd[9]; it = bd[10]; nb = bd[11] + is_lin = (d0 == 0) + d0s = (d0>>20)&0x3FF; d0st = (d0 & 0xFFFFF)+1 + d1s = (d1>>20)&0x3FF; d1st = (d1 & 0xFFFFF)+1 + d2st = (d2 & 0xFFFFF)+1; cache=(d2>>24)&0xF + its = ((it>>20)&0x3FF)+1; itst = (it & 0xFFFFF)+1 + nextbd=(nb>>27)&0xF; use_next=(nb>>26)&1; valid=(nb>>25)&1 + relval=(nb>>18)&0xFF; relid=(nb>>13)&0xF; acqen=(nb>>12)&1; acqval=(nb>>5)&0x7F; acqid=nb&0xF + d2s = buflen//(d0s*d1s) if (not is_lin and d0s*d1s) else 0 + out.append(f"[{cmd_idx:3d}@{i:4d}] BLOCKWRITE col={col} row={row} bd={bd_id} addr=0x{addr:x} opsz={opsize} " + f"len={buflen} bufoff={bufoff} pkt(en={en_pkt},ooo={ooo},id={pkt_id},ty={pkt_ty}) " + f"D0=({d0s},{d0st}) D1=({d1s},{d1st}) D2=({d2s},{d2st}) iter=({its},{itst}) cache={cache} " + f"next={nextbd} use_next={use_next} valid={valid} lock(rel={relval},{relid};acq={acqen},{acqval},{acqid})") + i += 12 + elif op == 0x81: # DDR_PATCH: 12 words + bd = words[i:i+12] + opsize = bd[1]>>2 + loc = bd[6] + col=(loc>>25)&0x7F; row=(loc>>20)&0x1F; bd_id=((loc-0x04)>>5)&0x1F; addr=loc&0x1FFFF + arg_idx = bd[8]; arg_off = bd[10] + out.append(f"[{cmd_idx:3d}@{i:4d}] DDR_PATCH col={col} row={row} bd={bd_id} addr=0x{addr:x} arg_idx={arg_idx} arg_off={arg_off}") + i += 12 + elif op == 0: # WRITE32: 6 words + bd = words[i:i+6] + loc = bd[2] + col=(loc>>25)&0x7F; row=(loc>>20)&0x1F; addr=loc&0xFFFFF + val = bd[4] + is_queue = (addr & 0x1FE00) == 0x1d200 + if is_queue: + ch = (loc>>3)&1; direction = "MM2S" if (addr&0x10) else "S2MM" + rep = (val>>16)&0xFF; itok=(val>>31)&1; bid=val&0xF + out.append(f"[{cmd_idx:3d}@{i:4d}] QUEUE_PUSH col={col} row={row} {direction} ch={ch} bd={bid} repeat={rep} issue_token={itok}") + else: + out.append(f"[{cmd_idx:3d}@{i:4d}] WRITE32 col={col} row={row} addr=0x{addr:05x} val=0x{val:08x}") + i += 6 + elif op == 3: # MASKWRITE: 7 words + bd = words[i:i+7] + loc = bd[2] + col=(loc>>25)&0x7F; row=(loc>>20)&0x1F; addr=loc&0xFFFFF + val=bd[4]; mask=bd[5] + # issue-token form: addr 0x1D2xx + if (addr & 0x1FE00) == 0x1d200: + ch=(loc>>3)&1; direction = "MM2S" if (addr&0x10) else "S2MM" + pktid = val>>8 + out.append(f"[{cmd_idx:3d}@{i:4d}] ISSUE_TOKEN col={col} row={row} {direction} ch={ch} pkt_id={pktid} mask=0x{mask:x}") + else: + out.append(f"[{cmd_idx:3d}@{i:4d}] MASKWRITE col={col} row={row} addr=0x{addr:05x} val=0x{val:08x} mask=0x{mask:08x}") + i += 7 + elif op == 0x80: # WAIT_TCT: 4 words + bd = words[i:i+4] + opsize=bd[1]>>2 + x=bd[2]; y=bd[3] + direction = "MM2S" if (x&1) else "S2MM" + row=(x>>8)&0xFF; col=(x>>16)&0xFF; ch=(y>>24)&0xFF + out.append(f"[{cmd_idx:3d}@{i:4d}] WAIT_TCT col={col} row={row} {direction} ch={ch} (w3=0x{y:x})") + i += 4 + elif op == 6: + out.append(f"[{cmd_idx:3d}@{i:4d}] PREEMPT level={(words[i]>>8)&3}") + i += 1 + else: + out.append(f"[{cmd_idx:3d}@{i:4d}] UNKNOWN op=0x{op:x} words={['%08x'%w for w in words[i:i+4]]}") + i += 1 + cmd_idx += 1 + return hdr, out + +def main(): + manifest = json.loads((ART/"manifest.json").read_text()) + seen = {} + for a in manifest["artifacts"]: + p = ART / a["insts"] + key = (a["arch"], a["n_aie_cols"], a["M"], a["K"], a["N"]) + if key in seen: + continue + seen[key] = True + data = p.read_bytes() + words = u32s(data) + hdr, lines = decode(words) + tag = f"{a['arch']}_{a['n_aie_cols']}col M{a['M']}K{a['K']}N{a['N']} tile={a['tile']['m']}x{a['tile']['k']}x{a['tile']['n']}" + print("="*100) + print(f"{p.relative_to(ART)} {tag}") + print("="*100) + for l in lines: + print(l) + +if __name__ == "__main__": + main() diff --git a/python/ryzenai_kernels/setup_env.ps1 b/python/ryzenai_kernels/setup_env.ps1 new file mode 100644 index 000000000..85a0e3e24 --- /dev/null +++ b/python/ryzenai_kernels/setup_env.ps1 @@ -0,0 +1,231 @@ +<# +.SYNOPSIS +Set up the mlir-aie ("IRON") toolchain that make_artifacts.py needs. + +.DESCRIPTION +Only kernel authors need this. Building katago needs nothing from here, and +running it needs nothing at all beyond the NPU driver - the .xclbin kernels are +committed to this repository. This is for regenerating them. + +The toolchain is a git checkout, not just a set of wheels: the GEMM generators +compile against kernel sources that live in the repository's aie_kernels tree +and are not part of any wheel. So this clones mlir-aie and runs the installer +that ships inside it (utils/iron_setup.py), which builds the virtual +environment and writes the iron_env activation scripts. Doing it that way means +the environment always matches whatever that checkout expects, rather than a +second guess maintained here. + +What it does, in order: + + 1. Checks the prerequisites (git, Python, the MSVC C++ toolchain, XRT) and + stops with an explanation if one is missing. It never installs any of them. + 2. Clones mlir-aie into -Prefix, or reuses the checkout already there. + 3. Runs its utils/iron_setup.py to create the environment. + 4. Writes activate_iron.bat next to this script, which enters that + environment from anywhere. + 5. Verifies: aie.iron imports, the aie_kernels tree the GEMM generators need + is present, and make_artifacts.py runs. + +Nothing is cloned or installed unless -Execute is passed. Without it the script +only checks prerequisites and prints what it would do, so several gigabytes are +never fetched by surprise. + +.PARAMETER Prefix +Where to put the mlir-aie checkout and its environment. Required, deliberately: +this is a multi-gigabyte tree and where it belongs is your call. + +.PARAMETER Ref +Git ref (branch, tag or commit) to check out. Defaults to the default branch. + +.PARAMETER Execute +Actually clone and install. Without this the script only reports. + +.EXAMPLE +.\setup_env.ps1 -Prefix C:\Envs\mlir-aie +Report what would be done, changing nothing. + +.EXAMPLE +.\setup_env.ps1 -Prefix C:\Envs\mlir-aie -Execute +Clone and install for real. +#> +[CmdletBinding()] +param( + [string]$Prefix, + [string]$Ref, + [switch]$Execute +) + +$ErrorActionPreference = "Stop" +$Here = Split-Path -Parent $MyInvocation.MyCommand.Path +$RepoUrl = "https://github.com/Xilinx/mlir-aie.git" + +function Fail($msg) { Write-Host "ERROR: $msg" -ForegroundColor Red; exit 1 } +function Step($msg) { Write-Host "`n== $msg" -ForegroundColor Cyan } +function Note($msg) { Write-Host " $msg" } + +if (-not $Prefix) { + Write-Host @" +ERROR: -Prefix is required. + +Give the directory to put the mlir-aie checkout and its environment in. It is +not defaulted because it is a multi-gigabyte tree and where that belongs is your +call, not this script's. + + .\setup_env.ps1 -Prefix C:\Envs\mlir-aie # report only + .\setup_env.ps1 -Prefix C:\Envs\mlir-aie -Execute # actually install + .\setup_env.ps1 -Prefix D:\tools\mlir-aie -Execute # anywhere else + +See Compiling.md, "Regenerating the NPU kernels", for the full flow. +"@ -ForegroundColor Red + exit 1 +} + +# ---- 1. prerequisites, checked but never installed -------------------------- + +Step "Checking prerequisites" + +if (-not (Get-Command git -ErrorAction SilentlyContinue)) { + Fail "git is not on PATH. The toolchain is a git checkout, not just wheels." +} +Note "git present" + +$py = Get-Command python -ErrorAction SilentlyContinue +if (-not $py) { Fail "python is not on PATH. Install Python 3.10 or newer." } +$pyver = (& python -c "import sys;print('%d.%d'%sys.version_info[:2])").Trim() +if ([version]$pyver -lt [version]"3.10") { + Fail "python $pyver is too old; mlir-aie needs 3.10 or newer. The one on PATH is $($py.Source)." +} +Note "python $pyver at $($py.Source)" + +# vswhere sits at a documented fixed location under Program Files, so this +# neither hardcodes an edition nor a version. +$vswhere = $null +foreach ($pf in @(${env:ProgramFiles(x86)}, $env:ProgramFiles)) { + if ($pf) { + $cand = Join-Path $pf "Microsoft Visual Studio\Installer\vswhere.exe" + if (Test-Path $cand) { $vswhere = $cand; break } + } +} +if (-not $vswhere) { + Fail "vswhere.exe not found. Install Visual Studio Build Tools with the 'Desktop development with C++' workload - the kernel compiler shells out to cl.exe." +} +$vsPath = & $vswhere -all -sort -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath | Select-Object -First 1 +if (-not $vsPath) { Fail "No Visual Studio C++ toolchain found. Install the 'Desktop development with C++' workload." } +Note "MSVC toolchain at $vsPath" + +# XRT: probe for xclbinutil.exe rather than for a bin\ directory - the Windows +# SDK puts its tools straight in the install root, and xclbinutil is the one +# thing aiecc actually shells out to. +$xrtRoot = $null +foreach ($cand in @($env:XRT_ROOT, $env:XILINX_XRT, "C:\Xilinx\XRT")) { + if (-not $cand) { continue } + foreach ($sub in @("", "bin")) { + $dir = if ($sub) { Join-Path $cand $sub } else { $cand } + if (Test-Path (Join-Path $dir "xclbinutil.exe")) { $xrtRoot = $cand; break } + } + if ($xrtRoot) { break } +} +if (-not $xrtRoot) { + Fail "xclbinutil.exe not found. Install AMD's XRT for Windows and either set XRT_ROOT to it or accept the default C:\Xilinx\XRT - aiecc shells out to xclbinutil to package each .xclbin." +} +Note "XRT at $xrtRoot" + +# ---- the plan --------------------------------------------------------------- + +$activateBat = Join-Path $Here "activate_iron.bat" +$ironPs1 = Join-Path $Prefix "iron_env.ps1" +$cloneArgs = if ($Ref) { "clone $RepoUrl `"$Prefix`" && git -C `"$Prefix`" checkout $Ref" } else { "clone $RepoUrl `"$Prefix`"" } + +Step "Plan" +Note "checkout : $Prefix (from $RepoUrl$(if ($Ref) { ", ref $Ref" }))" +Note "installer : $Prefix\utils\iron_setup.py --xrt-root `"$xrtRoot`"" +Note "activator : $activateBat -> $ironPs1" +if (Test-Path (Join-Path $Prefix ".git")) { Note "note : a checkout already exists there and will be reused, not re-cloned" } + +if (-not $Execute) { + Write-Host "`nDry run - nothing was cloned or installed. Re-run with -Execute to proceed." -ForegroundColor Yellow + Write-Host "The checkout plus its environment is several gigabytes." -ForegroundColor Yellow + exit 0 +} + +# ---- 2. the checkout -------------------------------------------------------- + +Step "Getting mlir-aie" +if (Test-Path (Join-Path $Prefix ".git")) { + Note "reusing the checkout already at $Prefix" + if ($Ref) { + & git -C $Prefix fetch --all --quiet + & git -C $Prefix checkout $Ref + if ($LASTEXITCODE -ne 0) { Fail "could not check out $Ref." } + } +} else { + if ((Test-Path $Prefix) -and (Get-ChildItem $Prefix -Force | Select-Object -First 1)) { + Fail "$Prefix exists and is not empty, but is not a git checkout. Point -Prefix somewhere else, or clear it." + } + & git clone $RepoUrl $Prefix + if ($LASTEXITCODE -ne 0) { Fail "git clone failed." } + if ($Ref) { + & git -C $Prefix checkout $Ref + if ($LASTEXITCODE -ne 0) { Fail "could not check out $Ref." } + } +} +Note ("at commit " + (& git -C $Prefix rev-parse --short HEAD)) + +# ---- 3. its own installer --------------------------------------------------- + +Step "Running the checkout's own installer (utils/iron_setup.py)" +Push-Location $Prefix +try { + & python (Join-Path $Prefix "utils\iron_setup.py") --xrt-root $xrtRoot + if ($LASTEXITCODE -ne 0) { Fail "iron_setup.py failed. See its output above." } +} finally { + Pop-Location +} +if (-not (Test-Path $ironPs1)) { + Fail "iron_setup.py finished but did not write $ironPs1. The checkout's layout may have changed." +} + +# ---- 4. the activator ------------------------------------------------------- + +Step "Writing $activateBat" +$ironCmd = Join-Path $Prefix "iron_env.cmd" +if (-not (Test-Path $ironCmd)) { Fail "expected $ironCmd from iron_setup.py, but it is not there." } +@" +@echo off +rem Generated by setup_env.ps1. Enters the mlir-aie environment so that +rem make_artifacts.py can run: +rem +rem activate_iron.bat +rem python make_artifacts.py --for-model 512 8 --ffn-hidden 768 +rem +rem The real work is done by the checkout's own iron_env.cmd, which sets +rem MLIR_AIE_INSTALL_DIR, PEANO_INSTALL_DIR, XRT_ROOT and the rest. +call "$ironCmd" +"@ | Set-Content -Path $activateBat -Encoding ascii +Note "written" + +# ---- 5. verify -------------------------------------------------------------- + +Step "Verifying" +$venvPy = Join-Path $Prefix "ironenv\Scripts\python.exe" +if (-not (Test-Path $venvPy)) { Fail "no interpreter at $venvPy." } + +& $venvPy -c "import aie.iron; print(' aie.iron imports OK')" +if ($LASTEXITCODE -ne 0) { Fail "the environment installed but 'import aie.iron' fails." } + +# The GEMM generators compile against kernel sources from the checkout, not from +# any wheel, so a wheel-only environment would pass the import above and then +# fail at the first build. +$kernels = Join-Path $Prefix "aie_kernels\aie2p" +if (-not (Test-Path $kernels)) { + Fail "$kernels is missing. The GEMM generators need the checkout's kernel sources; a wheels-only install is not enough." +} +Note "aie_kernels\aie2p present" + +& $venvPy (Join-Path $Here "make_artifacts.py") --list --for-model 384 6 +if ($LASTEXITCODE -ne 0) { Fail "make_artifacts.py could not run." } + +Write-Host "`nDone. Use it with:" -ForegroundColor Green +Write-Host " cd `"$Here`"" +Write-Host " activate_iron.bat" +Write-Host " python make_artifacts.py --for-model [points] [--ffn-hidden K]"