Files
gps/tools/local/circt/bin/circt-test-runner-verilator.py
T
2026-07-12 11:01:51 +03:00

120 lines
2.8 KiB
Python
Executable File

#!/usr/bin/env python3
from pathlib import Path
import argparse
import os
import shlex
import subprocess
import sys
parser = argparse.ArgumentParser()
parser.add_argument("verilog")
parser.add_argument("-t", "--test", required=True)
parser.add_argument("-d", "--directory", required=True)
parser.add_argument(
"--trace",
type=str,
default="",
help="Enable waveform tracing with format preferences (e.g., 'fst,vcd')")
args = parser.parse_args()
def select_trace_format(preferences):
if not preferences:
return None, None, None
supported = {
"vcd": ("vcd", ".vcd", "--trace-vcd"),
"fst": ("fst", ".fst", "--trace-fst"),
}
prefs = [p.strip().lower() for p in preferences.split(",")]
for pref in prefs:
if pref in supported:
return supported[pref]
return supported["vcd"]
directory = Path(args.directory)
source_path = Path(args.verilog)
build_path = directory / "build"
testbench_path = directory / "testbench.sv"
# Select trace format (returns Nones if args.trace is empty)
trace_format, trace_ext, trace_option = select_trace_format(args.trace)
# Only set trace_file if tracing is enabled
if trace_format:
trace_file = directory / f"{args.test}{trace_ext}"
else:
trace_file = ""
# Generate the Verilog top-level that interacts with the test module.
testbench = f"""
module circt_test;
bit clock = 0, init = 1, done, success;
{args.test} dut(.clock, .init, .done, .success);
initial begin
"""
if trace_format:
testbench += f"""
$dumpfile("{trace_file}");
$dumpvars(0, circt_test);
"""
testbench += f"""
#1 clock = 1;
#1 clock = 0; init = 0;
#1 clock = 1;
while (!done) begin
#1 clock = 0;
#1 clock = 1;
end
if (success) $finish; else $fatal;
end
endmodule
"""
with open(testbench_path, "w") as f:
f.write(testbench)
# Verilate the test.
cmd = [
"verilator",
"--cc",
"--exe",
"--main",
"--timing",
testbench_path,
"-Mdir",
build_path,
"--top-module",
"circt_test",
]
# Add trace support if tracing is enabled
if trace_format:
cmd += [trace_option]
if source_path.is_dir():
cmd += ["-F", source_path / "filelist.f"]
else:
cmd += [source_path]
sys.stderr.write("# " + shlex.join(str(c) for c in cmd) + "\n")
sys.stderr.flush()
if subprocess.call(cmd):
sys.exit(1)
# Compile the test.
cmd = ["make", "-j", "-C", build_path, "-f", "Vcirct_test.mk"]
if arg := os.environ.get("CC"):
cmd += ["CC=" + arg]
if arg := os.environ.get("CXX"):
cmd += ["CXX=" + arg]
sys.stderr.write("# " + shlex.join(str(c) for c in cmd) + "\n")
sys.stderr.flush()
if subprocess.call(cmd):
sys.exit(1)
# Run the test.
cmd = [build_path / "Vcirct_test"]
sys.stderr.write("# " + shlex.join(str(c) for c in cmd) + "\n")
sys.stderr.flush()
result = subprocess.call(cmd)
sys.exit(result)