nvc icon indicating copy to clipboard operation
nvc copied to clipboard

VHDL-2008: Error with Subprogram Instantiation

Open bpadalino opened this issue 2 years ago • 5 comments

The following file causes an error during analysis.

library ieee ;
    use ieee.std_logic_1164.std_logic ;
    use ieee.std_logic_1164.std_ulogic ;
    use ieee.std_logic_1164."not";

package frequency is

    type frequency is range 0 to 2e9 units
        Hz ;
        kHz = 1000 Hz ;
        MHz = 1000 kHz ;
        GHz = 1000 MHz ;
        THz = 1000 GHz ;
    end units ;

    function half_period(freq : frequency) return time ;
    function period(freq : frequency) return time ;

    procedure generate_clock generic (
        type t ;
        function "not"(x : t) return t is <>
    ) parameter (signal clock : inout t ; freq : frequency ; count : natural := 0) ;

    procedure generate_clock is new generate_clock generic map(t => std_ulogic) ;
    procedure generate_clock is new generate_clock generic map(t => std_logic) ;
    procedure generate_clock is new generate_clock generic map(t => bit) ;

end package ;

package body frequency is

    function period(freq : frequency) return time is
    begin
        return 1 sec / frequency'pos(freq) ;
    end function ;

    function half_period(freq : frequency) return time is
    begin
        return period(freq) / 2.0 ;
    end function ;

    procedure generate_clock generic(
      type t ;
      function "not"(x : t) return t is <>
    ) parameter (
        signal clock : inout t ;
        freq : frequency ;
        count : natural := 0
    ) is
        constant hp : time := half_period(freq) ;
        variable downcount : natural := count ;
    begin
        -- count = 0 means forever, otherwise we look at the downcount
        while count = 0 or downcount > 0 loop
            clock <= not clock after hp ;
            downcount := downcount - 1 ;
        end loop ;
    end procedure ;

end package body ;

... and the error:

$ nvc --std=2008 -a frequency.vhdl 

*** Caught signal 11 (SEGV_MAPERR) [address=(nil), ip=0x55901eda054b] ***

[0x55901ed44ead] ../src/util.c:837 signal_handler
[0x7fccef50851f] (/usr/lib/x86_64-linux-gnu/libc.so.6) 
[0x55901eda054b] ../src/tree.c:548 tree_kind
[0x55901eda054b] ../src/tree.c:1052 search_decls
[0x55901ed65e0d] ../src/parse.c:6340 p_subprogram_instantiation_declaration.lto_priv.0
[0x55901ed72ee9] ../src/parse.c:7592 p_package_declaration
[0x55901ed72ee9] ../src/parse.c:8271 p_primary_unit.lto_priv.0
[0x55901ed78132] ../src/parse.c:10949 p_design_unit
[0x55901ed78132] ../src/parse.c:11015 parse
[0x55901ed4d8a0] ../src/nvc.c:211 analyse
[0x55901ed4d8a0] ../src/nvc.c:1429 process_command
[0x55901ed415b6] ../src/nvc.c:1553 main

bpadalino avatar Mar 20 '23 05:03 bpadalino

I think this is not valid - the procedure cannot be instantiated until its body has been analysed - but it still shouldn't crash. It now produces an error:

** Error: subprogram GENERATE_CLOCK cannot be instantiated until its body has been analysed    
    > test.vhd:24                                                                              
    |                                                                                          
 24 |     procedure generate_clock is new generate_clock generic map(t => std_ulogic) ;        
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                  

nickg avatar Mar 20 '23 20:03 nickg

Is that true? Section 4.4 of the LRM-2008 states:

If the subprogram instantiation declaration occurs immediately within an enclosing package declaration, the generic-mapped subprogram body occurs at the end of the package body corresponding to the enclosing package declaration. If there is no such body, then there is implicitly a package body corresponding to the enclosing package declaration, and that implicit body contains the generic-mapped subprogram body. If the subprogram instantiation declaration occurs immediately within an enclosing protected type declaration, the generic-mapped subprogram body occurs at the end of the protected type body corresponding to the enclosing protected type declaration.

There is similar wording dealing with generic packages which are immediately instantiated, as per this ghdl issue.

From section 4.9 of LRM-2008:

If the package instantiation declaration occurs immediately within an enclosing package declaration and the uninstantiated package has a package body, the generic-mapped package body occurs at the end of the package body corresponding to the enclosing package declaration. If there is no such body, then there is implicitly a package body corresponding to the enclosing package declaration, and that implicit body contains the generic-mapped package body.

bpadalino avatar Mar 20 '23 21:03 bpadalino

Hm, ok. But it's not clear to me how this could be implemented.

nickg avatar Mar 20 '23 22:03 nickg

Do you think this is still unclear on how it could be implemented?

bpadalino avatar Dec 02 '23 15:12 bpadalino

I need to do some refactoring of how subprogram instantiation works.

nickg avatar Dec 02 '23 18:12 nickg

Should work now, sorry it took so long!

nickg avatar Mar 02 '24 14:03 nickg