summaryrefslogtreecommitdiff
path: root/llama.cpp/ggml/src/ggml-virtgpu/regenerate_remoting.py
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2026-02-12 20:57:17 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2026-02-12 20:57:17 +0100
commitb333b06772c89d96aacb5490d6a219fba7c09cc6 (patch)
tree211df60083a5946baa2ed61d33d8121b7e251b06 /llama.cpp/ggml/src/ggml-virtgpu/regenerate_remoting.py
downloadllmnpc-b333b06772c89d96aacb5490d6a219fba7c09cc6.tar.gz
Engage!
Diffstat (limited to 'llama.cpp/ggml/src/ggml-virtgpu/regenerate_remoting.py')
-rwxr-xr-xllama.cpp/ggml/src/ggml-virtgpu/regenerate_remoting.py332
1 files changed, 332 insertions, 0 deletions
diff --git a/llama.cpp/ggml/src/ggml-virtgpu/regenerate_remoting.py b/llama.cpp/ggml/src/ggml-virtgpu/regenerate_remoting.py
new file mode 100755
index 0000000..aeb48a4
--- /dev/null
+++ b/llama.cpp/ggml/src/ggml-virtgpu/regenerate_remoting.py
@@ -0,0 +1,332 @@
+#!/usr/bin/env python3
+"""
+# Generated by Claude AI
+
+Script to completely regenerate the GGML remoting codebase from YAML configuration.
+
+This script reads api_functions.yaml and regenerates all the header files and
+implementation templates for the GGML remoting layer.
+
+Usage:
+ python regenerate_remoting.py
+
+The script will:
+1. Read ggmlremoting_functions.yaml configuration
+2. Generate updated header files
+3. Generate implementation templates in dedicated files
+4. Show a summary of what was generated
+"""
+
+import yaml
+from typing import Dict, List, Any
+from pathlib import Path
+import os
+import subprocess
+import shutil
+import logging
+
+NL = '\n' # can't have f"{'\n'}" in f-strings
+
+
+class RemotingCodebaseGenerator:
+ def __init__(self, yaml_path: str = "ggmlremoting_functions.yaml"):
+ """Initialize the generator with the YAML configuration."""
+ self.yaml_path = yaml_path
+
+ if not Path(yaml_path).exists():
+ raise FileNotFoundError(f"Configuration file {yaml_path} not found")
+
+ with open(yaml_path, 'r') as f:
+ self.config = yaml.safe_load(f)
+
+ self.functions = self.config['functions']
+ self.naming_patterns = self.config['naming_patterns']
+ self.config_data = self.config['config']
+
+ # Check if clang-format is available
+ self.clang_format_available = self._check_clang_format_available()
+
+ def _check_clang_format_available(self) -> bool:
+ """Check if clang-format is available in the system PATH."""
+ return shutil.which("clang-format") is not None
+
+ def _format_file_with_clang_format(self, file_path: Path) -> bool:
+ """Format a file with clang-format -i. Returns True if successful, False otherwise."""
+ if not self.clang_format_available:
+ return False
+
+ try:
+ subprocess.run(
+ ["clang-format", "-i", str(file_path)],
+ check=True,
+ capture_output=True,
+ text=True
+ )
+ return True
+ except subprocess.CalledProcessError:
+ logging.exception(f" ⚠️ clang-format failed for {file_path}")
+ return False
+ except Exception as e:
+ logging.exception(f" ⚠️ Unexpected error formatting {file_path}: {e}")
+ return False
+
+ def generate_enum_name(self, group_name: str, function_name: str) -> str:
+ """Generate the APIR_COMMAND_TYPE enum name for a function."""
+ prefix = self.naming_patterns['enum_prefix']
+ return f"{prefix}{group_name.upper()}_{function_name.upper()}"
+
+ def generate_backend_function_name(self, group_name: str, function_name: str) -> str:
+ """Generate the backend function name."""
+ function_key = f"{group_name}_{function_name}"
+ overrides = self.naming_patterns.get('backend_function_overrides', {})
+
+ if function_key in overrides:
+ return overrides[function_key]
+
+ prefix = self.naming_patterns['backend_function_prefix']
+ return f"{prefix}{group_name}_{function_name}"
+
+ def generate_frontend_function_name(self, group_name: str, function_name: str) -> str:
+ """Generate the frontend function name."""
+ prefix = self.naming_patterns['frontend_function_prefix']
+ return f"{prefix}{group_name}_{function_name}"
+
+ def get_enabled_functions(self) -> List[Dict[str, Any]]:
+ """Get all enabled functions with their metadata."""
+ functions = []
+ enum_value = 0
+
+ for group_name, group_data in self.functions.items():
+ group_description = group_data['group_description']
+
+ for function_name, func_metadata in group_data['functions'].items():
+ # Handle case where func_metadata is None or empty (functions with only comments)
+ if func_metadata is None:
+ func_metadata = {}
+
+ # Functions are enabled by default unless explicitly disabled
+ if func_metadata.get('enabled', True):
+ functions.append({
+ 'group_name': group_name,
+ 'function_name': function_name,
+ 'enum_name': self.generate_enum_name(group_name, function_name),
+ 'enum_value': enum_value,
+ 'backend_function': self.generate_backend_function_name(group_name, function_name),
+ 'frontend_function': self.generate_frontend_function_name(group_name, function_name),
+ 'frontend_return': func_metadata.get('frontend_return', 'void'),
+ 'frontend_extra_params': func_metadata.get('frontend_extra_params', []),
+ 'group_description': group_description,
+ 'deprecated': func_metadata.get('deprecated', False),
+ })
+ enum_value += 1
+
+ return functions
+
+ def generate_apir_backend_header(self) -> str:
+ """Generate the complete apir_backend.h file."""
+ functions = self.get_enabled_functions()
+
+ # Generate the enum section
+ enum_lines = ["typedef enum ApirBackendCommandType {"]
+ current_group = None
+
+ for func in functions:
+ # Add comment for new group
+ if func['group_name'] != current_group:
+ enum_lines.append("")
+ enum_lines.append(f" /* {func['group_description']} */")
+ current_group = func['group_name']
+
+ enum_lines.append(f" {func['enum_name']} = {func['enum_value']},")
+
+ # Add the count
+ total_count = len(functions)
+ enum_lines.append("\n // last command_type index + 1")
+ enum_lines.append(f" APIR_BACKEND_DISPATCH_TABLE_COUNT = {total_count},")
+ enum_lines.append("} ApirBackendCommandType;")
+
+ # Full header template
+ header_content = NL.join(enum_lines) + "\n"
+
+ return header_content
+
+ def generate_backend_dispatched_header(self) -> str:
+ """Generate the complete backend-dispatched.h file."""
+ functions = self.get_enabled_functions()
+
+ # Function declarations
+ decl_lines = []
+ current_group = None
+
+ for func in functions:
+ if func['group_name'] != current_group:
+ decl_lines.append(f"\n/* {func['group_description']} */")
+ current_group = func['group_name']
+
+ signature = "uint32_t"
+ params = "apir_encoder *enc, apir_decoder *dec, virgl_apir_context *ctx"
+ if func['deprecated']:
+ decl_lines.append(f"/* {func['enum_name']} is deprecated. Keeping the handler for backward compatibility. */")
+
+ decl_lines.append(f"{signature} {func['backend_function']}({params});")
+
+ # Switch cases
+ switch_lines = []
+ current_group = None
+
+ for func in functions:
+ if func['group_name'] != current_group:
+ switch_lines.append(f" /* {func['group_description']} */")
+ current_group = func['group_name']
+
+ deprecated = " (DEPRECATED)" if func['deprecated'] else ""
+
+ switch_lines.append(f" case {func['enum_name']}: return \"{func['backend_function']}{deprecated}\";")
+
+ # Dispatch table
+ table_lines = []
+ current_group = None
+
+ for func in functions:
+ if func['group_name'] != current_group:
+ table_lines.append(f"\n /* {func['group_description']} */")
+ table_lines.append("")
+ current_group = func['group_name']
+
+ deprecated = " /* DEPRECATED */" if func['deprecated'] else ""
+ table_lines.append(f" /* {func['enum_name']} = */ {func['backend_function']}{deprecated},")
+
+ header_content = f'''\
+#pragma once
+
+{NL.join(decl_lines)}
+
+static inline const char *backend_dispatch_command_name(ApirBackendCommandType type)
+{{
+ switch (type) {{
+{NL.join(switch_lines)}
+
+ default: return "unknown";
+ }}
+}}
+
+extern "C" {{
+static const backend_dispatch_t apir_backend_dispatch_table[APIR_BACKEND_DISPATCH_TABLE_COUNT] = {{
+ {NL.join(table_lines)}
+}};
+}}
+'''
+ return header_content
+
+ def generate_virtgpu_forward_header(self) -> str:
+ """Generate the complete virtgpu-forward.gen.h file."""
+ functions = self.get_enabled_functions()
+
+ decl_lines = []
+ current_group = None
+
+ for func in functions:
+ if func['group_name'] != current_group:
+ decl_lines.append("")
+ decl_lines.append(f"/* {func['group_description']} */")
+ current_group = func['group_name']
+
+ if func['deprecated']:
+ decl_lines.append(f"/* {func['frontend_function']} is deprecated. */")
+ continue
+
+ # Build parameter list
+ params = [self.naming_patterns['frontend_base_param']]
+ params.extend(func['frontend_extra_params'])
+ param_str = ', '.join(params)
+
+ decl_lines.append(f"{func['frontend_return']} {func['frontend_function']}({param_str});")
+
+ header_content = f'''\
+#pragma once
+{NL.join(decl_lines)}
+'''
+ return header_content
+
+ def regenerate_codebase(self) -> None:
+ """Regenerate the entire remoting codebase."""
+ logging.info("πŸ”„ Regenerating GGML Remoting Codebase...")
+ logging.info("=" * 50)
+
+ # Detect if we're running from frontend directory
+ current_dir = os.getcwd()
+ is_frontend_dir = current_dir.endswith('ggml-virtgpu')
+
+ if is_frontend_dir:
+ # Running from ggml/src/ggml-virtgpu-apir
+ logging.info("πŸ“ Detected frontend directory execution")
+ frontend_base = Path(".")
+ else:
+ # Running from project root (fallback to original behavior)
+ logging.info("πŸ“ Detected project root execution")
+ base_path = self.config_data.get('base_path', 'ggml/src')
+ frontend_base = Path(base_path) / "ggml-virtgpu"
+
+ # Compute final file paths
+ backend_base = frontend_base / "backend"
+ apir_backend_path = backend_base / "shared" / "apir_backend.gen.h"
+ backend_dispatched_path = backend_base / "backend-dispatched.gen.h"
+ virtgpu_forward_path = frontend_base / "virtgpu-forward.gen.h"
+
+ # Create output directories for each file
+ apir_backend_path.parent.mkdir(parents=True, exist_ok=True)
+ backend_dispatched_path.parent.mkdir(parents=True, exist_ok=True)
+ virtgpu_forward_path.parent.mkdir(parents=True, exist_ok=True)
+
+ # Generate header files
+ logging.info("πŸ“ Generating header files...")
+
+ apir_backend_content = self.generate_apir_backend_header()
+ apir_backend_path.write_text(apir_backend_content)
+ logging.info(f" βœ… {apir_backend_path.resolve()}")
+
+ backend_dispatched_content = self.generate_backend_dispatched_header()
+ backend_dispatched_path.write_text(backend_dispatched_content)
+ logging.info(f" βœ… {backend_dispatched_path.resolve()}")
+
+ virtgpu_forward_content = self.generate_virtgpu_forward_header()
+ virtgpu_forward_path.write_text(virtgpu_forward_content)
+ logging.info(f" βœ… {virtgpu_forward_path.resolve()}")
+
+ # Format generated files with clang-format
+ generated_files = [apir_backend_path, backend_dispatched_path, virtgpu_forward_path]
+
+ if not self.clang_format_available:
+ logging.warning("\n⚠️clang-format not found in PATH. Generated files will not be formatted.\n"
+ " Install clang-format to enable automatic code formatting.")
+ else:
+ logging.info("\n🎨 Formatting files with clang-format...")
+ for file_path in generated_files:
+ if self._format_file_with_clang_format(file_path):
+ logging.info(f" βœ… Formatted {file_path.name}")
+ else:
+ logging.warning(f" ❌ Failed to format {file_path.name}")
+
+ # Generate summary
+ functions = self.get_enabled_functions()
+ total_functions = len(functions)
+
+ logging.info("\nπŸ“Š Generation Summary:")
+ logging.info("=" * 50)
+ logging.info(f" Total functions: {total_functions}")
+ logging.info(f" Function groups: {len(self.functions)}")
+ logging.info(" Header files: 3")
+ logging.info(f" Working directory: {current_dir}")
+
+
+def main():
+ try:
+ generator = RemotingCodebaseGenerator()
+ generator.regenerate_codebase()
+ except Exception as e:
+ logging.exception(f"❌ Error: {e}")
+ exit(1)
+
+
+if __name__ == "__main__":
+ main()