Search code examples
vhdlcode-coveragegcovghdl

GHDL + Code coverage using gcov (Ubuntu 16.04 LTS)


this page (from Arnim Läuger in 2005) explains that a tool chain {GHDL + gcov} can perform VHDL code coverage.

Question : Is it still working today with recent versions of GCC, GCOV and GHDL?

The following command fails

$ ghdl -a -Wc,-ftest-coverage -Wc,-fprofile-arcs tb_example.vhd 
ghdl: unknown option '-Wc,-ftest-coverage' for command '-a'

My setup is as follow:

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/gnat/bin/../libexec/gcc/x86_64-pc-linux-gnu/4.9.4/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../src/configure --enable-languages=ada,c,c++ --enable-dual-exceptions --enable-_cxa_atexit --enable-threads=posix --with-bugurl=URL:mailto:[email protected] --disable-nls --without-libiconv-prefix --disable-libstdcxx-pch --disable-libada --enable-checking=release --disable-multilib --with-mpfr=/boron.a/gnatmail/sandbox/gpl-2016/x86_64-linux/mpfr_stable/install --with-gmp=/boron.a/gnatmail/sandbox/gpl-2016/x86_64-linux/gmp_stable/install --with-mpc=/boron.a/gnatmail/sandbox/gpl-2016/x86_64-linux/mpc_stable/install --with-build-time-tools=/boron.a/gnatmail/sandbox/gpl-2016/x86_64-linux/gcc/build/buildtools/bin --prefix=/boron.a/gnatmail/sandbox/gpl-2016/x86_64-linux/gcc/pkg --build=x86_64-pc-linux-gnu
Thread model: posix
gcc version 4.9.4 20160426 (for GNAT GPL 2016 20160515) (GCC) 

$ gcov -v
gcov (GCC) 4.9.4 20160426 (for GNAT GPL 2016 20160515)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.

$ ghdl -v
GHDL 0.34dev (20151126) [Dunoon edition]
Compiled with GNAT Version: GPL 2016 (20160515-49)
mcode code generator
Written by Tristan Gingold.

Copyright (C) 2003 - 2015 Tristan Gingold.
GHDL is free software, covered by the GNU General Public License.  There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ cat /proc/version
Linux version 4.4.0-34-generic (buildd@lgw01-20) (gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2.1) ) #53-Ubuntu SMP Wed Jul 27 16:06:39 UTC 2016

I installed GHDL using the Building with mcode backend procedure. Could it be the root of the evil?

Thanks for help!


Solution

  • Yes, current ghdl does support code coverage.

    Make sure you have a recent ghdl version, but note that while ghdl suppports 3 code generation backends (LLVM, gcc and its own JIT compiler, mcode), only the gcc backend currently supports code coverage (via gcov). Specifically, the mcode version you have built will not work.

    There ought to be suitable packages for Ubuntu - failing that I have build instructions somewhere for building from source on Debian Jessie which ought to serve for Ubuntu too. (I'll dig them out if need be).

    ghdl --version
    GHDL 0.34dev (20151126) [Dunoon edition]
     Compiled with GNAT Version: 4.9.3
     GCC back-end code generator
    Written by Tristan Gingold.
    

    check...

    Now there are some compile time flags you need to supply...

    ghdl -a --std=08 -g -fprofile-arcs -ftest-coverage myfile.vhd
    ghdl -a --std=08 -g -fprofile-arcs -ftest-coverage my_TB.vhd
    

    and for elaboration (-Wl, precedes linker options)...

    ghdl -e --std=08 -Wl,-lgcov -Wl,--coverage my_tb
    ./my_tb
    

    and you should have a set of .gcno,.gcda files to be post-processed with gcov (or lcov and genhtml, for prettier reports)

    Also works under Vunit and with the OSVVM library.

    Branch coverage does not work so well, in part because VHDL's signal assignment semantics translate into a lot of spurious branches in the generated executable.

    Under VUnit, I don't use their "code coverage" experimental option. Instead, I set the relevant flags, run the vu.main() function, catch its return, and invoke lcov as a postprocessing step. An incomplete example run.py script is as follows:

    lib.add_compile_option("ghdl.flags", ["-fprofile-arcs"])
    vu.set_sim_option("ghdl.flags", ["-Wl,-lgcov"])
    try:
        vu.main()
    except SystemExit as exc:
        all_ok = exc.code == 0
    
    if all_ok:
        subprocess.call(["lcov", "--capture", "--directory", ".", "--output-file",  "code_coverage.info"])
        subprocess.call(["genhtml", "code_coverage.info", "--output-directory", "code_html"])