nvc
nvc copied to clipboard
VHDL-2008: Error with Subprogram Instantiation
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
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) ;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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.
Hm, ok. But it's not clear to me how this could be implemented.
Do you think this is still unclear on how it could be implemented?
I need to do some refactoring of how subprogram instantiation works.
Should work now, sorry it took so long!