| #!/usr/bin/env python3 |
| # Copyright lowRISC contributors. |
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| # SPDX-License-Identifier: Apache-2.0 |
| |
| import logging |
| from pathlib import Path, PurePath |
| from pprint import pformat |
| from typing import List |
| |
| from device_profile_data import extract_profile_data |
| from common import ( |
| BAZEL, |
| LLD_TARGET, |
| BazelTestType, |
| CoverageParams, |
| run, |
| ) |
| |
| # Commands that this script uses |
| LLVM_PROFDATA = "llvm-profdata" |
| |
| # Bazel target for locally spliced test ROM bitstream |
| BITSTREAM_TARGET = "//hw/bitstream:gcp_spliced_test_rom" |
| |
| |
| def handle_libs(device_libs_all: List[str]) -> List[str]: |
| """Filter device libraries that are not compatible with the target. |
| |
| Args: |
| device_libs_all: A list of device libraries. |
| |
| Returns: |
| `device_libs_all` with incompatible libraries filtered out. |
| """ |
| # Remove on_host libs |
| device_libs_incompat = [lib for lib in device_libs_all if "on_host" in lib] |
| logging.info(f"incompatible libraries: {pformat(device_libs_incompat)}") |
| # TODO: may want to add the coverage runtime to avoid undefined symbol warnings |
| return sorted(list(set(device_libs_all) - set(device_libs_incompat))) |
| |
| |
| def handle_objs(merged_library: Path, obj_files: List[str]) -> None: |
| """Create a library from the given object files. |
| |
| Args: |
| merged_library: Path where to save the merged library. |
| obj_files: A list of object files. |
| """ |
| # Note: We allow unresolved symbols and multiple definitions because this library is |
| # used only for generating a coverage report and we link only and all instrumented |
| # object files. |
| # TODO(#16761): Try to remove these flags. |
| run(LLD_TARGET, "--warn-unresolved-symbols", "-zmuldefs", "-o", |
| str(merged_library), *obj_files) |
| |
| |
| def handle_test_targets(test_targets: List[str]) -> List[str]: |
| """Choose cw310_test_rom tests from the given list of tests. |
| |
| This function also |
| - Programs the FPGA with the non-instrumented test ROM since the instrumented one |
| overflows the ROM memory, and |
| - Filters wycheproof tests since they take a long time to run. |
| |
| Args: |
| test_targets: A list of test targets. |
| |
| Returns: |
| cw310_test_rom tests without wycheproof tests. |
| """ |
| # Instrumented ROM overflows the space allocated for ROM. Program the fpga with the |
| # non-instrumented test ROM and skip bitstream loading during tests. |
| run(BAZEL, "build", BITSTREAM_TARGET) |
| [workspace] = run(BAZEL, "info", "workspace") |
| [bitstream] = run(BAZEL, "cquery", "--output=starlark", "--starlark:expr", |
| "target.files.to_list()[0].path", BITSTREAM_TARGET) |
| bitstream_path = PurePath(workspace) / PurePath(bitstream) |
| run(BAZEL, "run", "//sw/host/opentitantool", "--", "fpga", |
| "load-bitstream", str(bitstream_path)) |
| return [ |
| t for t in test_targets |
| if "cw310_test_rom" in t and "wycheproof" not in t |
| ] |
| |
| |
| def handle_test_log_dirs(test_log_dirs: List[Path]) -> List[Path]: |
| """Get coverage profiles. |
| |
| This function processes the logs in the given list of test log directories to |
| produce raw profiles and returns their paths. These profiles can then be indexed and |
| merged to produce a single profile file. |
| |
| Args: |
| test_log_dirs: A list of test log directories. |
| |
| Returns: |
| Paths of individual raw coverage profiles. |
| |
| """ |
| raw_profiles = [] |
| for d in test_log_dirs: |
| with (Path(d) / "test.log").open("rb") as test_log, ( |
| Path(d) / "prof.raw").open("wb") as raw_profile: |
| raw_profile.write( |
| extract_profile_data(test_log.read().decode("ascii", |
| "ignore"))) |
| raw_profiles += [Path(raw_profile.name)] |
| logging.info(f"raw profiles: {pformat(raw_profiles)}") |
| return raw_profiles |
| |
| |
| PARAMS = CoverageParams( |
| bazel_test_type=BazelTestType.SH_TEST, |
| config="ot_coverage_on_target", |
| libs_fn=handle_libs, |
| objs_fn=handle_objs, |
| test_targets_fn=handle_test_targets, |
| test_log_dirs_fn=handle_test_log_dirs, |
| report_title="OpenTitan Functional Test Coverage", |
| ) |