Skip to content

Commit

Permalink
More work
Browse files Browse the repository at this point in the history
  • Loading branch information
gussmith23 committed Nov 23, 2024
1 parent ad55f9d commit 2a49700
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 6 deletions.
40 changes: 37 additions & 3 deletions bin/main.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,40 @@
[_ (error "Invalid output format.")])])

(when (simulate-with-verilator)
(let* ([subproc (subprocess #f #f #f "python" "simulate_with_verilator.py")])

(subprocess-wait subproc)))
; TODO(@gussmith23): shouldn't use "python3" directly here.
(let*-values
([(path) (build-path HERE "simulate_with_verilator.py")]
[(_) (log-debug "running simulate_with_verilator.py at ~a" path)]
[(out-verilog-filepath) (make-temporary-file "rkttmp~a.v")]
[(_) (with-output-to-file
out-verilog-filepath
(lambda ()
(when (not (system (format "yosys -q -p 'read_json ~a; write_verilog'"
(json-filepath))))
(error "Yosys failed.")))
#:exists 'must-truncate)]
[(args) (list "--verilog_filepath"
(verilog-module-filepath)
"--verilog_filepath"
out-verilog-filepath
"--test_module_name"
(module-name)
"--ground_truth_module_name"
(top-module-name)
"--output_signal"
(format "~a:~a" (verilog-module-out-signal) (verilog-module-out-bitwidth)))]
[(args) (append args
(flatten (map (lambda (port-pair)
(list "--input_signal"
(format "~a:~a" (first port-pair) (second port-pair))))
(ports))))]
[(args) (append args (simulate-with-verilator-args))]
[(sp out in err) (apply subprocess #f #f #f (find-executable-path "python3") path args)]
[(_) (subprocess-wait sp)]
[(return-code) (subprocess-status sp)])
(when (not (equal? return-code 0))
(error (format
"simulate_with_verilator.py failed with return code ~a\n\nstderr:\n~a\n\nstdout:~a"
return-code
(port->string err)
(port->string out))))))
24 changes: 21 additions & 3 deletions bin/simulate_with_verilator.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
import sys
from typing import List, Optional, Tuple, Union
import subprocess
import logging

MAX_NUM_TESTS = 2**18

LOGGING_ENV_VAR = "SIMULATE_WITH_VERILOG_LOG_LEVEL"


def simulate_with_verilator(
test_module_name: str,
Expand Down Expand Up @@ -57,12 +60,16 @@ def simulate_with_verilator(
# all. But this will lead to a name collision from Verilator, and until
# there are namespaces in Verilog (how are there not???) this is what we're
# stuck with.
assert test_module_name != ground_truth_module_name, "Modules cannot have the same name."
assert (
test_module_name != ground_truth_module_name
), "Modules cannot have the same name."

if ignore_missing_test_module_file and not all(
[Path(path).exists() for path in verilog_filepaths]
):
missing = list(filter(lambda path: not Path(path).exists(), verilog_filepaths))[0]
missing = list(filter(lambda path: not Path(path).exists(), verilog_filepaths))[
0
]
logging.warning(
f"Required Verilog file {missing} does not exist. " "Skipping simulation."
)
Expand Down Expand Up @@ -183,12 +190,15 @@ def generate_one():
for one_set_of_inputs in all_inputs:
print(" ".join([str(hex(x)) for x in one_set_of_inputs]), file=f)

logging.debug(f"Running make -f {makefile_filepath} in {makefile_filepath.parent}")

# --environment-overrides is a brute-force way to allow users to use CXX=...
# to override the C++ compiler with an environment variable. Overriding
# doesn't normally work due to the issues brought up here:
# https://github.com/verilator/verilator/issues/4549
proc = subprocess.run(
["make", "--environment-overrides", "--always-make", "-f", makefile_filepath], capture_output=True
["make", "--environment-overrides", "--always-make", "-f", makefile_filepath],
capture_output=True,
)
Path(testbench_stdout_log_filepath).write_bytes(proc.stdout)
Path(testbench_stderr_log_filepath).write_bytes(proc.stderr)
Expand Down Expand Up @@ -328,6 +338,10 @@ def generate_one():
default=False,
help="Whether to expect that all outputs are always 0 on all inputs.",
)
parser.add_argument(
"--log_level",
help=f"Provide logging level. Example --loglevel debug, default=no logging. Logging can also be controlled by the {LOGGING_ENV_VAR} environment variable.",
)

args = parser.parse_args()

Expand All @@ -339,6 +353,10 @@ def generate_one():
# Parse something like <signal_name>:<bitwidth> into a tuple.
parse_signal_str = lambda x: (str(x.split(":")[0]), int(x.split(":")[1]))

if args.log_level or os.environ.get(LOGGING_ENV_VAR):
logging.basicConfig(level=args.log_level.upper() if args.log_level else os.environ.get(LOGGING_ENV_VAR))


simulate_with_verilator(
test_module_name=args.test_module_name,
ground_truth_module_name=args.ground_truth_module_name,
Expand Down

0 comments on commit 2a49700

Please sign in to comment.