| 11 | |
| 12 | |
| 13 | class DocsGenerator: |
| 14 | def __init__(self, ggml_root: str, output_filename: str = "ops.md"): |
| 15 | self.ggml_root = Path(ggml_root) |
| 16 | self.ops_dir = self.ggml_root / "docs" / "ops" |
| 17 | self.output_filename = output_filename |
| 18 | self.backend_support: dict[str, dict[str, list[bool]]] = defaultdict( |
| 19 | lambda: defaultdict(list) |
| 20 | ) |
| 21 | self.all_operations: set[str] = set() |
| 22 | self.all_backends: set[str] = set() |
| 23 | self.logger = logging.getLogger(__name__) |
| 24 | |
| 25 | def parse_support_files(self) -> None: |
| 26 | if not self.ops_dir.exists(): |
| 27 | self.logger.warning(f"ops directory not found: {self.ops_dir}") |
| 28 | return |
| 29 | |
| 30 | self.logger.info(f"Parsing support files from {self.ops_dir}...") |
| 31 | |
| 32 | for support_file in self.ops_dir.glob("*.csv"): |
| 33 | self.logger.info(f" Reading: {support_file.name}") |
| 34 | self._parse_support_file(support_file) |
| 35 | |
| 36 | def _parse_support_file(self, file_path: Path) -> None: |
| 37 | try: |
| 38 | with open(file_path, "r", newline='') as f: |
| 39 | reader = csv.DictReader(f) |
| 40 | |
| 41 | for row in reader: |
| 42 | # Skip rows that don't have support mode |
| 43 | if row.get('test_mode') != 'support': |
| 44 | continue |
| 45 | |
| 46 | backend_name = row.get('backend_name', '').strip() |
| 47 | operation = row.get('op_name', '').strip() |
| 48 | supported_str = row.get('error_message', '').strip() # "yes" or "no" |
| 49 | backend_reg_name = row.get('backend_reg_name', '').strip() |
| 50 | |
| 51 | # Skip invalid or error operations |
| 52 | if not operation or not backend_name or operation in [ |
| 53 | "CONTEXT_ERROR", |
| 54 | "BUILD_ERROR", |
| 55 | ]: |
| 56 | continue |
| 57 | |
| 58 | is_supported = supported_str.lower() == "yes" |
| 59 | |
| 60 | # Use backend_reg_name for grouping, fallback to backend_name |
| 61 | backend_key = backend_reg_name if backend_reg_name else backend_name |
| 62 | |
| 63 | self.all_backends.add(backend_key) |
| 64 | self.backend_support[backend_key][operation].append(is_supported) |
| 65 | self.all_operations.add(operation) |
| 66 | |
| 67 | except Exception as e: |
| 68 | self.logger.error(f" Error parsing {file_path}: {e}") |
| 69 | |
| 70 | def get_backend_support_status(self, backend: str, operation: str) -> str: |