Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/vhdl/coverage/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ def post_run(results):
call(["gcovr", "coverage_data"])
else:
call(["gcovr", "-a", "coverage_data/gcovr.json"])
elif VU.get_simulator_name() == "nvc":
call(["nvc", "--cover-report", "coverage_data.ncdb", "-o", "output_coverage"])


VU = VUnit.from_argv()
Expand All @@ -28,6 +30,7 @@ def post_run(results):

LIB.set_sim_option("enable_coverage", True)

LIB.set_sim_option("nvc.elab_flags", ["--cover=branch,statement"])
LIB.set_compile_option("rivierapro.vcom_flags", ["-coverage", "bs"])
LIB.set_compile_option("rivierapro.vlog_flags", ["-coverage", "bs"])
LIB.set_compile_option("modelsim.vcom_flags", ["+cover=bs"])
Expand Down
24 changes: 23 additions & 1 deletion examples/vhdl/uart/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,19 @@

from pathlib import Path
from vunit import VUnit
from subprocess import call


def post_run(results):
results.merge_coverage(file_name="coverage_data")
if VU.get_simulator_name() == "ghdl":
if results._simulator_if._backend == "gcc":
call(["gcovr", "coverage_data"])
else:
call(["gcovr", "-a", "coverage_data/gcovr.json"])
elif VU.get_simulator_name() == "nvc":
call(["nvc", "--cover-report", "coverage_data.ncdb", "-o", "output_coverage"])


VU = VUnit.from_argv()
VU.add_vhdl_builtins()
Expand All @@ -27,4 +40,13 @@
VU.add_library("uart_lib").add_source_files(SRC_PATH / "*.vhd")
VU.add_library("tb_uart_lib").add_source_files(SRC_PATH / "test" / "*.vhd")

VU.main()
VU.set_sim_option("enable_coverage", True)

VU.set_sim_option("nvc.elab_flags", ["--cover=branch,statement"])
VU.set_compile_option("rivierapro.vcom_flags", ["-coverage", "bs"])
VU.set_compile_option("rivierapro.vlog_flags", ["-coverage", "bs"])
VU.set_compile_option("modelsim.vcom_flags", ["+cover=bs"])
VU.set_compile_option("modelsim.vlog_flags", ["+cover=bs"])
VU.set_compile_option("enable_coverage", True)

VU.main(post_run=post_run)
46 changes: 43 additions & 3 deletions vunit/sim_if/nvc.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import re
from sys import stdout # To avoid output catched in non-verbose mode
from ..exceptions import CompileError
from ..ostools import Process
from ..ostools import Process, file_exists
from . import SimulatorInterface, ListOfStringOption, StringOption
from . import run_command
from ._viewermixin import ViewerMixin
Expand Down Expand Up @@ -86,10 +86,11 @@ def __init__( # pylint: disable=too-many-arguments
self._project = None

self._vhdl_standard = None
self._coverage_test_dirs = set()
self._coverage_files = set()
(major, minor) = self.determine_version(prefix)
self._supports_jit = major > 1 or (major == 1 and minor >= 9)
self._ieee_warnings_global = major > 1 or (major == 1 and minor >= 16)
self._supports_coverage_merge = major > 1 or (major == 1 and minor >= 14)

if self.use_color:
environ["NVC_COLORS"] = "always"
Expand Down Expand Up @@ -135,7 +136,7 @@ def supports_coverage(cls):
"""
Returns True when the simulator supports coverage
"""
return False
return True

@classmethod
def supports_vhdl_call_paths(cls):
Expand Down Expand Up @@ -273,6 +274,12 @@ def simulate(
cmd += ["-e"]

cmd += config.sim_options.get("nvc.elab_flags", [])

if config.sim_options.get("enable_coverage", False):
coverage_file_path = str(Path(output_path) / "coverage.ncdb")
self._coverage_files.add(coverage_file_path)
cmd += [f"--cover-file={coverage_file_path}"]

if config.vhdl_configuration_name is not None:
cmd += [config.vhdl_configuration_name]
else:
Expand Down Expand Up @@ -329,3 +336,36 @@ def simulate(
subprocess.call(cmd)

return status

def merge_coverage(self, file_name, args=None):
"""
Merge coverage from all test cases.
"""

if not self._supports_coverage_merge:
LOGGER.error(
"Current nvc version does not support coverage database merge."
)
return

coverage_files = []

for coverage_file in self._coverage_files:
if file_exists(coverage_file):
coverage_files.append(coverage_file)
else:
LOGGER.warning("Missing coverage file: %s", coverage_file)

nvc_coverage_merge_cmd = [
"nvc",
"--cover-merge",
"-o",
f"{file_name}.ncdb",
]

nvc_coverage_merge_cmd.extend(coverage_files)

print(f"Merging coverage files into {file_name!s}.ncdb...")
nvc_coverage_merge_process = Process(nvc_coverage_merge_cmd, env=self.get_env())
nvc_coverage_merge_process.consume_output()
print("Done merging coverage files")