Srikrishna Iyer | 39ffebd | 2020-03-30 11:53:12 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python3 |
| 2 | # Copyright lowRISC contributors. |
| 3 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 4 | # SPDX-License-Identifier: Apache-2.0 |
| 5 | """ |
| 6 | This script provides common DV simulation specific utilities. |
| 7 | """ |
| 8 | |
| 9 | import re |
| 10 | from collections import OrderedDict |
| 11 | |
| 12 | |
| 13 | # Capture the summary results as a list of lists. |
| 14 | # The text coverage report is passed as input to the function, in addition to |
| 15 | # the tool used. The tool returns a 2D list if the coverage report file was read |
| 16 | # and the coverage was extracted successfully. It returns a tuple of: |
| 17 | # List of metrics and values |
| 18 | # Final coverage total |
| 19 | # Error message, if failed |
| 20 | def get_cov_summary_table(cov_report_txt, tool): |
| 21 | try: |
| 22 | with open(cov_report_txt, 'r') as f: |
| 23 | if tool == 'xcelium': |
| 24 | return xcelium_cov_summary_table(f) |
| 25 | if tool == 'vcs': |
| 26 | return vcs_cov_summary_table(f) |
| 27 | |
| 28 | err_msg = "Unsupported tool for cov extraction: {}".format(tool) |
| 29 | return None, None, err_msg |
| 30 | |
| 31 | except Exception as e: |
| 32 | err_msg = "Exception occurred: {}".format(str(e)) |
| 33 | return None, None, err_msg |
| 34 | |
| 35 | |
| 36 | # Same desc as above, but specific to Xcelium and takes an opened input stream. |
| 37 | def xcelium_cov_summary_table(buf): |
| 38 | for line in buf: |
| 39 | if "name" in line: |
| 40 | # Strip the line and remove the unwanted "* Covered" string. |
| 41 | metrics = line.strip().replace("* Covered", "").split() |
| 42 | # Change first item to 'Score'. |
| 43 | metrics[0] = 'Score' |
| 44 | |
| 45 | # metric. |
| 46 | items = OrderedDict() |
| 47 | for metric in metrics: |
| 48 | items[metric] = {} |
| 49 | items[metric]['covered'] = 0 |
| 50 | items[metric]['total'] = 0 |
| 51 | # Next line is a separator. |
| 52 | line = buf.readline() |
| 53 | # Subsequent lines are coverage items to be aggregated. |
| 54 | for line in buf: |
| 55 | line = re.sub(r"%\s+\(", "%(", line) |
| 56 | values = line.strip().split() |
| 57 | for i, value in enumerate(values): |
| 58 | value = value.strip() |
| 59 | m = re.search(r"\((\d+)/(\d+)\)", value) |
| 60 | if m: |
| 61 | items[metrics[i]]['covered'] += int(m.group(1)) |
| 62 | items[metrics[i]]['total'] += int(m.group(2)) |
| 63 | items['Score']['covered'] += int(m.group(1)) |
| 64 | items['Score']['total'] += int(m.group(2)) |
| 65 | # Capture the percentages and the aggregate. |
| 66 | values = [] |
| 67 | cov_total = None |
| 68 | for metric in items.keys(): |
Rupert Swarbrick | 6cc2011 | 2020-04-24 09:44:35 +0100 | [diff] [blame] | 69 | if items[metric]['total'] == 0: |
| 70 | values.append("-- %") |
Srikrishna Iyer | 39ffebd | 2020-03-30 11:53:12 -0700 | [diff] [blame] | 71 | else: |
| 72 | value = items[metric]['covered'] / items[metric][ |
| 73 | 'total'] * 100 |
| 74 | value = "{0:.2f} %".format(round(value, 2)) |
| 75 | values.append(value) |
Rupert Swarbrick | 6cc2011 | 2020-04-24 09:44:35 +0100 | [diff] [blame] | 76 | if metric == 'Score': |
| 77 | cov_total = value |
Srikrishna Iyer | 39ffebd | 2020-03-30 11:53:12 -0700 | [diff] [blame] | 78 | return [metrics, values], cov_total, None |
| 79 | |
| 80 | # If we reached here, then we were unable to extract the coverage. |
| 81 | err_msg = "ParseError: coverage data not found!" |
| 82 | return None, None, err_msg |
| 83 | |
| 84 | |
| 85 | # Same desc as above, but specific to VCS and takes an opened input stream. |
| 86 | def vcs_cov_summary_table(buf): |
| 87 | for line in buf: |
| 88 | match = re.match("total coverage summary", line, re.IGNORECASE) |
| 89 | if match: |
| 90 | # Metrics on the next line. |
| 91 | line = buf.readline().strip() |
| 92 | metrics = line.split() |
| 93 | # Values on the next. |
| 94 | line = buf.readline().strip() |
| 95 | # Pretty up the values - add % sign for ease of post |
| 96 | # processing. |
| 97 | values = [] |
| 98 | for val in line.split(): |
| 99 | val += " %" |
| 100 | values.append(val) |
| 101 | # first row is coverage total |
| 102 | cov_total = values[0] |
| 103 | return [metrics, values], cov_total, None |
| 104 | |
| 105 | # If we reached here, then we were unable to extract the coverage. |
| 106 | err_msg = "ParseError: coverage data not found!" |
| 107 | return None, None, err_msg |