|
1 | 1 | #!/usr/bin/env python3 |
2 | 2 | import os |
| 3 | +import glob |
3 | 4 | import yaml |
4 | 5 | import logging |
5 | 6 | import pprint |
@@ -281,6 +282,79 @@ def load_instructions( |
281 | 282 | return instr_dict |
282 | 283 |
|
283 | 284 |
|
| 285 | +def load_full_instructions(inst_dir, enabled_extensions, include_all=False, target_arch="RV64"): |
| 286 | + """Load full instruction metadata, optionally filtering by extensions and architecture. |
| 287 | +
|
| 288 | + Parameters |
| 289 | + ---------- |
| 290 | + inst_dir : str |
| 291 | + Root directory containing instruction YAML files. |
| 292 | + enabled_extensions : list[str] |
| 293 | + Extensions that should be considered enabled when filtering instructions. |
| 294 | + include_all : bool, optional |
| 295 | + When True, skip extension filtering entirely. |
| 296 | + target_arch : str, optional |
| 297 | + Target architecture selector: "RV32", "RV64", or "BOTH". When a YAML file |
| 298 | + provides per-architecture encodings, the matching entry is selected. |
| 299 | +
|
| 300 | + Returns |
| 301 | + ------- |
| 302 | + dict[str, dict] |
| 303 | + Mapping from instruction name to the loaded YAML data (with a resolved |
| 304 | + ``encoding`` section for the requested architecture). |
| 305 | + """ |
| 306 | + |
| 307 | + instructions = {} |
| 308 | + ext_filter = [] if enabled_extensions is None else enabled_extensions |
| 309 | + |
| 310 | + yaml_files = glob.glob(os.path.join(inst_dir, "**/*.yaml"), recursive=True) |
| 311 | + logging.info("Found %d instruction files in %s", len(yaml_files), inst_dir) |
| 312 | + |
| 313 | + for yaml_file in yaml_files: |
| 314 | + try: |
| 315 | + with open(yaml_file, "r", encoding="utf-8") as fh: |
| 316 | + data = yaml.safe_load(fh) |
| 317 | + |
| 318 | + if not isinstance(data, dict) or data.get("kind") != "instruction": |
| 319 | + continue |
| 320 | + |
| 321 | + name = data.get("name") |
| 322 | + if not name: |
| 323 | + continue |
| 324 | + |
| 325 | + defined_by = data.get("definedBy") |
| 326 | + if not include_all and defined_by: |
| 327 | + try: |
| 328 | + meets_req = parse_extension_requirements(defined_by) |
| 329 | + if not meets_req(ext_filter): |
| 330 | + logging.debug( |
| 331 | + "Skipping %s - extension requirements not met", name |
| 332 | + ) |
| 333 | + continue |
| 334 | + except Exception as exc: # pragma: no cover - logging path only |
| 335 | + logging.debug( |
| 336 | + "Error parsing extension requirements for %s: %s", |
| 337 | + name, |
| 338 | + exc, |
| 339 | + ) |
| 340 | + continue |
| 341 | + |
| 342 | + encoding = data.get("encoding", {}) |
| 343 | + if target_arch in ("RV32", "RV64") and isinstance(encoding, dict): |
| 344 | + arch_encoding = encoding.get(target_arch) |
| 345 | + if arch_encoding: |
| 346 | + data["encoding"] = arch_encoding |
| 347 | + |
| 348 | + instructions[name] = data |
| 349 | + |
| 350 | + except Exception as exc: # pragma: no cover - logging path only |
| 351 | + logging.error("Error loading %s: %s", yaml_file, exc) |
| 352 | + continue |
| 353 | + |
| 354 | + logging.info("Loaded %d instructions after filtering", len(instructions)) |
| 355 | + return instructions |
| 356 | + |
| 357 | + |
284 | 358 | def load_csrs(csr_root, enabled_extensions, include_all=False, target_arch="RV64"): |
285 | 359 | """ |
286 | 360 | Recursively walk through csr_root, load YAML files that define a CSR, |
|
0 commit comments