nickg / nvc

VHDL compiler and simulator
https://www.nickg.me.uk/nvc/
GNU General Public License v3.0
589 stars 75 forks source link

Using Constants for Attribute Indexing #862

Closed bpadalino closed 3 months ago

bpadalino commented 3 months ago

Trying the following code:

entity test is
end entity ;

architecture arch of test is

    type bv_2d is array(integer range <>, integer range <>) of bit_vector ;

    constant ROWS : positive := 1 ;
    constant COLS : positive := 2 ;

    -- Assume first index is rows, next index is columns
    signal a : bv_2d(0 to 10, 0 to 10)(9 downto 0) ;

    procedure print(x : in string) is
        variable l : std.textio.line ;
    begin
        std.textio.write(l, x) ;
        std.textio.writeline(std.textio.output, l) ;
    end procedure ;

    procedure print(name : in string ; x : in bv_2d) is
    begin
        print(
            name & " is matrix " & integer'image(x'length(ROWS)) & " rows and " &
            integer'image(x'length(COLS)) & " with elements of length " & integer'image(x'element'length)
        ) ;
    end procedure ;

begin

    tb : process
    begin
        print("a", a) ;
        std.env.stop ;
    end process ;

end architecture ;

I get the following error with nvc:

$ nvc --std=2008 -a --relaxed parameter.vhdl -e test -r
** Error: dimension parameter of attribute LENGTH must be a locally static expression of type universal_integer
    > parameter.vhdl:24
    |
 24 |             name & " is matrix " & integer'image(x'length(ROWS)) & " rows and " &
    |                                                           ^^^^ expression has type POSITIVE

Questa and Riviera both don't even give a warning about this. The constant should be able to be internally cast /promoted to a universal_integer, right?

nickg commented 3 months ago

The constant should be able to be internally cast /promoted to a universal_integer, right?

Implicit conversions only happen in the other direction (universal to other integer type). Also a constant is only globally- rather than locally-static.

nickg commented 3 months ago

Also a constant is only globally- rather than locally-static.

OK that's not true in this case as the initialiser is a locally static expression.

nickg commented 3 months ago

Try using x'length(integer'pos(ROWS)) instead (the result of 'pos is a universal integer). This works in GHDL too.

bpadalino commented 3 months ago

That's a cute trick, but do you think this should be necessary given that Questa and Riviera both don't complain, or maybe something to be able to do with --relaxed rules?

nickg commented 3 months ago

I made it a warning in --relaxed mode as long as the parameter has an integer type.