verilator/test_regress/t/t_dist_warn_coverage.py

234 lines
9.2 KiB
Python
Raw Normal View History

2024-09-08 19:00:03 +02:00
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('dist')
Messages = {}
Outputs = {}
Suppressed = {}
for s in [
# Cannot hit, and comment as to why
# Instead of adding here, consider adding a LCOV_EXCL_LINE/START/STOP to the sources on the message
2024-09-08 19:00:03 +02:00
' exited with ', # Is hit; driver.py filters out
2025-05-17 22:28:09 +02:00
' loading non-variable', # Instead 'storing to parameter' or syntax error
2025-05-17 04:32:25 +02:00
'Assigned pin is neither input nor output', # Instead earlier error
'Define missing argument \'', # Instead get Define passed too many arguments
'Define or directive not defined: `', # Instead V3ParseImp will warn
'Expecting define formal arguments. Found: ', # Instead define syntax error
'Syntax error: Range \':\', \'+:\' etc are not allowed in the instance ', # Instead get syntax error
2024-09-08 19:00:03 +02:00
'dynamic new() not expected in this context (expected under an assign)', # Instead get syntax error
# Not yet analyzed
'--pipe-filter protocol error, unexpected: ',
2025-03-24 00:51:54 +01:00
'--pipe-filter returned bad status',
2024-09-08 19:00:03 +02:00
'Array initialization has too few elements, need element ',
'Assignment pattern with no members',
'Can\'t find varpin scope of ',
2025-03-24 00:51:54 +01:00
'Can\'t read annotation file: ',
2024-09-08 19:00:03 +02:00
'Can\'t resolve module reference: \'',
2025-03-24 00:51:54 +01:00
'Can\'t write file: ',
'Expected data type, not a ',
2024-09-08 19:00:03 +02:00
'Extern declaration\'s scope is not a defined class',
2025-03-24 00:51:54 +01:00
'File not found: ',
2024-09-08 19:00:03 +02:00
'Format to $display-like function must have constant format string',
'Forward typedef used as class/package does not resolve to class/package: ',
'Illegal +: or -: select; type already selected, or bad dimension: ',
'Illegal bit or array select; type already selected, or bad dimension: ',
'Illegal range select; type already selected, or bad dimension: ',
'Interface port declaration ',
2024-09-08 19:00:03 +02:00
'Modport item is not a function/task: ',
'Modport item is not a variable: ',
'Modport not referenced as <interface>.',
'Modport not referenced from underneath an interface: ',
'Non-interface used as an interface: ',
2024-09-08 19:00:03 +02:00
'Parameter type pin value isn\'t a type: Param ',
'Parameter type variable isn\'t a type: Param ',
'Pattern replication value of 0 is not legal.',
'Signals inside functions/tasks cannot be marked forceable',
'Slice size cannot be zero.',
'Slices of arrays in assignments have different unpacked dimensions, ',
'String of ',
'Symbol matching ',
'Unexpected connection to arrayed port',
'Unsized numbers/parameters not allowed in streams.',
'Unsupported RHS tristate construct: ',
'Unsupported or syntax error: Unsized range in instance or other declaration',
'Unsupported pullup/down (weak driver) construct.',
'Unsupported tristate port expression: ',
'Unsupported: $bits for queue',
2024-09-22 15:10:03 +02:00
'Unsupported: &&& expression',
2024-09-08 19:00:03 +02:00
'Unsupported: 4-state numbers in this context',
2024-09-22 15:10:03 +02:00
'Unsupported: Bind with instance list',
2024-09-08 19:00:03 +02:00
'Unsupported: Concatenation to form ',
2024-09-22 15:10:03 +02:00
'Unsupported: Modport dotted port name',
'Unsupported: Modport export with prototype',
'Unsupported: Modport import with prototype',
2024-09-08 19:00:03 +02:00
'Unsupported: Only one PSL clock allowed per assertion',
'Unsupported: Per-bit array instantiations ',
'Unsupported: Public functions with >64 bit outputs; ',
'Unsupported: Replication to form ',
'Unsupported: Size-changing cast on non-basic data type',
'Unsupported: Slice of non-constant bounds',
'Unsupported: Unclocked assertion',
2024-09-22 15:10:03 +02:00
'Unsupported: Verilog 1995 deassign',
'Unsupported: Verilog 1995 gate primitive: ',
'Unsupported: [] dimensions',
2025-03-24 00:51:54 +01:00
'Unsupported: \'default :/\' constraint',
'Unsupported: \'{} .* patterns',
2024-09-22 15:10:03 +02:00
'Unsupported: assertion items in clocking blocks',
2024-09-08 19:00:03 +02:00
'Unsupported: don\'t know how to deal with ',
2024-09-22 15:10:03 +02:00
'Unsupported: extern forkjoin',
'Unsupported: extern task',
2025-03-24 00:51:54 +01:00
'Unsupported: modport export',
'Unsupported: no_inline for tasks',
2024-09-22 15:10:03 +02:00
'Unsupported: property port \'local\'',
'Unsupported: repeat event control',
2025-03-24 00:51:54 +01:00
'Unsupported: static cast to ',
'Unsupported: super',
2024-09-22 15:10:03 +02:00
'Unsupported: with[] stream expression',
2024-09-08 19:00:03 +02:00
]:
Suppressed[s] = True
def read_messages():
for filename in test.glob_some(test.root + "/src/*"):
2024-09-08 19:00:03 +02:00
if not os.path.isfile(filename):
continue
if '#' in filename:
continue
2024-09-08 19:00:03 +02:00
with open(filename, 'r', encoding="utf8") as fh:
lineno = 0
read_next = None
excl = False
excl_next = False
2024-09-08 19:00:03 +02:00
for origline in fh:
line = origline
lineno += 1
if re.match(r'^\s*//', line):
continue
if re.match(r'^\s*/\*', line):
continue
excl = excl_next
if 'LCOV_EXCL_START' in line:
excl = True
excl_next = True
if 'LCOV_EXCL_STOP' in line:
excl_next = False # Reenables coverage on next line, not this one
2025-03-24 00:51:54 +01:00
if re.search(r'\b(v3error|v3warn|v3fatal|BBUNSUP)\b\($', line):
2024-09-08 19:00:03 +02:00
if 'LCOV_EXCL_LINE' not in line:
read_next = True
continue
2025-03-24 00:51:54 +01:00
m = re.search(r'.*\b(v3error|v3warn|v3fatal|BBUNSUP)\b(.*)', line)
2024-09-08 19:00:03 +02:00
if m:
line = m.group(2)
if 'LCOV_EXCL_LINE' not in line:
read_next = True
if read_next:
read_next = False
if 'LCOV_EXCL_LINE' in line:
continue
if excl:
continue
2024-09-08 19:00:03 +02:00
if "\\" in line: # \" messes up next part
continue
m = re.search(r'"([^"]*)"', line)
if m:
msg = m.group(1)
fileline = filename + ":" + str(lineno)
# print("FFFF " + fileline + ": " + msg + " LL " + line)
Messages[msg] = {}
Messages[msg]['fileline'] = fileline
Messages[msg]['line'] = origline
print("Number of messages = " + str(len(Messages)))
def read_outputs():
for filename in (test.glob_some(test.root + "/test_regress/t/*.py") +
test.glob_some(test.root + "/test_regress/t/*.out") +
test.glob_some(test.root + "/docs/gen/*.rst")):
2024-09-08 19:00:03 +02:00
if "t_dist_warn_coverage" in filename: # Avoid our own suppressions
continue
with open(filename, 'r', encoding="latin-1") as fh:
for line in fh:
if re.match(r'^\$date', line): # Assume it is a VCD file
break
line = line.lstrip().rstrip()
Outputs[line] = True
print("Number of outputs = " + str(len(Outputs)))
def check():
read_messages()
read_outputs()
print("Number of suppressions = " + str(len(Suppressed)))
2025-05-17 22:28:09 +02:00
print("Coverage = %3.1f%%" % (100 - (100 * len(Suppressed) / len(Messages))))
2024-09-08 19:00:03 +02:00
print()
print("Checking for v3error/v3warn messages in sources without")
print("coverage in test_regress/t/*.out:")
2025-03-24 00:51:54 +01:00
print("(Developers: If a message is impossible to test, consider using")
print("UASSERT or v3fatalSrc instead of v3error)")
2024-09-08 19:00:03 +02:00
print()
used_suppressed = {}
for msg in sorted(Messages.keys()):
fileline = Messages[msg]['fileline']
next_msg = False
for output in Outputs:
if msg in output:
# print(fileline+": M '" + msg + "' HIT '" + output)
next_msg = True
break
if next_msg:
continue
# Some exceptions
if re.match(r'internal:', msg, re.IGNORECASE):
continue
line = Messages[msg]['line']
line = line.lstrip().rstrip()
if msg in Suppressed:
used_suppressed[msg] = True
if test.verbose:
print(fileline + ": Suppressed check for message in source: '" + msg + "'")
else:
2024-09-22 15:10:03 +02:00
test.error_keep_going(fileline +
": Missing test_regress/t/*.out test for message in source: '" +
msg + "'")
2024-09-08 19:00:03 +02:00
if test.verbose:
print(" Line is: " + line)
print()
for msg in sorted(Suppressed.keys()):
if msg not in used_suppressed:
print("Suppression not used: '" + msg + "'")
print()
if not os.path.exists(test.root + "/.git"):
2024-09-08 19:00:03 +02:00
test.skip("Not in a git repository")
check()
test.passes()
# Local Variables:
# compile-command:"./t_dist_warn_coverage.py"
# End: