Search code examples
arrayscastingtype-conversionvhdlghdl

Shouldn't these types be closely related?


I am trying to analyze the following file which is supposed to be VHDL-2008 compatible.

entity closely_related is
end;

architecture example of closely_related is
    type integer_vector is array (natural range <>) of integer;
    type real_vector is array (natural range <>) of real;
begin
    process
        variable int_vect: integer_vector(1 to 3);
        variable real_vect: real_vector(1 to 3);
    begin
        real_vect := ( 1.0, 2.0, 3.0 );
        int_vect := integer_vector( real_vect );

        wait;
    end process;
end;

This is supposed to be an experiment about closely related types. According to the LRM, there are two cases of closely related types:

— Abstract numeric types—Any abstract numeric type is closely related to any other abstract numeric type. — Array types—Two array types are closely related if and only if the types have the same dimensionality and the element types are closely related

I understand that reals and integers are closely related; type conversion (aka type casting) between them works ok. Then why doesn't it work for the above array types?

GHDL gives the following error:

conversion not allowed between not closely related types

And Modelsim Altera 10.1e (with -2008 switch) is no better:

Illegal type conversion from std.STANDARD.REAL_VECTOR to std.STANDARD.INTEGER_VECTOR 
(array element type difference).

Just to be thorough, I tried to do the same operation one element at a time:

int_vect(1) := integer( real_vect(1) );
int_vect(2) := integer( real_vect(2) );
int_vect(3) := integer( real_vect(3) );

And it works perfectly. Any ideas?


Solution

  • Shouldn't these types be closely related?

    Not for ghdl which is strictly -1993 compliant by default.

    This is from IEEE Std 1076-1993, 7.3.5 Type conversions:

    A type conversion provides for explicit conversion between closely related types.
    ...

    b. Array Types -- Two array types are closely related if and only if

    -- The types have the same dimensionality;

    -- For each index position, the index types are either the same or are closely related; and

    -- The element types are the same.
    ...

    No other types are closely related.

    So the issue is that the element types are not the same.

    In -2008, 9.3.6 Type conversions:

    — Abstract numeric types—Any abstract numeric type is closely related to any other abstract numeric type.

    — Array types — Two array types are closely related if and only if the types have the same dimensionality and the element types are closely related

    Which tells us that any abstract numeric type (integer, real) are closely related and that array types are now closely related when their element types are closely related.

    So it looks like either the Modelsim version you specifiy isn't compliant with the change or something stopped the invocation of your -2008 flag for it.

    I don't have the -2008 versions of the libraries loaded for ghdl on my Mac. I wouldn't bet it would with the --std=08 flag, either.

    I checked out the the latest ghdl source code from ghdl-updates on Sourceforge, The change implementing closely related array types with closely related elements has not been incorporated. See sem_names.adb lines 1024 - 1047.

    When we find things that don't get implemented due to revisions in the standard like this it's generally because there isn't a test case that fails or passes when it should, and because there is no way to see changes between standards versions.

    You need a diff PDF and a way of correlating requirements between various clauses and subclauses as well as determining whether a statement in standard is testable, and if so by what code. It's safe to say that copyright is getting in the way of implementation.

    The thud factor (page count) of the -2008 standard also affects the likelihood compliance gotchas will occur.

    Any ideas?

     int_vect := integer_vector'(integer(real_vect(1)),integer(real_vect(2)), integer(real_vect(3)));