I have recently switched to using GHDL as my VHDL simulator of choice. GHDL (currently) supports three different backends: GCC, LLVM and a builtin code generator.
The GCC backend got me thinking… since my VHDL test benches are now native ELF binaries compiled with GCC, I should be able to instrument them with Gcov support – and measure code coverage for each unit under test (UUT).
Turns out to be pretty simple – just a matter of using the right compiler and linker flags, just like building a Gcov-instrumented binary from C code.
Take for instance the full adder example from the GHDL documentation – once the
adder_tb.vhdl files are saved to disk, it is just a matter of modifying the GHDL commands a bit to instrument the final binary with Gcov support.
First analyze the design files with
-ftest-coverage added to CFLAGS for all the VHDL files, that should be instrumented. Here, I have only instrumented the UUT, not the test bench:
$ ghdl -a -Wc,-fprofile-arcs -Wc,-ftest-coverage adder.vhdl $ ghdl -a adder_tb.vhdl
Next, elaborate the test bench and link the binary against libgcov:
$ ghdl -e -Wl,-lgcov adder_tb
Run the test bench as usual:
$ ghdl -r adder_tb adder_tb.vhdl:53:7:@8ns:(assertion note): end of test
Generate a code coverage report using the
$ gcov -s $PWD adder.vhdl File 'adder.vhdl' Lines executed:100.00% of 4 Creating 'adder.vhdl.gcov'
The Gcov code coverage details can be found in the
adder.vhdl.gcov file. Details on the file format can be found in the gcov(1) man page:
$ cat adder.vhdl.gcov -: 0:Source:adder.vhdl -: 0:Graph:adder.gcno -: 0:Data:adder.gcda -: 0:Runs:1 -: 0:Programs: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); -: 14:end rtl;
Another option is to use a tool like Lcov, which can produce nice looking HTML pages with the Gcov code coverage details:
$ lcov -c -d . -o adder_tb.info Capturing coverage data from . Found gcov version: 4.9.4 Scanning . for .gcda files ... Found 1 data files in . Processing adder.gcda Finished .info-file creation $ genhtml -o html adder_tb.info Reading data file adder_tb.info Found 1 entries. Found common filename prefix "/home/brix/tmp" Writing .css and .png files. Generating output. Processing file adder/adder.vhdl Writing directory view page. Overall coverage rate: lines......: 100.0% (4 of 4 lines) functions..: 100.0% (7 of 7 functions)
The Lcov code coverage details can be found in the