Skip to content

Commit

Permalink
Add support for Verilator Coverage (#143)
Browse files Browse the repository at this point in the history
The coverage Python scripts are from the XiangShan repo. Author: Zhigang Liu.
  • Loading branch information
poemonsense authored Sep 10, 2023
1 parent 4304336 commit 8d059e4
Show file tree
Hide file tree
Showing 5 changed files with 508 additions and 3 deletions.
13 changes: 13 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,16 @@ jobs:
make clean
make emu EMU_THREADS=2
./build/emu -b 0 -e 0 -i ./ready-to-run/microbench.bin --diff ./ready-to-run/riscv64-nemu-interpreter-so
- name: Difftest with Verilator Coverage
run: |
cd $GITHUB_WORKSPACE/../xs-env
source ./env.sh
cd $GITHUB_WORKSPACE/../xs-env/NutShell
source ./env.sh
make clean
rm -rf *.coverage
make emu EMU_COVERAGE=1
./build/emu -e 0 -i ./ready-to-run/microbench.bin --diff ./ready-to-run/riscv64-nemu-interpreter-so -C 10000 --dump-coverage
make -C difftest coverage
ls -lh *.coverage
111 changes: 111 additions & 0 deletions scripts/coverage/coverage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#/usr/bin/python3
# -*- coding: UTF-8 -*-

#***************************************************************************************
# Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
# Copyright (c) 2020-2021 Peng Cheng Laboratory
#
# XiangShan is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
# http://license.coscl.org.cn/MulanPSL2
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#
# See the Mulan PSL v2 for more details.
#***************************************************************************************

import sys
import re
import copy

if __name__ == "__main__":
assert len(sys.argv) == 3, "Expect input_file and output_file"
input_file = sys.argv[1]
output_file = sys.argv[2]
lines = []
line_count = 0
synthesis_nest_level = 0
reg_init_nest_level = 0
mem_init_nest_level = 0
with open(input_file) as f:
for line in f:
line_count += 1

ifdef = re.compile('`ifdef')
ifndef = re.compile('`ifndef')
endif = re.compile('`endif')
# remove the line coverage results of not synthesizable code(mostly assert and fwrite)
synthesis = re.compile('`ifndef SYNTHESIS')
# remove the coverage results of random init variables
reg_init = re.compile('`ifdef RANDOMIZE_REG_INIT')
mem_init = re.compile('`ifdef RANDOMIZE_MEM_INIT')
coverage = re.compile('^\s*(%?\d+)\s+')


ifdef_match = ifdef.search(line)
ifndef_match = ifndef.search(line)
endif_match = endif.search(line)
synthesis_match = synthesis.search(line)
reg_init_match = reg_init.search(line)
mem_init_match = mem_init.search(line)
coverage_match = coverage.search(line)

# enter synthesis block
if synthesis_match:
assert synthesis_nest_level == 0, "Should not nest SYNTHESIS macro"
synthesis_nest_level = 1

if synthesis_nest_level > 0:
if ifdef_match or (ifndef_match and not synthesis_match):
synthesis_nest_level += 1
if endif_match:
synthesis_nest_level -= 1
assert synthesis_nest_level >= 0, "Macro nest level should be >= 0"

# remove line coverage results in systhesis block
if coverage_match:
coverage_stat = coverage_match.group(1)
line = line.replace(coverage_match.group(1), " " * len(coverage_stat))

# enter reg_init block
if reg_init_match:
assert reg_init_nest_level == 0, "Should not nest reg_init macro"
reg_init_nest_level = 1

if reg_init_nest_level > 0:
if (ifdef_match and not reg_init_match) or ifndef_match:
reg_init_nest_level += 1
if endif_match:
reg_init_nest_level -= 1
assert reg_init_nest_level >= 0, "Macro nest level should be >= 0"

# remove line coverage results in systhesis block
if coverage_match:
coverage_stat = coverage_match.group(1)
line = line.replace(coverage_match.group(1), " " * len(coverage_stat))

# enter mem_init block
if mem_init_match:
assert mem_init_nest_level == 0, "Should not nest mem_init macro"
mem_init_nest_level = 1

if mem_init_nest_level > 0:
if (ifdef_match and not mem_init_match) or ifndef_match:
mem_init_nest_level += 1
if endif_match:
mem_init_nest_level -= 1
assert mem_init_nest_level >= 0, "Macro nest level should be >= 0"

# remove line coverage results in systhesis block
if coverage_match:
coverage_stat = coverage_match.group(1)
line = line.replace(coverage_match.group(1), " " * len(coverage_stat))

lines += line

with open(output_file, "w") as f:
for line in lines:
f.write(line)
Loading

0 comments on commit 8d059e4

Please sign in to comment.