coverage: Update scripts
- Update coverage scripts to parse new tarmac format
- Update script command line arguments to take in specific binaries to
generate report for
- Make genhtml a separate step from this script
Change-Id: I9f39b1e4f305b3428189f858088f23c979c8b9a4
Signed-off-by: Jackson Cooper-Driver <jackson.cooper-driver@arm.com>
diff --git a/code_coverage/generate_report_config_json.py b/code_coverage/generate_report_config_json.py
index 08c399a..d5afe0a 100755
--- a/code_coverage/generate_report_config_json.py
+++ b/code_coverage/generate_report_config_json.py
@@ -1,6 +1,6 @@
#!/usr/bin/python3
# -----------------------------------------------------------------------------
-# Copyright (c) 2024, Arm Limited. All rights reserved.
+# Copyright (c) 2024-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -52,6 +52,7 @@
parser.add_argument("--output_config_file", help="output JSON file", required=True)
parser.add_argument("--output_intermediate_file", help="output intermediate file", required=True)
parser.add_argument("trace_file", nargs="+", help="input trace log files")
+parser.add_argument("--filter_elfs", help="comma-separated list of ELF files to generate report for", required=False)
args = parser.parse_args()
# logging setup
@@ -88,6 +89,9 @@
bin_dir = join(args.build_dir, "bin")
elf_files = [join(bin_dir, x) for x in listdir(bin_dir) if isfile(join(bin_dir, x)) and "elf" in x]
+if args.filter_elfs:
+ elf_files = [x for x in elf_files for f in args.filter_elfs.split(",") if f in x]
+
elfs = [
{
"name": x,
diff --git a/code_coverage/ingest_tarmac.py b/code_coverage/ingest_tarmac.py
index 64d9251..bc386e0 100755
--- a/code_coverage/ingest_tarmac.py
+++ b/code_coverage/ingest_tarmac.py
@@ -1,6 +1,6 @@
#!/usr/bin/python3
# -----------------------------------------------------------------------------
-# Copyright (c) 2024, Arm Limited. All rights reserved.
+# Copyright (c) 2024-2025, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -10,12 +10,28 @@
import logging
import re
import elftools
+from itertools import islice
-def parse_line(line: str) -> str:
+def parse_line_fvp(line: str) -> str:
split = line.split(" ")
- addr = split[5]
- size = len(split[6]) // 2
- logging.debug("Instruction at {} of size {}".format(addr, size))
+ try:
+ addr = split[5]
+ size = len(split[6]) // 2
+ logging.debug("Instruction at {} of size {}".format(addr, size))
+ except Exception as e:
+ print("Parse error {} for line {}".format(e,line))
+ raise Exception
+ return (addr, size)
+
+def parse_line_rtl(line: str) -> str:
+ try:
+ split = line.split(" ")[1].replace("(", "").replace(")", "").split(":")
+ addr = split[0]
+ size = len(split[1]) // 2
+ logging.debug("Instruction at {} of size {}".format(addr, size))
+ except Exception as e:
+ print("Parse error {} for line {}".format(e,line))
+ raise Exception
return (addr, size)
parser = argparse.ArgumentParser()
@@ -27,19 +43,26 @@
# logging setup
logging.basicConfig(level=args.log_level)
-with open(args.input_file, "rt") as input_file:
- trace = input_file.read()
-
-instructions = re.findall("[0-9]* [a-z]{2} [a-z\.]* IT .*", trace)
-
+instructions = []
+parse_function = parse_line_fvp
hit_counts = {}
-for i in instructions:
- addr = parse_line(i)
- if addr in hit_counts.keys():
- hit_counts[addr] += 1
- else:
- hit_counts[addr] = 1
+with open(args.input_file, "rt") as input_file:
+ while(lines := list(islice(input_file, 100000))):
+ lines = ''.join(lines)
+ chunk_instructions = re.findall(r'[0-9]* [a-z]{3} [a-z\.]* IT .*', lines)
+
+ if len(chunk_instructions) == 0:
+ chunk_instructions = re.findall(r'[0-9]* clk ES (.*:.*).*', lines)
+ if len(chunk_instructions) != 0:
+ parse_function = parse_line_rtl
+
+ for i in chunk_instructions:
+ addr = parse_function(i)
+ if addr in hit_counts.keys():
+ hit_counts[addr] += 1
+ else:
+ hit_counts[addr] = 1
with open(args.output_file, "w+") as output_file:
output_file.writelines(["{} {} {}\n".format(x[0], hit_counts[x], x[1]) for x in hit_counts.keys()])
diff --git a/code_coverage/tfm_generate_coverage_report.sh b/code_coverage/tfm_generate_coverage_report.sh
index fe0853a..1074fcb 100755
--- a/code_coverage/tfm_generate_coverage_report.sh
+++ b/code_coverage/tfm_generate_coverage_report.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-# Copyright (c) 2024, Arm Limited. All rights reserved.
+# Copyright (c) 2024-2025, Arm Limited. All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
error()
@@ -15,10 +15,10 @@
}
usage() {
- echo "$0 --source_dir <source_dir> --build_dir <build_dir> --output_dir <output_dir> data_file [data_file ...]"
+ echo "$0 --source_dir <source_dir> --build_dir <build_dir> [--filter_elfs \"foo.elf,bar.elf\"] --output_file <output_file> data_file [data_file ...]"
}
-set -ex
+set -e
SCRIPT_DIR="$( dirname "${BASH_SOURCE[0]}")"
@@ -35,8 +35,13 @@
shift
shift
;;
- -b|--output_dir)
- OUTPUT_DIR="$2"
+ -f|--filter_elfs)
+ ELF_FILTER="--filter_elfs $2"
+ shift
+ shift
+ ;;
+ -b|--output_file)
+ OUTPUT_FILE="$2"
shift
shift
;;
@@ -62,7 +67,7 @@
error "No build dir specified"
fi
-if test -z "$OUTPUT_DIR"
+if test -z "$OUTPUT_FILE"
then
usage
error "No output dir specified"
@@ -93,6 +98,7 @@
${SCRIPT_DIR}/generate_report_config_json.py \
--source_dir "${SOURCE_DIR}" \
--build_dir "${BUILD_DIR}" \
+ ${ELF_FILTER} \
--output_config_file "${tmpdir}/$(basename "$x")_config.json" \
--output_intermediate_file "${tmpdir}/$(basename "$x")_intermediate.json" \
"$input_file"
@@ -119,4 +125,4 @@
info_file=$(find "$info_dir" -type f)
fi
-genhtml --branch-coverage "${info_file}" --output-directory "$OUTPUT_DIR"
+cp "${info_file}" "${OUTPUT_FILE}"