| name | hipdnn-codegen |
| description | Generate hipDNN operation boilerplate from a YAML config. Use when the user wants to add a new operation type to hipDNN, or generate descriptor/packer/unpacker code. |
| argument-hint | <schema-path-or-op-name> [mode: backend|frontend|full] |
| allowed-tools | Bash, Read, Write, Edit, Grep, Glob, WebFetch, AskUserQuestion |
hipDNN Code Generator Skill
Generate all boilerplate code needed to add a new operation to hipDNN from a YAML config.
This skill is near-autonomous. The agent first tries to resolve everything itself by deriving from the schema, the existing codebase, and cudnn-frontend on GitHub. It may prompt the user as a fallback on three classes of decision where derivation has failed:
- cuDNN naming uncertainty — when the cuDNN equivalent descriptor / attribute / frontend-node name cannot be confidently identified after consulting
cudnn-frontend (drives the _EXT decision; see Step 3a-i).
infer_properties_node() strategy — output-shape inference rule, when the op's shape behavior isn't obvious from analogous ops.
pre_validate_node() rules — additional validation beyond default null/dim checks, when domain-specific constraints aren't derivable.
In a clean, well-known op (cuDNN-aligned with a clear analog), the agent may not prompt at all on the three classes above.
There is one mandatory prompt whenever the agent had to construct the FBS schema (from a user description, or from cudnn-frontend): schema confirmation (Step 2a-ii). Schema mistakes propagate through every layer, so the agent must show the schema and get explicit user sign-off before continuing. This prompt is skipped only when the user supplied a complete FBS file.
Everything else is mechanical and is derived from the FBS schema, existing codebase state, and the conventions in this skill.
For human-facing context, including the cuDNN parity rules, layer-by-layer reference, testing matrix, and PR checklist, see projects/hipdnn/docs/AddingNewOperations.md. For a complete worked example, see configs/convolution_fwd.yaml.
Philosophy
You MUST run the generator. The code generator exists to produce correct, pattern-matched boilerplate. Do not skip it and write code by hand — even if you think you understand the patterns well enough. The generator's output is the starting point for every file and fragment. If Bash access is unavailable or denied, stop and ask the user to grant it rather than proceeding without the generator.
After running the generator, the agent owns the integration. Generated output is scaffolding, not a finished product. Before placing any generated file or inserting any fragment, check if the target already exists in hipDNN. If it does, compare the generated version with the existing code. Use whichever is more correct, or merge them if each covers different parts. If a fragment's insertion point has changed, adapt the fragment to the current code structure.
Generated code is not always perfect. Enum value numbering may differ between the backend C-API, SDK, and frontend — use frontend_value and sdk_name overrides in enum_def to handle mismatches. Test patterns may need adjustment for unusual field types. Fragment insertion points are guidelines; always read the target file. But these are adjustments to generator output, not reasons to bypass the generator entirely.
The goal is a clean, building, tested integration. If generated code needs tweaks to compile, make them. If a fragment conflicts with existing code, resolve it. Judgment and adaptation are applied to generated output, not as a substitute for it.
When to Use Which Mode
| Scenario | Mode |
|---|
| Brand new operation (nothing exists yet) | full |
| Adding backend only (frontend exists or will land later) | backend |
| Adding frontend only (backend descriptor already exists) | frontend |
Arguments
$ARGUMENTS can contain:
- Schema or operation: Path to
.fbs schema file, path to existing YAML config, or operation name (e.g., convolution_fwd)
- Mode (one of):
backend (default) - Descriptor, Packer, Unpacker + backend tests
frontend - Node, Attributes, Graph method + frontend tests
full - Everything (backend + frontend)
Directory Locations
Determine the hipDNN project root by finding the nearest parent directory containing tools/DescriptorGenerator/. Set paths relative to that:
HIPDNN_SRC=<path to projects/hipdnn>
CODEGEN=$HIPDNN_SRC/tools/DescriptorGenerator
VENV=$CODEGEN/.venv
Hint: if the current working directory is inside a rocm-libraries worktree, the hipDNN root is at <worktree>/projects/hipdnn/. If invoked from a standalone hipDNN checkout, it is the repo root.
Execution Steps
1. Parse Arguments and Set Up
Parse $ARGUMENTS for:
- Schema path, config path, or operation name
- Mode (default:
backend)
Locate the hipDNN project root. Verify the codegen venv exists:
cd $CODEGEN
if [ ! -d .venv ]; then
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
fi
2. Determine Input Type
- If argument is a
.fbs file path: proceed to Step 3 (create YAML config from schema)
- If argument is a
.yaml file path: skip to Step 5 (run generator)
- If argument is an operation name and
configs/<name>.yaml exists: skip to Step 5
- If argument is an operation name and no FBS schema exists for it: proceed to Step 2a (author the FBS schema)
- If the argument is unrecognized or ambiguous: ask the user to clarify
2a. Author the FBS Schema (if it does not exist)
Schemas live ONLY in $HIPDNN_SRC/flatbuffers_sdk/schemas/ (they were removed from data_sdk/). Before deriving the YAML, you may need to write the FBS schema yourself.
2a-i. Source the schema content
Pick the path that matches what the user provided:
- User provided an FBS file → use it directly, skip to 2a-ii.
- User provided a description (text listing inputs, outputs, attributes, modes) → translate it directly into the table, skip to 2a-ii.
- User gave only an op name → derive the schema from
cudnn-frontend on GitHub:
- Run the directory listing + node-file fetch from Step 3a-i to locate the matching cuDNN node header (e.g.,
include/cudnn_frontend/node/<op>.h).
- From that header, find the attributes class it references (e.g.,
Conv_fprop_attributes). Fetch its source — usually under include/cudnn_frontend/graph_properties.h or alongside the node header.
- Walk the attributes class:
- Each tensor input/output method (typically
set_<name>(...)) becomes a <name>_tensor_uid: long field. Note which are required vs optional.
- Each scalar/vector attribute (typically
set_<attr>(...)) becomes a typed field with the matching cuDNN name.
- Mode-style enums become a
<field>: <Enum> field; capture the enum members from the cuDNN definition.
- Use the same naming as cuDNN (lowercase snake_case for fields, matching cuDNN attribute identifiers). Apply
_EXT per the rule in Step 3a only to fields with no cuDNN equivalent.
- Write the draft schema to
$HIPDNN_SRC/flatbuffers_sdk/schemas/<op_name>_attributes.fbs.
2a-ii. Confirm the schema with the user
When this prompt is required:
| Schema source | Confirmation required? |
|---|
| User supplied a complete FBS file | No (they already authored it) |
| User supplied a description and the agent translated it | Yes |
Agent derived from cudnn-frontend | Yes |
When required, show the schema and the parsed structure, and get explicit sign-off via AskUserQuestion:
"Here is the FBS schema I will use for <op_name> (sourced from <description / cudnn-frontend URL>):
<full schema contents>
Tensor inputs: <list>. Tensor outputs: <list>. Optional fields: <list>. Mode enums: <list>.
Confirm before I proceed: is this schema correct? (Yes / Edit-and-resend / No-rewrite)"
Do NOT proceed to 2a-iii until the user confirms. If the user requests edits, apply them and ask again. Schema mistakes propagate to every layer (FBS table, generated headers, descriptor, packer, unpacker, attributes class, node, tests) — fixing them late is expensive.
2a-iii. Wire the schema into the build
Once confirmed:
- Update
graph.fbs:
- Add
include "<op_name>_attributes.fbs";
- Add
<Op>Attributes to the NodeAttributes union
- Update the
SCHEMAS list in $HIPDNN_SRC/flatbuffers_sdk/CMakeLists.txt so the new schema is compiled into the SDK.
- Rebuild the FlatBuffers SDK target so the generated headers are present before the code generator runs:
cd $HIPDNN_SRC/build
ninja hipdnn_flatbuffers_sdk
(If no build dir exists yet, see docs/Building.md for first-time setup.)
After 2a-iii, proceed to Step 3.
3. Create YAML Config from FBS Schema
Read the FBS schema file. Map fields to YAML config following these rules:
| FBS Field Pattern | YAML Section | YAML type |
|---|
*_tensor_uid: long | tensor_fields | (tensors are UIDs) |
field: [long] | data_fields | vector_int64 |
field: SomeEnum | data_fields | mode |
field: float | data_fields | scalar_float |
field: long (non-UID) | data_fields | scalar_int64 |
field: bool | data_fields | bool |
field: [long] (array of UIDs) | tensor_array_fields | (tensor arrays) |
Derive all config fields from the schema and existing codebase — do NOT ask the user for these. Use existing configs and backend code to determine:
- Operation name: Derive from the FBS table name (e.g.,
ConvolutionFwdAttributes → ConvolutionFwd)
- Descriptor type enum: Search
$HIPDNN_SRC/backend/include/HipdnnBackendDescriptorType.h for existing enum entries
- Operation attribute prefix: Search
$HIPDNN_SRC/backend/include/HipdnnBackendAttributeName.h for existing HIPDNN_ATTR_OPERATION_* entries
- Shared attributes: Compare attribute names against existing operations in the codebase
- Compute data type: Check if the FBS schema has compute precision fields; check existing operations for patterns
- Test tensor UIDs: Read existing configs in
$CODEGEN/configs/ to find used UID ranges, pick the next available
- Frontend fields (graph method name, NodeType, union type): Derive from existing frontend code or operation name conventions
If a field truly cannot be determined, use sensible defaults derived from the operation name. Only ask the user as a last resort for genuinely ambiguous decisions.
Write the config to $CODEGEN/configs/<operation>.yaml.
Use $CODEGEN/configs/convolution_fwd.yaml as the reference template for all config fields.
3a. cuDNN Naming Parity Check (_EXT Decision Rule)
Parity with cuDNN is nominal (names match) but not numeric (values do not align — pick the next free value as Step 3 already does).
For each name being constructed in the YAML — enum_name, attr_suffix (per tensor/data field), compute_data_type_attr, operation_type_enum — apply the rule:
| Name has a real cuDNN equivalent? | Suffix |
|---|
Yes, exact match (e.g., CUDNN_BACKEND_OPERATION_REDUCTION_DESCRIPTOR) | No _EXT |
| No equivalent, or hipDNN aggregates/splits differently from cuDNN | _EXT |
Sources of truth, in order of preference:
cudnn-frontend source on GitHub — fetch directly to identify class names, attribute names, and the constant identifiers it references. See sub-step 3a-i below. This is the only external cuDNN source the agent should consult.
docs/PortingGuide.md — cuDNN ↔ hipDNN API mapping (may be incomplete or out of date).
Reference examples:
MATH_PREC vs COMP_TYPE for compute_data_type_attr — this is not a free choice; it follows cuDNN. Check the cudnn-frontend node header for the op (or the closest op in the same family) before setting this name. Examples: CUDNN_ATTR_POINTWISE_MATH_PREC → HIPDNN_ATTR_POINTWISE_MATH_PREC (no _EXT); CUDNN_ATTR_REDUCTION_COMP_TYPE → HIPDNN_ATTR_REDUCTION_COMP_TYPE (no _EXT). For ops with no cuDNN equivalent, use COMP_TYPE_EXT.
3a-i. Web-check cudnn-frontend before prompting
cudnn-frontend is open-source at https://github.com/NVIDIA/cudnn-frontend. Use it to discover the cuDNN node class name, its attribute getters, and the CUDNN_ATTR_* / CUDNN_BACKEND_OPERATION_* constants the wrapper references. Node file naming is hard to guess (e.g., conv_fprop.h not convolution_forward.h), so always list the directory first, then fetch the matching file.
-
List the node directory to discover the candidate filename:
gh api repos/NVIDIA/cudnn-frontend/contents/include/cudnn_frontend/node \
--jq '.[].name' 2>/dev/null
Or via WebFetch as a fallback: https://github.com/NVIDIA/cudnn-frontend/tree/main/include/cudnn_frontend/node.
-
Pick the file that matches your op semantically. Examples of name divergence to watch for: conv_fprop.h for forward conv, dbn_weight.h for batchnorm-backward weight grad, sdpa.h for scaled-dot-product-attention. If multiple candidates look plausible, fetch each header in parallel.
-
Fetch the matched header to read the cuDNN class, attribute getters, and the backend constants it wraps:
gh api repos/NVIDIA/cudnn-frontend/contents/include/cudnn_frontend/node/<file>.h \
--jq '.content' | base64 -d
Or via WebFetch on the raw URL: https://raw.githubusercontent.com/NVIDIA/cudnn-frontend/main/include/cudnn_frontend/node/<file>.h.
-
Extract the parity facts you need:
- The cuDNN node class name (e.g.,
Conv_fprop_attributes) — use to confirm the YAML's compatibility_typedef.
- Which
CUDNN_BACKEND_OPERATION_<X>_DESCRIPTOR it constructs — use to set enum_name and decide _EXT.
- Each
CUDNN_ATTR_OPERATION_<X>_<FIELD> it sets via setAttribute — use per-field attr_suffix and _EXT decisions.
-
If the directory listing has no matching file, treat the op as hipDNN-specific: apply _EXT to all four name fields. No need to prompt.
-
If web access fails or the file is ambiguous, fall back to prompting the user via AskUserQuestion with one or more of:
- "I don't know the cuDNN equivalent for this operation. What is the full cuDNN backend descriptor constant name (e.g.,
CUDNN_BACKEND_OPERATION_<X>_DESCRIPTOR), or 'none' if hipDNN-specific?"
- "I cannot confidently match attribute
<name> to a cuDNN constant. What is the full CUDNN_ATTR_<X> name, or 'none' if hipDNN-specific?"
- "I'm not sure what to name the frontend node class / Graph API method (e.g.,
Graph::reduction vs Graph::reduce). Confirm the preferred name."
-
Surface the source in the Step 14 summary. For every name decision driven by the web-check, record the URL fetched and the line/snippet referenced (e.g., "enum_name=...REDUCTION_DESCRIPTOR per cudnn-frontend node/reduction.h L42"). This lets the human spot a misread.
On "none" answers (or no matching cudnn-frontend file), apply _EXT to the corresponding YAML name. On confirmed cuDNN equivalents, omit _EXT.
3b. Populate enum_def for New Enum Types