blob: 9408778703cb8f65c7635657443742687ed46af8 [file] [log] [blame]
Srikrishna Iyer39ffebd2020-03-30 11:53:12 -07001#!/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"""
6This script provides common DV simulation specific utilities.
7"""
8
9import re
10from 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
20def 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.
37def 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 Swarbrick6cc20112020-04-24 09:44:35 +010069 if items[metric]['total'] == 0:
70 values.append("-- %")
Srikrishna Iyer39ffebd2020-03-30 11:53:12 -070071 else:
72 value = items[metric]['covered'] / items[metric][
73 'total'] * 100
74 value = "{0:.2f} %".format(round(value, 2))
75 values.append(value)
Rupert Swarbrick6cc20112020-04-24 09:44:35 +010076 if metric == 'Score':
77 cov_total = value
Srikrishna Iyer39ffebd2020-03-30 11:53:12 -070078 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.
86def 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