mirror of
https://github.com/retroSoC/retroSoC.git
synced 2026-11-04 22:32:36 +00:00
- Changed parameter names in various modules from uppercase to camel case for consistency. - Updated local parameters in testbenches to follow the same naming convention. - Modified the RTL style manifest to include additional prefixes for better organization. - Enhanced the check_format and check_rtl_style scripts to improve file tracking and naming validation. - Added new tests to ensure compliance with the updated naming conventions and allowed local parameters in specific contexts.
147 lines
4.8 KiB
Python
147 lines
4.8 KiB
Python
#!/usr/bin/env python3
|
|
"""Format or verify the tracked self-owned Makefile and RTL sources."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
from collections.abc import Iterable, Iterator
|
|
from pathlib import Path
|
|
|
|
|
|
RTL_SUFFIXES = {".sv", ".svh", ".v", ".vh"}
|
|
SELF_OWNED_RTL_ROOTS = {
|
|
("rtl", "demo"),
|
|
("rtl", "ip"),
|
|
("rtl", "mini"),
|
|
("rtl", "tech"),
|
|
("tests", "rtl"),
|
|
}
|
|
|
|
|
|
def tracked_files(root: Path) -> list[Path]:
|
|
"""Return repository files, including worktree files after directory moves."""
|
|
result = subprocess.run(
|
|
["git", "-C", str(root), "ls-files", "--cached", "--others", "--exclude-standard", "-z"],
|
|
check=True,
|
|
stdout=subprocess.PIPE,
|
|
)
|
|
return sorted({Path(path.decode("utf-8")) for path in result.stdout.split(b"\0") if path})
|
|
|
|
|
|
def format_files(paths: Iterable[Path], kind: str) -> list[Path]:
|
|
"""Select formatter-owned files from tracked relative paths."""
|
|
if kind == "make":
|
|
return sorted(path for path in paths if path.name == "Makefile" or path.suffix == ".mk")
|
|
if kind == "rtl":
|
|
return sorted(
|
|
path
|
|
for path in paths
|
|
if path.suffix in RTL_SUFFIXES and tuple(path.parts[:2]) in SELF_OWNED_RTL_ROOTS
|
|
)
|
|
raise ValueError(f"unknown format kind: {kind}")
|
|
|
|
|
|
def chunks(paths: list[Path], size: int = 64) -> Iterator[list[Path]]:
|
|
for start in range(0, len(paths), size):
|
|
yield paths[start : start + size]
|
|
|
|
|
|
def require_tool(tool: str) -> str:
|
|
executable = shutil.which(tool)
|
|
if executable is None:
|
|
raise RuntimeError(f"formatter executable not found: {tool}")
|
|
return executable
|
|
|
|
|
|
def run(command: list[str], root: Path) -> None:
|
|
subprocess.run(command, cwd=root, check=True)
|
|
|
|
|
|
def format_makefiles(tool: str, config: Path, paths: list[Path], root: Path) -> None:
|
|
for batch in chunks(paths):
|
|
run([tool, "format", "--config", str(config), *(str(path) for path in batch)], root)
|
|
|
|
|
|
def format_rtl(tool: str, config: Path, paths: list[Path], root: Path, verify: bool) -> None:
|
|
batches: Iterable[list[Path]] = ([path] for path in paths) if verify else chunks(paths)
|
|
for batch in batches:
|
|
action = "--verify" if verify else "--inplace"
|
|
run(
|
|
[
|
|
tool,
|
|
f"--flagfile={config}",
|
|
"--failsafe_success=false",
|
|
action,
|
|
*(str(path) for path in batch),
|
|
],
|
|
root,
|
|
)
|
|
|
|
|
|
def check_makefiles(tool: str, config: Path, paths: list[Path], root: Path) -> list[Path]:
|
|
"""Return source paths that mbake would rewrite without touching the workspace."""
|
|
with tempfile.TemporaryDirectory(prefix="retrosoc-format-") as temporary:
|
|
temporary_root = Path(temporary)
|
|
copies: list[Path] = []
|
|
for source in paths:
|
|
destination = temporary_root / source
|
|
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
shutil.copy2(root / source, destination)
|
|
copies.append(destination)
|
|
format_makefiles(tool, config, copies, root)
|
|
return [
|
|
source
|
|
for source, copy in zip(paths, copies, strict=True)
|
|
if (root / source).read_bytes() != copy.read_bytes()
|
|
]
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("--root", type=Path, required=True)
|
|
parser.add_argument("--kind", choices=("make", "rtl"), required=True)
|
|
parser.add_argument("--apply", action="store_true")
|
|
parser.add_argument("--mbake", default="mbake")
|
|
parser.add_argument("--verible-verilog-format", default="verible-verilog-format")
|
|
args = parser.parse_args()
|
|
|
|
root = args.root.resolve()
|
|
files = [
|
|
path
|
|
for path in format_files(tracked_files(root), args.kind)
|
|
if (root / path).is_file()
|
|
]
|
|
if not files:
|
|
print(f"no tracked {args.kind} files selected")
|
|
return 0
|
|
|
|
if args.kind == "make":
|
|
tool = require_tool(args.mbake)
|
|
config = root / ".bake.toml"
|
|
if args.apply:
|
|
format_makefiles(tool, config, files, root)
|
|
return 0
|
|
changed = check_makefiles(tool, config, files, root)
|
|
if changed:
|
|
print("Makefile formatting required:", file=sys.stderr)
|
|
print("\n".join(str(path) for path in changed), file=sys.stderr)
|
|
return 1
|
|
return 0
|
|
|
|
tool = require_tool(args.verible_verilog_format)
|
|
config = root / ".verible-format"
|
|
format_rtl(tool, config, files, root, verify=not args.apply)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
raise SystemExit(main())
|
|
except (RuntimeError, subprocess.CalledProcessError) as error:
|
|
print(f"format check failed: {error}", file=sys.stderr)
|
|
raise SystemExit(1) from error
|