admin管理员组文章数量:1345891
I'm working with GHDL (GHDL - v6.0.0-dev - Ubuntu 24.04 (x86-64, LTS) - gcc backend) and LCOV to analyze code coverage for VHDL projects, but I'm encountering unexpected behavior in the branch coverage reporting. The
Issue: LCOV is showing branch coverage metrics for lines of code that don't appear to contain actual branches.
Question:
How can I configure LCOV or GHDL to prevent branch coverage reporting for non-branch operations in VHDL?
The full project code is available at:
Details:
Here's an example (lcov report) from a simple adder component:
Branch data Line data Source code
1 : 13 : entity adder is
2 : : -- `i0`, `i1` and the carry-in `ci` are inputs of the adder.
3 : : -- `s` is the sum output, `co` is the carry-out.
4 : : port (i0, i1 : in bit; ci : in bit; s : out bit; co : out bit);
5 : : end adder;
6 : :
7 : 2 : architecture rtl of adder is
8 : : begin
9 : : -- This full-adder architecture contains two concurrent assignment.
10 : : -- Compute the sum.
11 [ - + + + ]: 17 : s <= i0 xor i1 xor ci;
12 : : -- Compute the carry.
13 [ + + + + : 10 : co <= (i0 and i1) or (i0 and ci) or (i1 and ci);
+ + + + +
+ - + +
+ ]
14 : : end rtl;
15 : :
Note that line 11 (s <= i0 xor i1 xor ci;) shows branch coverage data ([ - + + + ]) despite being a simple XOR operation with no explicit branches. I would expect branch coverage to only appear for control flow statements like if, case, etc.
Additional Output from gcov Here's the raw .gcov output from running gcov -b -c -s . adder.vhd, which may help clarify what's happening under the hood:
-: 0:Source:/home/aaghmour/ghdl-coverage/projects/adder/adder.vhd
-: 0:Graph:adder.gcno
-: 0:Data:adder.gcda
-: 0:Runs:1
13: 1:entity adder is
-: 2: -- `i0`, `i1` and the carry-in `ci` are inputs of the adder.
-: 3: -- `s` is the sum output, `co` is the carry-out.
-: 4: port (i0, i1 : in bit; ci : in bit; s : out bit; co : out bit);
-: 5:end adder;
-: 6:
2: 7:architecture rtl of adder is
-: 8:begin
-: 9: -- This full-adder architecture contains two concurrent assignment.
-: 10: -- Compute the sum.
17*: 11: s <= i0 xor i1 xor ci;
-: 12: -- Compute the carry.
10*: 13: co <= (i0 and i1) or (i0 and ci) or (i1 and ci);
call 0 returned 1
branch 1 taken 4 (fallthrough)
branch 2 taken 4
branch 3 taken 6 (fallthrough)
branch 4 taken 2
branch 5 taken 2 (fallthrough)
branch 6 taken 4
branch 7 taken 5 (fallthrough)
branch 8 taken 3
branch 9 taken 2 (fallthrough)
branch 10 taken 3
branch 11 taken 0 (fallthrough)
branch 12 taken 8
branch 13 taken 3 (fallthrough)
branch 14 taken 5
call 15 returned 3
------------------
work__adder__ARCH__rtl__STMT_ELAB:
function work__adder__ARCH__rtl__STMT_ELAB called 1 returned 100% blocks executed 100%
1: 1:entity adder is
-: 2: -- `i0`, `i1` and the carry-in `ci` are inputs of the adder.
-: 3: -- `s` is the sum output, `co` is the carry-out.
-: 4: port (i0, i1 : in bit; ci : in bit; s : out bit; co : out bit);
-: 5:end adder;
-: 6:
1: 7:architecture rtl of adder is
call 0 returned 1
-: 8:begin
-: 9: -- This full-adder architecture contains two concurrent assignment.
-: 10: -- Compute the sum.
1: 11: s <= i0 xor i1 xor ci;
call 0 returned 1
call 1 returned 1
call 2 returned 1
call 3 returned 1
call 4 returned 1
-: 12: -- Compute the carry.
1: 13: co <= (i0 and i1) or (i0 and ci) or (i1 and ci);
call 0 returned 1
call 1 returned 1
call 2 returned 1
call 3 returned 1
call 4 returned 1
------------------
work__adder__ARCH__rtl__DECL_ELAB:
function work__adder__ARCH__rtl__DECL_ELAB called 1 returned 100% blocks executed 100%
1: 1:entity adder is
-: 2: -- `i0`, `i1` and the carry-in `ci` are inputs of the adder.
-: 3: -- `s` is the sum output, `co` is the carry-out.
-: 4: port (i0, i1 : in bit; ci : in bit; s : out bit; co : out bit);
-: 5:end adder;
-: 6:
1: 7:architecture rtl of adder is
------------------
work__adder__ARCH__rtl__P0__PROC:
function work__adder__ARCH__rtl__P0__PROC called 8 returned 100% blocks executed 83%
8: 1:entity adder is
-: 2: -- `i0`, `i1` and the carry-in `ci` are inputs of the adder.
-: 3: -- `s` is the sum output, `co` is the carry-out.
-: 4: port (i0, i1 : in bit; ci : in bit; s : out bit; co : out bit);
-: 5:end adder;
-: 6:
-: 7:architecture rtl of adder is
-: 8:begin
-: 9: -- This full-adder architecture contains two concurrent assignment.
-: 10: -- Compute the sum.
8*: 11: s <= i0 xor i1 xor ci;
branch 0 taken 0 (fallthrough)
branch 1 taken 8
branch 2 taken 5 (fallthrough)
branch 3 taken 3
call 4 returned 5
------------------
work__adder__STMT_ELAB:
function work__adder__STMT_ELAB called 1 returned 100% blocks executed 100%
1: 1:entity adder is
------------------
work__adder__DECL_ELAB:
function work__adder__DECL_ELAB called 1 returned 100% blocks executed 100%
1: 1:entity adder is
call 0 returned 1
call 1 returned 1
call 2 returned 1
call 3 returned 1
call 4 returned 1
------------------
work__adder__PKG_ELAB:
function work__adder__PKG_ELAB called 1 returned 100% blocks executed 100%
1: 1:entity adder is
------------------
-: 14:end rtl;
-: 15:
My Code and Build Process Here's the full adder code:
entity adder is
-- `i0`, `i1` and the carry-in `ci` are inputs of the adder.
-- `s` is the sum output, `co` is the carry-out.
port (i0, i1 : in bit; ci : in bit; s : out bit; co : out bit);
end adder;
architecture rtl of adder is
begin
-- This full-adder architecture contains two concurrent assignment.
-- Compute the sum.
s <= i0 xor i1 xor ci;
-- Compute the carry.
co <= (i0 and i1) or (i0 and ci) or (i1 and ci);
end rtl;
And here's the **Makefile **I'm using to build, run, and generate reports:
# Specify target
PROJECT = adder
################################################################################
# Defs
PROJ_DIR = projects
TB_EXTENSION = _tb
BUILD = build
################################################################################
# Sources
SRCS := $(shell find $(PROJ_DIR)/$(PROJECT)/ -type f -name "*.vhd")
OBJS := $(addprefix $(BUILD)/, $(notdir $(patsubst %.vhd,%.o,$(SRCS))))
TB = $(PROJECT)$(TB_EXTENSION)
################################################################################
# Executables
GHDL_COV_FLGAS = -Wc,-fprofile-arcs -Wc,-ftest-coverage
GHDL_ANALYZE = ghdl -a --workdir=.
GHDL_ELAB = ghdl -e --workdir=. -Wl,-lgcov
GHDL_RUN = ghdl -r --workdir=.
GCOV = gcov
LCOV = lcov -c --rc branch_coverage=1 --ignore-errors mismatch
GENHTML = genhtml --rc genhtml_branch_coverage=1
RM = rm -rf
################################################################################
# Output files
all: run
run: $(TB)
cd $(BUILD)/ && $(GHDL_RUN) $(TB)
cd $(BUILD)/ && $(GCOV) -s . $(PROJECT).vhd
cd $(BUILD)/ && $(LCOV) -d . -o $(PROJECT)$(TB_EXTENSION).info
cd $(BUILD)/ && $(GENHTML) -o html $(PROJECT)$(TB_EXTENSION).info
$(TB) : $(OBJS)
cd $(BUILD)/ && $(GHDL_ELAB) $@
# GHDL_COV_FLGAS only if not tb file
cov_flags=$(if $(findstring _tb,$(1)),,$(GHDL_COV_FLGAS))
$(OBJS) : $(SRCS)
cd $(BUILD)/ && $(GHDL_ANALYZE) $(call cov_flags,$(notdir $@)) ../$(addprefix $(PROJ_DIR)/$(PROJECT)/,$(notdir $(patsubst %.o,%.vhd,$@)))
clean:
$(RM) $(BUILD)/*
.PHONY: all run clean
My Environment Ubuntu 24.04.2 LTS GHDL version: 6.0.0-dev (4.1.0.r593.gdd13f1d38) [Dunoon edition] GCC version: 13.3.0 (Ubuntu 13.3.0-6ubuntu2~24.04) LCOV version: 2.0-1
版权声明:本文标题:LCOV reporting branch coverage for non-branch lines in VHDL code - bug or expected behavior? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1743819126a2544468.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论