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
184 lines
6.3 KiB
Python
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()
|