74 lines
2.4 KiB
Bash
Executable File
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
|