Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] check_equal and check_true raises error for values other than '0' and '1' #1061

Open
nselvara opened this issue Sep 25, 2024 · 3 comments

Comments

@nselvara
Copy link

Hey, there I noticed something strange, while using check_equal or check_true for (un-)signed types.
It actually raises an error if we pass any value except '0' and '1' for got resp. expected.

-- This passes
check_equal(got => std_ulogic_vector'("U"), expected => std_ulogic_vector'("U"), msg => "test std_ulogic_vector");
-- These not
check_equal(got => signed'("U"), expected => signed'("U"), msg => "test signed");
check_equal(got => unsigned'("X"), expected => unsigned'("X"), msg => "test unsigned");
check_true(expr => unsigned'("Z") = unsigned'("Z"), msg => "test equality unsigned");

I checked the definition of the (un-)signed types and seems to be that those are just arrays of std_ulogic type:

type UNRESOLVED_UNSIGNED is array (NATURAL range <>) of STD_ULOGIC;
type UNRESOLVED_SIGNED is array (NATURAL range <>) of STD_ULOGIC;

I guess, equality check with values other than number don't pass for (un-)signed types in VHDL resp. excluded in LRM?

if got = expected then
@nselvara
Copy link
Author

Okay, I've dug through the definition of the "="-operator. I thought, it was an implicitly defined one, however, it has been explicitly defined.

  -- Id: C.25
function "=" (L, R : UNRESOLVED_UNSIGNED) return BOOLEAN is
    constant L_LEFT : INTEGER := L'length-1;
    constant R_LEFT : INTEGER := R'length-1;
    alias XL        : UNRESOLVED_UNSIGNED(L_LEFT downto 0) is L;
    alias XR        : UNRESOLVED_UNSIGNED(R_LEFT downto 0) is R;
    constant SIZE   : NATURAL := MAXIMUM(L'length, R'length);
    variable L01    : UNRESOLVED_UNSIGNED(L_LEFT downto 0);
    variable R01    : UNRESOLVED_UNSIGNED(R_LEFT downto 0);
begin
    if ((L'length < 1) or (R'length < 1)) then
      assert NO_WARNING
        report "NUMERIC_STD.""="": null argument detected, returning FALSE"
        severity warning;
      return false;
    end if;
    L01 := TO_01(XL, 'X');
    R01 := TO_01(XR, 'X');
    if ((L01(L01'left) = 'X') or (R01(R01'left) = 'X')) then
      assert NO_WARNING
        report "NUMERIC_STD.""="": metavalue detected, returning FALSE"
        severity warning;
      return false;
    end if;
    return UNSIGNED_EQUAL(RESIZE(L01, SIZE), RESIZE(R01, SIZE));
end function "=";

The non-number values are converted to '0' and '1':

L01 := TO_01(XL, 'X');
R01 := TO_01(XR, 'X');

So, I don't know if it's worth to change the check_equal wrapper for (un-)signed types to allow these kind of conditions.

@LarsAsplund
Copy link
Collaborator

VHDL is not always obvious and consistent. However, it would only create more confusion if VUnit was to check equality in a way that is not compatible with the = operator

@nselvara
Copy link
Author

Yeah, I understand that totally. I think there's also this function UNSIGNED_EQUAL in numeric-std-body, which converts the (un-)signed types to std_ulogic_vector beforehand. I think maybe expanding (either add. option, another name or completely something else) the check_equal-procedure with this sort of conversion would be cool though. But I understand if it's not desired.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants