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}"