118 lines
4.3 KiB
Python
118 lines
4.3 KiB
Python
# pylint: disable=R0914
|
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify it
|
|
# under the terms of either the GNU Lesser General Public License Version 3
|
|
# or the Perl Artistic License Version 2.0.
|
|
# SPDX-FileCopyrightText: 2026 Wilson Snyder
|
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
|
|
import os
|
|
import re
|
|
|
|
|
|
def run(test, *, verilator_flags2=()):
|
|
variant, fmt = test.parse_name(r"t_trace_lib_(default|notop)_([a-z]+)")
|
|
|
|
# All test use the same SV file
|
|
test.top_filename = "t/t_trace_lib.v"
|
|
# Any variations after the format name must yield the exact same trace
|
|
test.golden_filename = test.py_filename.rpartition(fmt)[0] + fmt + ".out"
|
|
|
|
verilator_common_flags = [
|
|
"--cc",
|
|
"--trace-threads",
|
|
"1",
|
|
f"--trace-{fmt}",
|
|
"--trace-underscore", # Should not trace __Vhandle
|
|
"--trace-max-width",
|
|
"0",
|
|
"--trace-max-array",
|
|
"0",
|
|
"--trace-structs"
|
|
]
|
|
|
|
main_top_name = "top"
|
|
match variant:
|
|
case "default":
|
|
pass
|
|
case "notop":
|
|
main_top_name = ""
|
|
case _:
|
|
test.error(f"Unhandled test variant '{variant}'")
|
|
|
|
verilator_common_flags.extend(verilator_flags2)
|
|
|
|
# Compile sub0 --lib-create
|
|
test.vm_prefix = "Vsub0"
|
|
test.compile(make_main=False,
|
|
threads=1,
|
|
verilator_make_gmake=False,
|
|
verilator_flags2=verilator_common_flags + [
|
|
"+define+SUB0",
|
|
"--lib-create",
|
|
"sub0",
|
|
"--top-module",
|
|
"sub0",
|
|
])
|
|
test.run(logfile=test.obj_dir + "/Vsub0_make.log",
|
|
cmd=[os.environ["MAKE"], "-C", test.obj_dir, "-f", "Vsub0.mk", "libsub0.a"])
|
|
# Compile sub1 --lib-create
|
|
test.vm_prefix = "Vsub1"
|
|
test.compile(make_main=False,
|
|
threads=1,
|
|
verilator_make_gmake=False,
|
|
verilator_flags2=verilator_common_flags + [
|
|
"+define+SUB1",
|
|
"--lib-create",
|
|
"sub1",
|
|
"--top-module",
|
|
"sub1",
|
|
])
|
|
test.run(logfile=test.obj_dir + "/Vsub1_make.log",
|
|
cmd=[os.environ["MAKE"], "-C", test.obj_dir, "-f", "Vsub1.mk", "libsub1.a"])
|
|
# Compile top with libraries
|
|
test.vm_prefix = "Vlibs"
|
|
test.compile(main_top_name=main_top_name,
|
|
verilator_flags2=verilator_common_flags + [
|
|
"+define+TOP", test.obj_dir + "/sub0.sv", "libsub0.a",
|
|
test.obj_dir + "/sub1.sv", "libsub1.a"
|
|
])
|
|
|
|
# Compile simply without libraries
|
|
test.vm_prefix = "Vnonl"
|
|
test.main_filename = test.obj_dir + "/Vnonl__main.cpp"
|
|
test.compile(main_top_name=main_top_name,
|
|
verilator_flags2=verilator_common_flags +
|
|
["+define+TOP", "+define+SUB0", "+define+SUB1"])
|
|
|
|
trace_libs = test.trace_filename.replace("simx", "libs")
|
|
trace_nonl = test.trace_filename.replace("simx", "nonl")
|
|
|
|
# Run the --lib-create model
|
|
test.execute(executable=test.obj_dir + "/Vlibs")
|
|
test.run(cmd=["mv", test.trace_filename, trace_libs])
|
|
# Run the simple model without libraries
|
|
test.execute(executable=test.obj_dir + "/Vnonl")
|
|
test.run(cmd=["mv", test.trace_filename, trace_nonl])
|
|
|
|
# Scope structure must match exactly, check only in vcd
|
|
if fmt == "vcd":
|
|
with open(trace_nonl, 'r', encoding='utf8') as fnonl, \
|
|
open(trace_libs, 'r', encoding='utf8') as flibs:
|
|
for la, lb in zip(fnonl, flibs):
|
|
la = re.sub(r'^(\s*\$var\s+\S+\s+\S+\s+)\S+(.*)$', r'\1CODE\2', la)
|
|
lb = re.sub(r'^(\s*\$var\s+\S+\s+\S+\s+)\S+(.*)$', r'\1CODE\2', lb)
|
|
if la != lb:
|
|
test.error_keep_going("VCD header mismatch: '{}' !~ '{}'".format(
|
|
la.strip(), lb.strip()))
|
|
if "enddefinitions" in la:
|
|
break
|
|
|
|
# The two models must match ignoring enum attributes which can differ
|
|
test.trace_identical(trace_libs, trace_nonl, ignore_attr=True)
|
|
# The --lib-create must match the reference
|
|
test.trace_identical(trace_libs, test.golden_filename)
|
|
|
|
test.passes()
|