Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

184 lines
6.3 KiB
Python

#!/usr/bin/env python3
# Copyright (c) Advanced Micro Devices, Inc., or its affiliates.
# SPDX-License-Identifier: MIT
"""CLI entry point for the hipDNN descriptor code generator."""
import argparse
import sys
from pathlib import Path
from codegen.config_loader import ConfigError, load_config, validate_for_mode
from codegen.generator import BACKEND_FRAGMENT_FILENAMES, DescriptorGenerator
# Generation modes
MODE_BACKEND = "backend"
MODE_FRONTEND = "frontend"
MODE_FULL = "full"
VALID_MODES = (MODE_BACKEND, MODE_FRONTEND, MODE_FULL)
# Modes that require frontend config fields
FRONTEND_MODES = (MODE_FRONTEND, MODE_FULL)
def main():
parser = argparse.ArgumentParser(
description="Generate hipDNN operation descriptor boilerplate from YAML configs."
)
parser.add_argument(
"--config",
required=True,
type=Path,
help="Path to YAML config file (e.g., configs/convolution_fwd.yaml)",
)
parser.add_argument(
"--output-dir",
required=True,
type=Path,
help="Output directory (e.g., ../../ to write relative to hipdnn project root)",
)
parser.add_argument(
"--mode",
choices=VALID_MODES,
default=MODE_BACKEND,
help="Generation mode: 'backend' (default, current behavior), "
"'frontend' (frontend-only), or 'full' (everything).",
)
parser.add_argument(
"--dry-run",
action="store_true",
help="Preview which files would be generated without writing them.",
)
args = parser.parse_args()
if not args.config.exists():
print(f"Error: Config file not found: {args.config}", file=sys.stderr)
sys.exit(1)
try:
config = load_config(args.config)
except ConfigError as e:
print(f"Config error: {e}", file=sys.stderr)
sys.exit(1)
# Validate frontend fields when mode requires frontend generation
if args.mode in FRONTEND_MODES:
try:
validate_for_mode(config, args.mode)
except ConfigError as e:
print(f"Config error: {e}", file=sys.stderr)
sys.exit(1)
print(f"Loaded config for operation: {config.name}")
print(f" Class: {config.class_name}")
print(f" FBS table: {config.fbs_table}")
print(f" Tensors: {[f.name for f in config.tensor_fields]}")
print(f" Data fields: {[f.name for f in config.data_fields]}")
print(f" Mode: {args.mode}")
if args.mode in FRONTEND_MODES:
print(f" Frontend inputs: " f"{[t.name for t in config.frontend.inputs]}")
print(f" Frontend outputs: " f"{[t.name for t in config.frontend.outputs]}")
template_dir = Path(__file__).parent / "templates"
generator = DescriptorGenerator(template_dir)
if args.dry_run:
files = _preview_files(config, args.mode)
print(f"\nDry run: {len(files)} files would be generated:")
for f in files:
print(f" {f}")
print("\nNo files were written.")
return
args.output_dir.mkdir(parents=True, exist_ok=True)
try:
written = generator.render(config, args.output_dir, args.mode)
except ValueError as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"Template rendering error: {e}", file=sys.stderr)
sys.exit(1)
mode_label = {
MODE_BACKEND: "backend",
MODE_FRONTEND: "frontend",
MODE_FULL: "full",
}.get(args.mode, "")
print(f"\nGenerated {len(written)} {mode_label} files:")
for f in written:
print(f" {f}")
print("\nDone. See CLAUDE.md for post-generation integration steps.")
def _preview_files(config, mode: str) -> list[str]:
"""Return the list of file paths that would be generated for the given mode."""
files = []
# Backend files
backend_files = [
f"backend/src/descriptors/{config.header_filename}",
f"backend/src/descriptors/{config.source_filename}",
f"frontend/include/hipdnn_frontend/detail/{config.packer_filename}",
f"frontend/include/hipdnn_frontend/detail/{config.unpacker_filename}",
f"backend/tests/descriptors/{config.test_descriptor_filename}",
f"backend/tests/descriptors/{config.test_graph_filename}",
f"backend/tests/descriptors/{config.test_from_node_filename}",
f"tests/frontend/{config.test_integration_filename}",
f"tests/frontend/{config.test_integration_lifting_filename}",
]
backend_fragments = [f"fragments/{f}" for f in BACKEND_FRAGMENT_FILENAMES]
# Frontend files
frontend_files = [
f"frontend/include/hipdnn_frontend/attributes/{config.attributes_header_filename}",
f"frontend/include/hipdnn_frontend/node/{config.node_header_filename}",
]
frontend_test_files = [
f"frontend/tests/{config.test_attributes_filename}",
f"frontend/tests/{config.test_node_filename}",
f"frontend/tests/{config.test_frontend_graph_filename}",
]
frontend_fragments = [
"fragments/graph_method.txt",
"fragments/graph_includes.txt",
"fragments/frontend_cmake_entries.txt",
"fragments/node_type_enum.txt",
]
if mode == MODE_BACKEND:
files = backend_files + backend_fragments
elif mode == MODE_FRONTEND:
files = frontend_files + frontend_test_files + frontend_fragments
elif mode == MODE_FULL:
files = (
backend_files
+ backend_fragments
+ frontend_files
+ frontend_test_files
+ frontend_fragments
)
# Mode enum files (dynamic based on config)
if mode in (MODE_BACKEND, MODE_FULL):
for df in config.generatable_mode_fields:
files.append(f"backend/include/{df.enum_def.backend_header}")
files.append(f"fragments/mode_backend_plumbing_{df.name}.txt")
files.append(f"fragments/mode_frontend_plumbing_{df.name}.txt")
files.append(f"fragments/mode_frontend_tests_{df.name}.txt")
# Constants file (only when no pre-existing constants header)
if not config.test_data.constants_include:
constants_path = f"test_sdk/include/hipdnn_test_sdk/constants/{config.effective_constants_include}.hpp"
if mode in (MODE_BACKEND, MODE_FULL):
files.append(constants_path)
return files
if __name__ == "__main__":
main()