?= and numeric_std implementation
The matching equality and inequality are predefined by the language as follows (9.2.3)
The matching equality and matching inequality operators are also defined for any one-dimensional array type whose element type is BIT or STD_ULOGIC. The operands shall be arrays of the same length.
Do these same rules relating to "operands shall be arrays of the same length" apply when overloading the operator? Currently in numeric_std, "?=" allows either array to be resized in the event they are not the same length.
Is this overloading even desirable? Note that this is not done for logic operations. I think equality checks should also preserve the sense that the arrays must be the same length and fail if they are not the same length. I also think we need a way to express this to the compiler so it can be a compile time check.
OTOH, if we just commented these functions out, then we would have the language implicit definition for them as described above from 9.2.3
Note the issue about the arrays not being equal when they are both null arrays is discussed in #24
For reference:
-- Id: C.74
function "?=" (L, R : UNRESOLVED_SIGNED) return STD_ULOGIC is
constant L_LEFT : INTEGER := L'length-1;
constant R_LEFT : INTEGER := R'length-1;
alias XL : UNRESOLVED_SIGNED(L_LEFT downto 0) is L;
alias XR : UNRESOLVED_SIGNED(R_LEFT downto 0) is R;
constant SIZE : NATURAL := MAXIMUM(L'length, R'length);
variable LX : UNRESOLVED_SIGNED(SIZE-1 downto 0);
variable RX : UNRESOLVED_SIGNED(SIZE-1 downto 0);
variable result, result1 : STD_ULOGIC; -- result
begin -- ?=
if ((L'length < 1) or (R'length < 1)) then
assert NO_WARNING
report "NUMERIC_STD.""?="": null detected, returning X"
severity warning;
return 'X';
else
LX := RESIZE(XL, SIZE);
RX := RESIZE(XR, SIZE);
result := '1';
for i in LX'low to LX'high loop
result1 := LX(i) ?= RX(i);
if result1 = 'U' then
return 'U';
elsif result1 = 'X' or result = 'X' then
result := 'X';
else
result := result and result1;
end if;
end loop;
return result;
end if;
end function "?=";
I suppose that this code is only a reference implementation, but I am surprised that "?=" and "and" are called, rather than using a lookup table. Furthermore, if an appropriate lookup table is used, then the handling of 'U' and 'X' could be incorporated into it.
-- truth table for "and" function
constant and_sticky_u_x_table : stdlogic_table := (
-- ----------------------------------------------------
-- | U X 0 1 Z W L H - | |
-- ----------------------------------------------------
('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U'), -- | U |
('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X'), -- | X |
('U', 'X', '0', '0', '0', '0', '0', '0', '0'), -- | 0 |
('U', 'X', '0', '1', 'X', 'X', '0', '1', 'X'), -- | 1 |
('U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X'), -- | Z |
('U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X'), -- | W |
('U', 'X', '0', '0', '0', '0', '0', '0', '0'), -- | L |
('U', 'X', '0', '1', 'X', 'X', '0', '1', 'X'), -- | H |
('U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X') -- | - |
);
This could be used to improve the speed of the handling of the table. It seems like the body of the loop could be simply:
result := and_sticky_u_x_table(result, LX(i) ?= RX(i)) ;
I suppose if we took a deep dive into the packages this may need to be done more extensively, so maybe this is a mute point unless someone is interested in the work.