ScottishTapWater
ScottishTapWater

Reputation: 4836

Test for Assertion Failure in VUnit

I may have some functions that assert and fail if they're not happy.

How do I test this functionality with VUnit to ensure that these functions do in-fact throw the failure in the right conditions?


For instance, lets say I wanted to check this function:

function to_normalised_float(slv: std_logic_vector) return half_float is
variable temp_hf: half_float;
begin
    assert slv'high = 15 report "SLV provided is incorrect length for an FP16";
    -- ConstructFloat
    return normalise_float(temp_hf);
end function;

I can quite easily test that it returns the expected value if I pass in a value and then assert on the output in my testbench.

However, I also want to be able to test, using VUnit, that if I pass in a 22 bit SLV, that the assertion throws.

This is obviously a very simplified example, but it should explain what I mean.

The equivalent in C# would be Assert.Throws(function) if that helps.

Upvotes: 1

Views: 678

Answers (1)

lasplund
lasplund

Reputation: 1440

The ability to inspect asserts will improve with VHDL-2019 support in your simulator but since you're using VUnit I recommend using VUnit mocking (http://vunit.github.io/logging/user_guide.html#mocking and https://github.com/VUnit/vunit/blob/f02c21452a505c527db575b10db94195ceb7ed2f/vunit/vhdl/logging/src/logger_pkg.vhd#L342) which is provided exactly to support your use case.

First replace your assert with a VUnit check:

check(slv'high = 15, "SLV provided is incorrect length for an FP16");

When that check fails you will see an error message looking something like this:

0 ps - check - ERROR - SLV provided is incorrect length for an FP16

check is the VUnit logger managing this message. You can get this logger by name (get_logger("check")) and mock it. Mocking means that all output messages (of a specific severity level) will be placed in a queue rather than passed to stdout. The messages in this queue can be inspected to determine if the function works as expected. Here is a slightly modified example testbench to show the principle

library vunit_lib;
context vunit_lib.vunit_context;

library ieee;
use ieee.std_logic_1164.all;

entity tb_example is
  generic (runner_cfg : string);
end entity;

architecture tb of tb_example is
begin
  main : process
    procedure dummy(slv : std_logic_vector) is
    begin
      check(slv'length = 16, "SLV provided is incorrect length for an FP16");
    end;

    constant logger : logger_t := get_logger("check");
  begin
    test_runner_setup(runner, runner_cfg);

    while test_suite loop
      if run("Test to see dummy fail") then
        dummy(x"17");
      elsif run("Test that dummy fails with the correct message") then
        mock(logger, error);
        dummy(x"17");
        check_log(logger, "SLV provided is incorrect length for an FP16", error);
        unmock(logger);
      elsif run("Test that dummy passes with 16 bit inputs") then
        mock(logger, error);
        dummy(x"1718");
        check_no_log;
        unmock(logger);
      end if;
    end loop;

    test_runner_cleanup(runner);
  end process;

end architecture;

The first test case will fail (which is your problem) but the last two will pass

enter image description here

I can also recommend using check_equal for a more informative output.

check_equal(slv'length, 16, result("for input length"));

will give you the following error output:

0 fs - check - ERROR - Equality check failed for input length - Got 8. Expected 16.

Upvotes: 1

Related Questions