Files
retroSoC/scripts/spi_p3.py
T
maksyuki 31daf3e84c feat(spi): implement SPI-P3 Tiny GPIO RCU and SDK integration
Integrate the SPI-P2 shared-DMA ABI into the Tiny product: SPI0 at
0x1001D000 with IRQ25 and RCU target16, the four frozen Gen1 ALT routes,
latched four-bit source qualification through the fabric and APB CDC, GPIO
readiness/ownership guard, and the bounded rs_spi_* HAL with the
TINY_SPI_P3_ACCEPTANCE ci_smoke image. Tiny DMA enables V2.2 requests 16/17
with exact fixed FIFO MMIO checks; Mini remains default-disabled and
unchanged. Review closure: the DMA AXI4 master stages the origin channel with
each burst so final and contended SPI alias bursts stay qualified, the RCU
spare feedback bit is tied off for four-state simulators, and the
clock-switch quiescence now includes the SPI session.

Validation: full Pytest 2097 passed, 0 failed, 1 skipped (optional pypdf);
both Tiny profiles pass the SPI-P3 Verilator acceptance (SIM_TEST_PASS
cycles=1030088); R2-P7 Verilator acceptance, Mini DMA formal prove and
cover, Mini/Tiny lint, Tiny Yosys synthesis, netsim-boot and OpenSTA pass;
C format/policy/host tests and RTL format/style checks clean. Evidence and
remaining obligations are recorded in docs/ip/spi-verification.md.

Tiny Icarus behavioral remains blocked by the pre-existing observer/sv2v
defect (routed to the R2 DV owners); Mini smoke synthesis host timeout is
skipped per maintainer decision. Human phase acceptance and SPI-P4/P5
remain outstanding; phase_accepted stays false.
2026-10-22 11:57:29 +08:00

51 lines
2.1 KiB
Python

#!/usr/bin/env python3
"""Source-bound focused SPI-P3 Tiny integration checks."""
from __future__ import annotations
import argparse
import hashlib
import json
from pathlib import Path
import subprocess
import sys
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
from scripts.setup_helpers import atomic_write # noqa: E402
def configuration_digest(manifest: dict) -> str:
payload = json.dumps(manifest["configuration"], sort_keys=True).encode("utf-8")
return hashlib.sha256(payload).hexdigest()
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("stage", choices=("lint", "rtl", "report"))
parser.add_argument("--variant-root", type=Path, required=True)
parser.add_argument("--pdk", choices=("ICS55", "IHP130"), required=True)
args = parser.parse_args()
variant = args.variant_root.resolve()
variant.relative_to(ROOT / "build")
manifest = json.loads((variant / "meta/manifest.json").read_text())
if manifest["configuration"]["SOC"] != "TINY" or manifest["configuration"]["PDK"] != args.pdk:
raise ValueError("profile/PDK mismatch")
output = variant / "meta/spi-p3" / args.stage
output.mkdir(parents=True, exist_ok=False)
command = [sys.executable, "-m", "pytest", "-q", "tests/test_spi_p3.py",
"tests/test_spi_p2.py", "tests/test_spi_register_parity.py"]
result = subprocess.run(command, cwd=ROOT, capture_output=True, text=True, check=False)
atomic_write(output / "pytest.log", result.stdout + result.stderr)
record = {"phase": "SPI-P3", "stage": args.stage,
"status": "passed" if result.returncode == 0 else "failed",
"command": command, "configuration_digest": configuration_digest(manifest),
"phase_accepted": False}
atomic_write(output / "record.json", json.dumps(record, indent=2, sort_keys=True) + "\n")
if result.returncode != 0:
print(result.stdout + result.stderr, file=sys.stderr)
return result.returncode
if __name__ == "__main__":
raise SystemExit(main())