Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
1e919aa
feat(hipdnn): add persistent graph UUIDs
SamuelReeder Aug 5, 2026
d501d14
refactor(hipdnn): use CRT for Windows UUID RNG
SamuelReeder Aug 5, 2026
d8ee796
docs(hipdnn): update UUID standard wording
SamuelReeder Aug 5, 2026
df810d2
fix(hipdnn): treat graph IDs as opaque values
SamuelReeder Aug 5, 2026
5a99a2c
docs(hipdnn): clarify graph ID contract
SamuelReeder Aug 5, 2026
950e320
Merge remote-tracking branch 'origin/develop' into users/sareeder/gra…
SamuelReeder Aug 5, 2026
a4c9c40
fix(hipdnn): keep finalized graph identity immutable
SamuelReeder Aug 5, 2026
9cc9a89
fix(hipdnn): preserve graph dump content deduplication
SamuelReeder Aug 6, 2026
b3d438c
fix(hipdnn): mark graph log size unused
SamuelReeder Aug 6, 2026
783ceb6
refactor(hipdnn): name graph dumps by graph ID
SamuelReeder Aug 10, 2026
0726545
fix(hipdnn): require graph identity for graph dumps
SamuelReeder Aug 10, 2026
378ec3d
test(hipdnn): assert JSON export carries graph id
SamuelReeder Aug 10, 2026
7dd1a50
test(hipdnn): assert graph dumps require an id
SamuelReeder Aug 10, 2026
d112f8b
feat(hipdnn): report graph id in descriptor text
SamuelReeder Aug 10, 2026
fe743e9
test(hipdnn): split Uuid.hpp tests into their own file
SamuelReeder Aug 11, 2026
c581886
feat(hipdnn): add generic kernel ingestor skeleton (ALMIOPEN-2402)
BrianHarrisonAMD Aug 10, 2026
b8f33a9
fix(hipdnn): key ingestor catalogs on the calling handle's device (AL…
BrianHarrisonAMD Aug 10, 2026
93ccd23
refactor(hipdnn): name the kernel ingestor as the foundation it is (A…
BrianHarrisonAMD Aug 10, 2026
d788929
refactor(hipdnn): tighten the ingestor descriptor types from PR revie…
BrianHarrisonAMD Aug 11, 2026
3c9098d
fix(hipdnn): conform the kernel ingestor to RFC 0017's matching and c…
BrianHarrisonAMD Aug 11, 2026
f1a3d6d
feat(hipdnn): defer heuristic loading and report the UED's behavior n…
BrianHarrisonAMD Aug 11, 2026
b81a756
feat(hipdnn): cache the bound token state and scope the catalog to on…
BrianHarrisonAMD Aug 11, 2026
57c3755
ci(hipdnn): enable the kernel ingestor in the superbuild CI (ALMIOPEN…
BrianHarrisonAMD Aug 11, 2026
180cb28
refactor(hipdnn): make a new ingestor op four functions plus data (AL…
BrianHarrisonAMD Aug 11, 2026
a31904e
test(hipdnn): one test file per ingestor source, happy and unhappy (A…
BrianHarrisonAMD Aug 11, 2026
77f50fa
test(hipdnn): drop an unused ingestor test double (ALMIOPEN-2402)
BrianHarrisonAMD Aug 11, 2026
2921936
fix(hipdnn): close four defects the ingestor review proved (ALMIOPEN-…
BrianHarrisonAMD Aug 12, 2026
39bfb2a
feat(hipdnn): unify the bound-token value type and log why matching d…
BrianHarrisonAMD Aug 12, 2026
4e0e303
fix(hipdnn): fail closed on collisions and cover what the tests misse…
BrianHarrisonAMD Aug 12, 2026
0632347
docs(hipdnn): cut the argument out of the ingestor's comments (ALMIOP…
BrianHarrisonAMD Aug 12, 2026
4576b09
docs(hipdnn): minimize comments across the ingestor skeleton (ALMIOPE…
BrianHarrisonAMD Aug 12, 2026
606c5c7
First pass of RFC
DarylHawkinsAMD Jul 23, 2026
dd6c3b0
More updates to RFC
DarylHawkinsAMD Jul 23, 2026
7f48188
First implementation of JsonLogic
DarylHawkinsAMD Jul 23, 2026
998ff1a
Refactor JsonLogic Value API and namespace naming
DarylHawkinsAMD Jul 23, 2026
f010f16
Add nlohmann::json-backed JsonLogic data source with getData/setData
DarylHawkinsAMD Jul 23, 2026
4b48130
Flesh out RFC 0018 schema and annotate SDPA UMD bindings
DarylHawkinsAMD Jul 24, 2026
f5c9f80
Added plan
DarylHawkinsAMD Jul 24, 2026
3445c14
Add UMD op-schema registry codegen from FlatBuffers annotations
DarylHawkinsAMD Jul 24, 2026
4e8bb7b
Lowercase SDPA q/k/v/o UMD role names
DarylHawkinsAMD Jul 24, 2026
87b478d
Rename UMD tensor annotations and bindings to input/output tensor ter…
DarylHawkinsAMD Jul 24, 2026
96f460a
Comment each generated op namespace with its source fbs table name
DarylHawkinsAMD Jul 24, 2026
f5b566e
Rename binding 'role' field to 'name' in op-schema registry
DarylHawkinsAMD Jul 24, 2026
22940fe
Rename 'role' to 'name' in RFC 0018 and PoC plan
DarylHawkinsAMD Jul 24, 2026
97386b9
Store NodeAttributes enum value in OpSchemaEntry instead of int
DarylHawkinsAMD Jul 24, 2026
be392ce
Skip generated umd registry header in clang-tidy and fix hand-written…
DarylHawkinsAMD Jul 24, 2026
71265b3
Implement RFC 0018 UMD Phase 1: bindings, compiler, matcher
DarylHawkinsAMD Jul 24, 2026
486228c
Add $kernel metadata namespace to UMD graph matcher
DarylHawkinsAMD Jul 24, 2026
7fb91f3
ci(hipdnn): guard UMD op-schema registry against schema drift
DarylHawkinsAMD Aug 4, 2026
a65762d
docs(hipdnn): move UMD PoC plan under projects/hipdnn/docs/rfcs
DarylHawkinsAMD Aug 4, 2026
dcf0fac
docs(rfc-0018): align UMD spec with RFC 0017 review updates
DarylHawkinsAMD Aug 4, 2026
af0b51a
feat(hip-kernel-provider): conform the UMD matcher to RFC 0017
DarylHawkinsAMD Aug 4, 2026
f82fbdb
fix(hip-kernel-provider): fail closed on absent operands; correct ver…
DarylHawkinsAMD Aug 4, 2026
df12e7d
docs(rfc-0018): correct version gating, fail-closed rule, and layout …
DarylHawkinsAMD Aug 4, 2026
b15b5f6
refactor(umd): adopt RFC 0017's stride-order convention
DarylHawkinsAMD Aug 4, 2026
301a769
fix(hip-kernel-provider): unbreak the Windows and Linux superbuilds
DarylHawkinsAMD Aug 4, 2026
584b8e4
test(hipdnn): conform new UMD suite names to the naming convention
DarylHawkinsAMD Aug 4, 2026
09d825b
chore(umd): regenerate op-schema registry for the new graph ops
DarylHawkinsAMD Aug 6, 2026
bf1626c
fix(hip-kernel-provider): spell the SdpaPlanUtils include from an inc…
DarylHawkinsAMD Aug 6, 2026
78d07b4
refactor(umd): move the escape hatch out of the expression language
DarylHawkinsAMD Aug 12, 2026
a900ec6
refactor(umd): carry a compiled UMD's id as UUID bytes
DarylHawkinsAMD Aug 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/hipdnn-superbuild-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ jobs:
-DROCM_LIBS_ENABLE_ROOT_CTEST=ON \
-DENABLE_CLANG_FORMAT=OFF \
-DHIPKERNELPROVIDER_ENABLE_ROCKE=ON \
-DHIPDNN_ENABLE_KERNEL_INGESTOR=ON \
-DENABLE_CLANG_TIDY=OFF

- name: Build
Expand Down Expand Up @@ -280,11 +281,26 @@ jobs:
-DENABLE_CLANG_FORMAT=OFF \
-DENABLE_CLANG_TIDY=ON \
-DHIPKERNELPROVIDER_ENABLE_ROCKE=ON \
-DHIPDNN_ENABLE_KERNEL_INGESTOR=ON \
-DCMAKE_CXX_CLANG_TIDY=/usr/bin/clang-tidy-20

- name: Build
run: cmake --build build

- name: Verify UMD op-schema registry is in sync
# The build regenerates op_schema_registry_generated.hpp in-tree from the
# .fbs schemas (HIPDNN_GENERATE_SDK_HEADERS defaults ON). The pre-commit
# flatc-hipdnn hook only refreshes the --cpp data-object headers, not this
# registry, so a schema change committed via pre-commit can leave the
# committed registry stale. This step is the authoritative drift guard.
run: |
if ! git diff --exit-code -- \
projects/hipdnn/flatbuffers_sdk/include/hipdnn_flatbuffers_sdk/umd/op_schema_registry_generated.hpp; then
echo "::error::UMD op-schema registry is stale: a schema change was committed without regenerating op_schema_registry_generated.hpp."
echo "Rebuild hipDNN with -DHIPDNN_GENERATE_SDK_HEADERS=ON (the default) and commit the regenerated header."
exit 1
fi

- name: Run tests
run: ctest --test-dir build --output-on-failure

Expand Down
11 changes: 10 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ exclude: |
\.github/workflows/.*\.lock\.yml$|
# Binary files
projects/hipdnn/.*\.bin$|
# Generated hipDNN FlatBuffers headers
# Generated hipDNN FlatBuffers headers (flatc output)
projects/hipdnn/flatbuffers_sdk/include/hipdnn_flatbuffers_sdk/data_objects/.*_generated\.h|
# umd_registry_gen-derived op-schema registry (keep OpSchemaRegistry.hpp formatted)
projects/hipdnn/flatbuffers_sdk/include/hipdnn_flatbuffers_sdk/umd/.*_generated\.hpp|
# Reference data (auto-generated)
dnn-providers/integration-tests/integration-test-bundles/.*|
# Generated files (see rocrand/tools/ _generator.cpp files)
Expand Down Expand Up @@ -93,6 +95,13 @@ repos:

- repo: local
hooks:
# Regenerates only the --cpp data-object headers (data_objects/*_generated.h)
# from the edited .fbs schemas. The UMD op-schema registry
# (umd/op_schema_registry_generated.hpp) is NOT refreshed here: it is derived
# from a C++ tool (umd_registry_gen) that must be compiled, which the
# pre-commit environment cannot do. That header is regenerated by the CMake
# build (HIPDNN_GENERATE_SDK_HEADERS, default ON) and enforced in CI by the
# "Verify UMD op-schema registry is in sync" step in hipdnn-superbuild-ci.yml.
- id: flatc-hipdnn
name: flatc (hipDNN)
entry: python projects/hipdnn/scripts/run_flatc.py
Expand Down
4 changes: 4 additions & 0 deletions dnn-providers/hip-kernel-provider/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ option(HIPKERNELPROVIDER_ENABLE_ROCKE "Build rocKE engine and smoke tests" OFF)
option(ENABLE_ASM_SDPA_ENGINE "Build the ASM SDPA engine" ON)
option(ENABLE_HIP_MLOPS_ENGINE "Build the HIP kernel engine" ON)

# Gates the generic kernel ingestor (RFC 0017). The ingestor engine compiles its kernel
# through the HIP kernel engine's compiler, so it only builds alongside that engine.
option(HIPDNN_ENABLE_KERNEL_INGESTOR "Build the generic kernel ingestor (RFC 0017)" OFF)

option(BUILD_ADDRESS_SANITIZER "Build with Address Sanitizer enabled" OFF)
option(ENABLE_CLANG_FORMAT "Enable Clang-Format checks" ON)
if(WIN32)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,310 @@
// Copyright © Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier: MIT

#pragma once

// JsonDataSource.hpp - a sample JsonLogic data source backed by nlohmann::json.
//
// All names below live in namespace hip_kernel_provider_common::jsonlogic;
// these examples assume `namespace jlogic = hip_kernel_provider_common::jsonlogic;`.
//
// JsonDataSource wraps an nlohmann::json document and satisfies the JsonLogic
// data-source contract (Value getData(const std::string&) const), so a compiled
// jlogic::Expression can evaluate directly against a JSON document:
//
// jlogic::JsonDataSource src(nlohmann::json{{"q", {{"dims", {8, 16}}}}});
// auto expr = jlogic::compile<jlogic::JsonDataSource>(rule);
// jlogic::Value r = expr(src);
//
// It also offers the inverse, setData, which writes a jlogic::Value back into
// the document at a path, creating intermediate objects and arrays as needed:
//
// src.setData("$q.dims[0]", 2); // -> {"q":{"dims":[2, 16]}}
//
// Path syntax (shared by getData and setData):
// - dotted keys: a.b.c
// - [N] array subscripts: arr[0], rows[2].name, grid[0][1]
// - dot-form array indices: arr.1 (resolves as an index only against an
// existing array; use arr[1] to force array creation)
// - an optional leading variable sigil ('$' by default) is stripped, so both
// "q.dims[0]" and "$q.dims[0]" address the same location
// - the empty path (or a bare sigil) addresses the whole document
//
// getData follows the JsonLogic convention: an unresolved path reads as null
// (Value()). setData is a mutation and reports a malformed path or an
// incompatible index by throwing std::invalid_argument.
//
// This is a *sample* accessor: objects and null in the document convert to
// jlogic::Value null (Value has no object alternative), matching Value's
// scalar/array-only model.

#include "hip_kernel_provider_common/JsonLogic.hpp"

#include <nlohmann/json.hpp>

#include <cstddef>
#include <cstdlib>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>

namespace hip_kernel_provider_common::jsonlogic
{
class JsonDataSource
{
public:
JsonDataSource() = default;
explicit JsonDataSource(nlohmann::json doc, char sigil = '$')
: _doc(std::move(doc))
, _sigil(sigil)
{
}

/// The backing document, for inspection or bulk replacement.
const nlohmann::json& document() const
{
return _doc;
}
nlohmann::json& document()
{
return _doc;
}

/// JsonLogic data-source contract: resolve a variable path to a Value.
/// An empty path returns the whole document; an unresolved path (missing
/// key, out-of-range or non-numeric index, subscript on a non-array)
/// returns null so a `var` default, if any, takes over.
Value getData(const std::string& path) const
{
std::vector<Segment> segs;
if(!tokenize(path, _sigil, segs))
{
return {}; // malformed subscript -> not found
}
const nlohmann::json* cur = &_doc;
for(const auto& seg : segs)
{
if(seg.subscript || cur->is_array())
{
if(!cur->is_array())
{
return {}; // subscript on a non-array
}
std::size_t idx = 0;
if(!parseIndex(seg.text, idx) || idx >= cur->size())
{
return {};
}
cur = &(*cur)[idx];
}
else if(cur->is_object())
{
const auto it = cur->find(seg.text);
if(it == cur->end())
{
return {};
}
cur = &*it;
}
else
{
return {};
}
}
return toValue(*cur);
}

/// Write a Value into the document at a path, creating intermediate
/// containers as needed: a `[N]` subscript (or a dot-form index against an
/// existing array) grows an array, filling gaps with null; any other key
/// creates or descends into an object. An empty path replaces the whole
/// document. Throws std::invalid_argument on a malformed path or a
/// non-numeric index applied to an array.
void setData(const std::string& path, const Value& value)
{
std::vector<Segment> segs;
if(!tokenize(path, _sigil, segs))
{
throw std::invalid_argument("JsonDataSource::setData: malformed path '" + path + "'");
}
if(segs.empty())
{
_doc = toJson(value); // whole-document assignment
return;
}
nlohmann::json* cur = &_doc;
for(std::size_t i = 0; i < segs.size(); ++i)
{
const Segment& seg = segs[i];
nlohmann::json* target = nullptr;
if(seg.subscript)
{
std::size_t idx = 0;
if(!parseIndex(seg.text, idx))
{
throw std::invalid_argument("JsonDataSource::setData: bad array index '"
+ seg.text + "' in path '" + path + "'");
}
if(!cur->is_array())
{
*cur = nlohmann::json::array();
}
target = &(*cur)[idx]; // grows the array, filling gaps with null
}
else if(cur->is_array())
{
std::size_t idx = 0;
if(!parseIndex(seg.text, idx))
{
throw std::invalid_argument("JsonDataSource::setData: non-numeric key '"
+ seg.text + "' on array in path '" + path + "'");
}
target = &(*cur)[idx];
}
else
{
if(!cur->is_object())
{
*cur = nlohmann::json::object();
}
target = &(*cur)[seg.text];
}
if(i + 1 == segs.size())
{
*target = toJson(value);
}
else
{
cur = target;
}
}
}

private:
struct Segment
{
bool subscript; // true for [N] forms, false for dotted/leading keys
std::string text;
};

/// Split a path into segments. Strips one optional leading sigil. Returns
/// false on a malformed subscript (missing ']').
static bool tokenize(const std::string& raw, char sigil, std::vector<Segment>& out)
{
std::size_t pos = 0;
if(!raw.empty() && raw[0] == sigil)
{
++pos; // strip the variable sigil
}
while(pos < raw.size())
{
if(raw[pos] == '[')
{
const std::size_t close = raw.find(']', pos + 1);
if(close == std::string::npos)
{
return false;
}
out.push_back({true, raw.substr(pos + 1, close - pos - 1)});
pos = close + 1;
}
else
{
if(raw[pos] == '.')
{
++pos; // skip the key separator
}
const std::size_t next = raw.find_first_of(".[", pos);
const std::size_t end = (next == std::string::npos) ? raw.size() : next;
out.push_back({false, raw.substr(pos, end - pos)});
pos = end;
}
}
return true;
}

/// Parse a non-negative decimal index. Rejects empty, negative, and
/// non-numeric (with trailing garbage) text.
static bool parseIndex(const std::string& s, std::size_t& idx)
{
if(s.empty())
{
return false;
}
char* endp = nullptr;
const long val = std::strtol(s.c_str(), &endp, 10);
if(*endp != '\0' || val < 0)
{
return false;
}
idx = static_cast<std::size_t>(val);
return true;
}

static Value toValue(const nlohmann::json& j)
{
if(j.is_boolean())
{
return {j.get<bool>()};
}
if(j.is_number_integer() || j.is_number_unsigned())
{
return {j.get<std::int64_t>()};
}
if(j.is_number_float())
{
return {j.get<double>()};
}
if(j.is_string())
{
return {j.get<std::string>()};
}
if(j.is_array())
{
Value::Array a;
a.reserve(j.size());
for(const auto& e : j)
{
a.push_back(toValue(e));
}
return {std::move(a)};
}
return {}; // null or object -> not representable, treated as null
}

static nlohmann::json toJson(const Value& v)
{
if(v.isBool())
{
return v.asBool();
}
if(v.isInt())
{
return v.asInt();
}
if(v.isDouble())
{
return v.asDouble();
}
if(v.isString())
{
return v.asString();
}
if(v.isArray())
{
nlohmann::json a = nlohmann::json::array();
for(const auto& e : v.asArray())
{
a.push_back(toJson(e));
}
return a;
}
return nullptr; // null
}

nlohmann::json _doc;
char _sigil = '$';
};

} // namespace hip_kernel_provider_common::jsonlogic
Loading
Loading