Description
GHDL elaboration ends with error: bound check failure at etest.vhd:13 when using VHDL-2008.
Expected behaviour
GHDL ends with error: direction of the range mismatch
or error: slice direction doesn't match index direction
How to reproduce?
```vhd :file: tb.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity etest is
end;
architecture atest of etest is
function foo(a : std_logic_vector) return unsigned is
variable v : unsigned(3 downto 0):=(others=>'0') ;
begin
v := v + unsigned(a(1 downto 1));
return v;
end;
begin
test : process
variable v : std_logic_vector(3 downto 0) ;
variable w : std_logic_vector(0 to 3);
variable x : unsigned(3 downto 0) ;
begin
x := foo(w);
-- x := x + unsigned(w(0 downto 0)) ;
wait;
end process ; -- test
end;
```sh :image: ghdl/ghdl:buster-mcode
ghdl -a --std=08 tb.vhd
ghdl --elab-run --std=08 etest
Context
Additional context
Compiling with VHDL-93 provides the following message: error: slice direction doesn't match index direction
the bound check failure is probably due to the unsigned addition, but AFAIK synthesis automatically resizes to the bigger size.
@arcturus140, you are implicitly assigning (3 downto 0) to (0 to 3). Isn't this a legit design error?
@eine it is, but I would like to see an slice direction doesn't match index direction error in this situation. This is the case when using VHDL-93.
I am not sure if my code has a bound error. The MNWE is very simplified, it took me a long time to find the error because the original code was using assert("0000" = foo("0000"). Apparently, VHDL has a default range if none is provided.
The error message is correct. Your code has a bug.
function foo(a : std_logic_vector) return unsigned is
foo has an unconstrained parameter, thus a can be in ascending (to) or descending (downto) direction.
v := v + unsigned(a(1 downto 1));
More precisely a(1 downto 1) does a downto slice operation on an ascending array (coming from w).
Solutions:
downto only.vhdl
function foo(a : std_logic_vector) return unsigned is
alias b : std_logic_vector(a'high downto a'low) is a;
variable v : unsigned(3 downto 0):=(others=>'0') ;
begin
v := v + unsigned(b(1 downto 1));
return v;
end function;
b(1 downto 1) , because it's not the 2nd bit from right, it might be second bit from left.So in general, you should rethink the overall semantics of what you want to achieve with bit arrays.
The errors for a slice name are given in IEEE Std 1076-2008 8.5 Slice names:
The bounds of the discrete range define those of the slice and shall be of the type of the index of the array. The slice is a _null slice_ if the discrete range is a null range. It is an error if the direction of the discrete range is not the same as that of the index range of the array denoted by the prefix of the slice name.
For the evaluation of a name that is a slice, the prefix and the discrete range are evaluated. It is an error if either of the bounds of the discrete range does not belong to the index range of the prefixing array, unless the slice is a null slice. (The bounds of a null slice need not belong to the subtype of the index.)
You could note that null range is specified in 5.2 Scalar types, 5.2.1 General:
A range specifies a subset of values of a scalar type. A range is said to be a _null_ range if the specified subset is empty.
The range L to R is called an _ascending range_; if L > R, then the range is a null range. The range L downto R is called a _descending range_; if L < R, then the range is a null range. L is called the _left bound_ of the range, and R is called the _right bound_ of the range. ...
a(1 downto 1) has a descending range. w is declared with an ascending range. The error in the first quoted paragraph of 8.5 occurs. 1 belongs to the index range of the prefixing array, and it's not a null slice. The errors specified in the second quoted paragraph of 8.5 do not occur.
This tells us the at issue error message is incorrect while there is an error, "...the direction of the discrete range is not the same as that of the index range of the array denoted by the prefix of the slice name."
in previous revisions of the standard the semantic description has the same semantic meaning (e.g. IEEE Std 1076-1993 6.5 Slice names):
The bounds of the discrete range define those of the slice and must be of the type of the index of the array. The slice is a _null slice_ if the discrete range is a null range. It is an error if the direction of the discrete range is not the same as that of the index range of the array denoted by the prefix of the slice name.
For the evaluation of a name that is a slice, the prefix and the discrete range are evaluated. It is an error if either of the bounds of the discrete range does not belong to the index range of the prefixing array, unless the slice is a null slice. (The bounds of a null slice need not belong to the subtype of the index.)
We see a contrast in error messages:
ghdl -a --std=08 etest.vhdl
ghdl -e --std=08 etest
ghdl -r --std=08 etest
./etest:error: bound check failure at etest.vhdl:14
./etest:error: simulation failed
ghdl -a etest.vhdl
ghdl -e etest
ghdl -r etest
./etest:error: slice direction doesn't match index direction at etest.vhdl:14
./etest:error: simulation failed
Note that the earlier revision (--std default is 93c) is correct while the --std=08 revision promulgates the wrong error message and the error messages are produced during simulation.
These errors occur at run time as a result of dynamic elaboration (-2008 14.6) which would require code to test for the error cases embedded in function foo (ghdl/src/vhdl/translate) noting parameter a is an unbounded array in -2008 (previously an unconstrained array). The error message is found in ghdl/src/grt/grt-lib.adb.
If I had to hazard a guess here the semantic rules are either both not applied or applied in the wrong order with an assumption that isn't met for the index range being bounds checked.
As Patrick notes there are work around methods to prevent encountering the incongruous error message. Another might be:
-- x := x + unsigned(w(0 downto 0)) ;
x := x + ("" & w(0));
where the parentheses are require by precedence rules. Here concatenating an empty string whose type is specified by context to w(0) results in array value whose type is specified by context provided by the left parameter type to the "+" operator and the result type of the expression dictated by the assignment statement target (12.5 The context of overload resolution). Concatenation is predefined for any single dimensional array type and the result type is the same array type (9.2.5 Adding operators). The expression in parentheses uses a locally static index constraint which can be checked at analysis time (9.4.2 Locally static primaries, 9.4.1 General).
First of all I noticed I did not indicate the line where the error occurs. This would have been helpful and was meant to be included when I created the issue. My apology for that!
If I had to hazard a guess here the semantic rules are either both not applied or applied in the wrong order with an assumption that isn't met for the index range being bounds checked.
Yes, that would make sense. I also noted that, when I change
v := v + unsigned(a(1 downto 1));
into
v := v + unsigned(a(0 downto 0));
, the build passes completely without error message when using VHDL-2008.
When using VHDL-93 the build correctly detects the error:
ghdl --elab-run etest
./etest:error: slice direction doesn't match index direction at etest.vhd:13
./etest:error: simulation failed
which makes me assume that slice direction error checking is not working as intended for VHDL-2008.