diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d94549c..0da35a3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,9 @@ jobs: - name: Test Python golden model run: python -m unittest discover -s tests -v + - name: Check generated README evidence + run: python tools/render_readme_assets.py --check + - name: Regress single-lane parameter case run: python tools/run_regression.py --sim iverilog --vec-len 1 --random-cases 40 diff --git a/README.md b/README.md index cfcc00b..649215a 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,14 @@ I kept the scope deliberately small: parameterized SystemVerilog, ready/valid control, a bit-exact Python reference model, deterministic regression, and CI. This is **not** a trained AI model or a complete neural-network accelerator. +

+ Deterministic RTL regression matrix across vector lengths 1, 8, and 17 +

+ +The figure is generated from the checked-in CI matrix. It counts verification +transactions; it is not a throughput, timing, area, power, FPGA, or silicon +benchmark. + ## What is implemented - Synthesizable SystemVerilog with configurable vector length @@ -72,6 +80,7 @@ lane. See [Architecture](docs/architecture.md) for timing and width details. | `model/dot_product_model.py` | Bit-exact reference arithmetic and packing | | `tb/tb_int8_dot_product.sv` | Self-checking ready/valid testbench | | `tools/run_regression.py` | Vector generation, compile, and simulation harness | +| `tools/render_readme_assets.py` | Rebuilds and checks the README evidence figure | | `tests/` | Python unit tests for the arithmetic contract | | `docs/` | Architecture and verification notes | diff --git a/assets/rtl-regression.svg b/assets/rtl-regression.svg new file mode 100644 index 0000000..d55250e --- /dev/null +++ b/assets/rtl-regression.svg @@ -0,0 +1,70 @@ + + Edge AI RTL Lab deterministic regression matrix + Stacked bars show corner and fixed-seed random transactions for vector lengths 1, 8, and 17. A verification panel lists ten Python model tests, Icarus RTL simulation, and a Yosys structural check. + + + + VERIFICATION / REGRESSION MATRIX + Checked-in CI workload — transaction count, not performance + + + + + 211 max transactions + + + + 47 + VEC_LEN 1 + 7 corner + 40 random + + + + 211 + VEC_LEN 8 + 11 corner + 200 random + + + + 111 + VEC_LEN 17 + 11 corner + 100 random + + + + + WHAT THE PIPELINE CHECKS + + + Python golden-model unit tests + 10 + + RTL transactions across 3 parameter cases + 369 + + Pseudo-random seed + 0x5eed2339 + + Simulation + Icarus + + Structural synthesis sanity check + Yosys + + No timing, area, power, FPGA, or silicon claim + + + + named corner cases + fixed-seed random cases + + diff --git a/tools/render_readme_assets.py b/tools/render_readme_assets.py new file mode 100644 index 0000000..36ed757 --- /dev/null +++ b/tools/render_readme_assets.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +"""Render deterministic README evidence from the checked-in CI matrix.""" + +from __future__ import annotations + +import argparse +from pathlib import Path + +from run_regression import corner_cases + + +ROOT = Path(__file__).resolve().parents[1] +OUTPUT = ROOT / "assets" / "rtl-regression.svg" +SCENARIOS = ((1, 40), (8, 200), (17, 100)) + + +def render() -> str: + rows = [] + for vec_len, random_cases in SCENARIOS: + corners = len(corner_cases(vec_len)) + rows.append((vec_len, random_cases, corners, random_cases + corners)) + + max_total = max(total for _, _, _, total in rows) + bars = [] + for index, (vec_len, random_cases, corners, total) in enumerate(rows): + x = 126 + index * 190 + total_height = 300 * total / max_total + corner_height = 300 * corners / max_total + random_height = total_height - corner_height + y_random = 474 - random_height + y_corner = y_random - corner_height + bars.append( + f''' + + + {total} + VEC_LEN {vec_len} + {corners} corner + {random_cases} random +''' + ) + + return f''' + Edge AI RTL Lab deterministic regression matrix + Stacked bars show corner and fixed-seed random transactions for vector lengths 1, 8, and 17. A verification panel lists ten Python model tests, Icarus RTL simulation, and a Yosys structural check. + + + + VERIFICATION / REGRESSION MATRIX + Checked-in CI workload — transaction count, not performance + + + + + 211 max transactions + {''.join(bars)} + + + + WHAT THE PIPELINE CHECKS + + + Python golden-model unit tests + 10 + + RTL transactions across 3 parameter cases + 369 + + Pseudo-random seed + 0x5eed2339 + + Simulation + Icarus + + Structural synthesis sanity check + Yosys + + No timing, area, power, FPGA, or silicon claim + + + + named corner cases + fixed-seed random cases + + +''' + + +def main() -> None: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--check", action="store_true", help="fail if the committed SVG is stale") + args = parser.parse_args() + expected = render() + + if args.check: + if not OUTPUT.exists() or OUTPUT.read_text(encoding="utf-8") != expected: + raise SystemExit(f"stale generated asset: {OUTPUT.relative_to(ROOT)}") + print(f"up to date: {OUTPUT.relative_to(ROOT)}") + return + + OUTPUT.parent.mkdir(parents=True, exist_ok=True) + OUTPUT.write_text(expected, encoding="utf-8") + print(f"wrote {OUTPUT.relative_to(ROOT)}") + + +if __name__ == "__main__": + main()