nutshell-cache-verification/scripts/run_rtl_coverage.sh

74 lines
2.4 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
OUT_DIR="${1:-reports/rtl_coverage}"
SUMMARY_MD="${2:-reports/rtl_coverage_summary.md}"
mkdir -p "$OUT_DIR" "$(dirname "$SUMMARY_MD")"
DAT_FILES=()
for f in Cache/VCache_coverage.dat VCache_coverage.dat; do
if [ -f "$f" ]; then
DAT_FILES+=("$f")
fi
done
if [ "${#DAT_FILES[@]}" -eq 0 ]; then
cat >&2 <<'MSG'
ERROR: no Verilator coverage .dat files found.
Run `make gen_dut && make test-hw` first, then rerun `make rtl-coverage`.
MSG
exit 1
fi
LOG="$OUT_DIR/verilator_coverage.log"
verilator_coverage --annotate "$OUT_DIR" "${DAT_FILES[@]}" 2>&1 | tee "$LOG"
python3 - "$LOG" "$SUMMARY_MD" "${DAT_FILES[@]}" <<'PY'
from __future__ import annotations
import re
import sys
from pathlib import Path
log = Path(sys.argv[1]).read_text(encoding='utf-8')
out = Path(sys.argv[2])
dats = sys.argv[3:]
rows = []
for line in log.splitlines():
m = re.match(r"\s*(line|toggle|branch|expr|fsm_state|fsm_arc)\s*:\s*([0-9.]+)%\s*\(\s*(\d+)/\s*(\d+)\)", line)
if m:
kind, pct, hit, total = m.groups()
rows.append((kind, pct, hit, total))
ann = re.search(r"Annotation Summary:\n\s*lines with all attached points covered\s*:\s*([0-9.]+)%\s*\(\s*(\d+)/(\d+)\)", log)
lines = [
"# RTL Coverage Summary",
"",
"Generated by `verilator_coverage --annotate` from Verilator coverage `.dat` files.",
"",
"## Input data",
"",
]
for dat in dats:
lines.append(f"- `{dat}`")
lines += ["", "## Coverage", "", "| Type | Coverage | Hit / Total |", "|---|---:|---:|"]
for kind, pct, hit, total in rows:
if int(total) == 0:
display = "N/A"
else:
display = f"{float(pct):.1f}%"
lines.append(f"| `{kind}` | {display} | {hit} / {total} |")
if ann:
pct, hit, total = ann.groups()
lines += ["", "## Annotation", "", f"Lines with all attached points covered: **{float(pct):.2f}%** ({hit}/{total})."]
lines += [
"",
"Annotated source files are generated under `reports/rtl_coverage/`; lines marked `%00` identify uncovered coverage points.",
"",
"## Interpretation",
"",
"This is RTL code coverage, complementary to functional coverage. Functional coverage proves planned cache scenarios were hit; RTL coverage highlights unexercised implementation code such as reset-only, rare error, unused coherence-release, or tool-generated paths.",
]
out.write_text("\n".join(lines) + "\n", encoding='utf-8')
print(f"wrote {out}")
PY