Error: Libero SoC 11.9 VHDL compile "A homograph of hread is already declared in the region" - vhdl

I am a novice at VHDL. Im getting the following compile errors:
A homograph of hread is already in the region
A homograph of hread is already in the region
A homograph of hwrite is already in the region
The location of the errors appear as if Libero
compilation is not telling the difference between Std_ULogic_Vector and Std_Logic_Vector. Any insight is helpful.
Slyswine
--pragma translate_off
library Std;
use Std.Standard.all;
use Std.TextIO.all;
library ieee;
use ieee.std_logic_1164.all;
--pragma translate_on
package StdIO is
--pragma translate_off
procedure HRead(
variable L: inout Line;
variable VALUE: out Std_ULogic_Vector;
variable GOOD: out Boolean);
procedure HRead(
variable L: inout Line;
variable VALUE: out Std_ULogic_Vector);
procedure HRead(
variable L: inout Line;
variable VALUE: out bit_vector);
procedure HRead( -- "Error occurs on this line"
variable L: inout Line;
variable VALUE: out Std_Logic_Vector;
variable GOOD: out Boolean);
procedure HRead( -- "and this line"
variable L: inout Line;
variable VALUE: out Std_Logic_Vector);
procedure HWrite(
variable L: inout Line;
constant VALUE: in Std_ULogic_Vector;
constant JUSTIFIED: in SIDE := RIGHT;
constant FIELD: in WIDTH := 0);
procedure HWrite( -- "and this line"
variable L: inout Line;
constant VALUE: in Std_Logic_Vector;
constant JUSTIFIED: in SIDE := RIGHT;
constant FIELD: in WIDTH := 0);
procedure Write(
variable L: inout Line;
constant VALUE: in Std_ULogic;
constant JUSTIFIED: in SIDE := RIGHT;
constant FIELD: in WIDTH := 0);
--pragma translate_on
end package StdIO;

The TL;DR answer
All of these subprogram declarations are already covered in package std_logic_1164 for an IEEE Std 1076-2008 revision compliant tool. Also in n -2008 STD_LOGIC_VECTOR is a subtype of STD_ULOGIC_VECTOR, meaning the base type (STD_ULOGIC_VECTOR) is the same and they errors are homographs (which aren't allowed here in the same declarative region).
When using -2008 package StdIO (it's declaration shown here) isn't needed unless there are behavioral differences in a subprogram specification.
The package declaration would analyze correctly in a tool compliant to an earlier revision of the VHDL standard because STD_LOGIC_VECTOR is declared as a separate type in package std_logic_1164.
The long answer
The Errors
12.3 Visibility
... Each of two declarations is said to be a homograph of the other if and only if both declarations have the same designator, and they denote different named entities, and either overloading is allowed for at most one of the two, or overloading is allowed for both declarations and they have the same parameter and result type profile (see 4.5.1).
4.5 Subprogram overloading
4.5.1 General
Two formal parameter lists are said to have the same parameter type profile if and only if they have the same number of parameters, and if at each parameter position the corresponding parameters have the same base type. Two subprograms are said to have the same parameter and result type profile if and only if both have the same parameter type profile, and if either both are functions with the same result base type or neither of the two is a function.
procedure HRead(
variable L: inout Line;
variable VALUE: out Std_ULogic_Vector;
variable GOOD: out Boolean);
and
procedure HRead( -- "Error occurs on this line"
variable L: inout Line;
variable VALUE: out Std_Logic_Vector;
variable GOOD: out Boolean);
are being considered homographs as are
procedure HRead(
variable L: inout Line;
variable VALUE: out Std_ULogic_Vector);
and
procedure HRead( -- "and this line"
variable L: inout Line;
variable VALUE: out Std_Logic_Vector);
As well as
procedure HWrite(
variable L: inout Line;
constant VALUE: in Std_ULogic_Vector;
constant JUSTIFIED: in SIDE := RIGHT;
constant FIELD: in WIDTH := 0);
and
procedure HWrite( -- "and this line"
variable L: inout Line;
constant VALUE: in Std_Logic_Vector;
constant JUSTIFIED: in SIDE := RIGHT;
constant FIELD: in WIDTH := 0);
12.3 Visibility
...
Two declarations that occur immediately within the same declarative region, other than the declarative region of a block implied by a component instantiation or the declarative region of a generic-mapped package or subprogram equivalent to a package instance or a subprogram instance, shall not be homographs, unless exactly one of them is the implicit declaration of a predefined operation or is an implicit alias of such an implicit declaration. In such cases, a predefined operation or alias thereof is always hidden by the other homograph. Where hidden in this manner, an implicit declaration is hidden within the entire scope of the other declaration (regardless of which declaration occurs first); the implicit declaration is visible neither by selection nor directly. For a declarative region of a block implied by a component instantiation or the declarative region of a generic-mapped package or subprogram equivalent to a package instance or a subprogram instance, the rules of this paragraph are applied to the corresponding entity declaration, component declaration, uninstantiated package declaration, or uninstantiated subprogram declaration, as appropriate.
...
To avoid a rathole HREAD and HWRITE are explicitly declared in package std_logic_1164 (-2008) and
procedure HRead(
variable L: inout Line;
variable VALUE: out Std_ULogic_Vector;
variable GOOD: out Boolean);
procedure HRead(
variable L: inout Line;
variable VALUE: out Std_ULogic_Vector);
procedure HWrite(
variable L: inout Line;
constant VALUE: in Std_ULogic_Vector;
constant JUSTIFIED: in SIDE := RIGHT;
constant FIELD: in WIDTH := 0);
are legal overloads of the procedures declared in -2008 package std_logic_1164. (These are the declarations for which following illegal homographs are found. They aren't implicitly declared or aliases. These declarations are not found in earlier revision versions of package std_logic_1164. The implication is none of these declarations may be necessary in the OP's package StdIO.)
And these are errors:
1.3 Structure and terminology of this standard
1.3.1 General
In this document, the word shall is used to indicate a mandatory requirement. The word should is used to indicate a recommendation. The word may is used to indicate a permissible action. The word can is used for statements of possibility and capability.
1.3.3 Semantic description
The meaning and restrictions of a particular construct are described with a set of narrative rules immediately following the syntactic productions. In these rules, an italicized term indicates the definition of that term, and identifiers appearing entirely in uppercase letters refer to definitions in package STANDARD (see 16.3).
The following terms are used in these semantic descriptions with the following meanings:
erroneous: The condition described represents an ill-formed description; however, implementations are not required to detect and report this condition. Conditions are deemed erroneous only when it is impossible in general to detect the condition during the processing of the language.
error: The condition described represents an ill-formed description; implementations are required to detect the condition and report an error to the user of the tool.
illegal: A synonym for “error.”
legal: The condition described represents a well-formed description.
The homograph subprogram declarations produce errors, not meeting a semantic requirement that is mandatory (the use of shall in 12.3 above).
Why they're homographs is based on the use of IEEE Std 1076-2008 compliant VHDL tool where in IEEE package std_logic_1164 STD_LOGIC_VECTOR is a subtype of STD_ULOGIC_VECTOR:
subtype STD_LOGIC_VECTOR is (resolved) STD_ULOGIC_VECTOR;
Note for homograph procedure declarations the interface objects of the form:
6.5.2 Interface object declarations
interface_constant_declaration ::=
[ constant ] identifier_list : [ in ] subtype_indication [ := static_expression ]
interface_variable_declaration ::=
[ variable ] identifier_list : [ mode ] subtype_indication [ := static_expression ]
whose subtype indication type marks:
6.3 Subtype declarations
subtype_indication ::=
[ resolution_indication ] type_mark [ constraint ]
..
type_mark ::=
type_name
| subtype_name
have the same base type:
6.3 Subtype declarations
...
A type mark denotes a type or a subtype. If a type mark is the name of a type, the type mark denotes this type and also the corresponding unconstrained subtype. The base type of a type mark is, by definition, the base type of the type or subtype denoted by the type mark.
...
have the same parameter type profile (4.5.1), and the procedure declarations are homographs.
4.5 Subprogram overloading
4.5.1 General
...
A given subprogram designator can be used to designate multiple subprograms. The subprogram designator is then said to be overloaded; the designated subprograms are also said to be overloaded and to overload each other. If two subprograms overload each other, one of them can hide the other only if both subprograms have the same parameter and result type profile.
A call to an overloaded subprogram is ambiguous (and therefore is an error) if the name of the subprogram, the number of parameter associations, the types and order of the actual parameters, the names of the formal parameters (if named associations are used), and the result type (for functions) are not sufficient to identify exactly one (overloaded) subprogram.
Solutions
First you could use a tool compatible with an earlier revision of the VHDL standard. Prior to -2008 the std_ulogic_vector and std_logic_vector were two separate types.
Second you could delete the 'duplicate' declarations with std_logic_vector parameters and presumably any matching subprogram specifications in the package body while using -2008 compliant design specifications and tools. Potentially none of this package (as seen from it's declaration) is needed with -2008 unless there is some behavior found for any of it's subprogram specifications not provided in -2008 package std_logic_1164. If there's no differentiation in behavior the package StdIO isn't needed whatsoever, all it's procedures are declared in -2008 package std_logic_1164. (You may get a glimmer of why STD_LOGIC_VECTOR is a subtype of STD_ULOGIC_VECTOR in -2008, it reduces the number of subprogram declarations and specifications drammatically.)
Resources
The source for the -2008 package bodies as well as earlier package bodies can be found here if not made available in your tool implementation. (Respectively 1076-2008_downloads.zip and 1076.2-1996_downloads.zip). For purposes of these errors only the declarations for STD_LOGIC_VECTOR in package std_logic_1164 need be considered (1076-2008_downloads/1076-2008_machine-readable/ieee/std_logic_1164.vhdl and 1076.2-1996_downloads/std_logic_1164.vhdl).
Other items
You don't need the library clause for std nor the use clause for std.standard in the context clause of package StdIO.
See IEEE Std 1076-2008:
13.2 Design libraries.
...
Every design unit except a context declaration and package STANDARD is assumed to contain the following implicit context items as part of its context clause:
library STD, WORK; use STD.STANDARD.all;

Related

What happens when I provide a function with the parent of the subtype argument it's expecting?

While trying to figure out the specifics of the shift_right function from the numeric_std package I noticed that the count argument is of the subtype NATURAL:
function shift_right(ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is
begin
if (ARG'length<1) then return NAU; end if;
return UNSIGNED(XSRL(STD_LOGIC_VECTOR(ARG),COUNT));
end;
However when calling the function I can also provide an INTEGER which in contrast to NATURAL can hold a negative number.
Example of calling code that succesfully compiles:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ExampleCode is
port
(
clk : in std_logic;
input : in signed(15 downto 0);
shift : in signed(3 downto 0);
output : out signed(15 downto 0)
);
end entity;
architecture rtl of ExampleCode is
begin
ProcessExample : process(clk)
begin
if (rising_edge(clk)) then
output <= shift_right(input, to_integer(shift));
end if;
end process;
end rtl;
The numeric_std package shows that if you use to_integer with a signed argument that it returns an integer:
function TO_INTEGER ( ARG: SIGNED) return INTEGER;
My questions are;
Does VHDL always allow parents of subtypes to be provided as arguments to functions?
When it does allow a parent type, how does it resolve the imposed constraints of the subtype?
The other answer is very detailed, but I think goes down a bit of a rabbit hole, when your specific questions can be answered more succinctly. I have answered from a perspecitve of what will practically happen in a real tool that you might use, as opposed to trying to re-interpret the language standard.
An important feature of a subtype is that there is automatic 'conversion'+ to and from the parent type. The example below clearly shows this with an enumerated type. The same automatic conversion would be invoked when passing a parent-type parameter to a function that expects the sub-type.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity e is
end;
architecture a of e is
type r is (A, B, C, D);
subtype rs is r range A to C;
signal x1 : r := B;
signal x2 : r := D;
signal xs : rs;
begin
process
begin
xs <= x1; -- Fine.
wait for 1 ns;
xs <= x2; -- Run-time error, "Value 3 is out of range 0 to 2".
wait;
end process;
end;
Does VHDL always allow parents of subtypes to be provided as arguments to functions?
From the above, yes, it does, but in many tools, you will get an error if the automatic type conversion cannot succeed, as it obviously cannot in the second assignment in the example. Note that if x2 was a constant, a tool could work out that the conversion is not going to be possible, and thrown up a compile-time error then instead.
The same applies with natural and integer; since natural is defined as subtype natural is integer range 0 to integer'high, natural in a sense is an integer, so automatic 'conversion' is simple and reasonable as long as the integer is not outside the natural's range.
When it does allow a parent type, how does it resolve the imposed constraints of the subtype?
Whether standardised or not, a particular tool might implement this in a variety of ways, so you might see different behavior for out-of-range parent-typed values with different tools.
For example, when I tried with ModelSim, it appears that its conversion from integer to natural simply copies the value, meaning that shift_right will surprisingly work with a negative value in that tool, if the shift amount integer is not a constant (at least for version 10.7e).
Obviously it is not sensible to rely on a particular behavior, but regardless of behavior, using a sub type can offer you more protection than just using base types throughout a design.
+ It's not really conversion in VHDL, but if you've used pretty much any other language, this is how you will tend to refer to it.

Why is there an apostrophe before a parenthesis in this VHDL function?

I'm new to coding test benches and so there is a lot of new syntax for me to learn. I'm stuck on trying to understand what the apostrophe after "string" is indicating.
It doesn't appear to be an attribute from here. Also, I've never seen a parenthesis after an apostrophe in VHDL.
procedure Shrink_line(L : inout LINE; pos : in integer)
is
variable old_L : LINE := L;
begin
if pos > 1 then
L := new string'(old_L(pos to old_L'high));
Deallocate(old_L);
end if;
end;
It's a qualified expression.
IEEE Std 1076-2008, 9.3.5 Qualified expressions:
A qualified expression is a basic operation (see 5.1) that is used to explicitly state the type, and possibly the subtype, of an operand that is an expression or an aggregate."
qualified_expression ::=
type_mark ' ( expression )
| type_mark ' aggregate
This qualified expression states both the type and the subtype for the allocator (9.3.7 Allocators) assigned to L in the procedure.
The operand of the qualified expression is the expression old_L(pos to old_L'high).
It's not an aggregate, it doesn't use named association to distinguish it from a parenthesized expression having a single choice (9.3.3 Aggregates).
Because you're not using a reference covering expressions you may not be aware what this allocator can do. Creating an MCVE:
use std.textio.all;
entity foo is
end entity;
architecture fum of foo is
procedure Shrink_line(L : inout LINE; pos : in integer)
is
variable old_L : LINE := L;
begin
if pos > 1 then
L := new string'(old_L(pos to old_L'high));
Deallocate(old_L);
end if;
end;
begin
process
variable L: LINE;
begin
write (L, string'("...shrinking violet"));
Shrink_line(L, 14);
writeline(OUTPUT,L);
wait;
end process;
end architecture;
Running this code in a simulation provides an output:
ghdl -a foo.vhdl
ghdl -e foo
ghdl -r foo
violet
The output comes from the writeline to OUTPUT (which is the File STD_OUTPUT (stdout in POSIX parlance).
9.3.7 Allocators, para 2:
The type of the object created by an allocator is the base type of the type mark given in either the subtype indication or the qualified expression. For an allocator with a subtype indication, the initial value of the created object is the same as the default initial value for an explicitly declared variable of the designated subtype. For an allocator with a qualified expression, this expression defines the initial value of the created object.
Creating the new allocator with a subtype constraint from the old allocator copied the string from the old allocator starting at position pos.
One other thing to note is that a string left bound is 1 by default. Shrink_line counted on that.

How would I create a function to convert from an integer to std_logic vector in VHDL?

I am seeking help as I am learning this language construct.
Here is what I have:
function int_slv(val,width: integer) return std_logic_vector is
variable R: std_logic_vector(0 to width-1):=(others=>'0')
variable b:integer:= width;
begin
if (b>32) then
b=32;
else
assert 2**bits >val report
"value too big for std_logic_vector"
severity warning
end if;
for i in 0 to b-1 loop
if val ((val/(2**i)) MOD 2 = 1) then
R(i)='1';
end if;
end loop;
return(R);
end int_slv;
In addition to 5 syntax errors, one wrong identifier and a modulo reduction expressions expressed as an element of an array as well as several sets of redundant parentheses, your modified code:
library ieee;
use ieee.std_logic_1164.all;
package int2bv_pkg is
function int_slv (val, width: integer) return std_logic_vector;
end package;
package body int2bv_pkg is
function int_slv (val, width: integer) return std_logic_vector is
variable R: std_logic_vector(0 to width-1):=(others=>'0'); -- added ';'
variable b:integer:= width;
begin
if b > 32 then
b := 32; -- ":=" is used for variable assignment
else
assert 2 ** width > val report -- width not bits
"value too big for std_logic_vector"
severity warning; -- missing semicolon at the end of assertion
end if;
for i in 0 to b - 1 loop
if val/2 ** i MOD 2 = 1 then -- not val (...)
R(i) := '1'; -- ":=" variable assign.
end if;
end loop;
return R; -- parentheses not needed
end int_slv;
end package body int2bv_pkg;
analyzes (compiles). The exponentiation operator "**" is the highest priority, the division operators "/" and "mod" are the same priority and executed in the order they are found (left to right). It's likely worthwhile learning VHDL operator precedence.
You were using "=" for variable assignment when you should have been using ":=" in two places, you were missing two semicolons and were using the identifier bits (which isn't declared in your function) where apparently you meant width.
The modified example analyzes, and hasn't been tested absent a Minimal, Complete and Verifiable example in the question.
Note that a package body is a design unit as is a package declaration. There are various other places in other design units you can introduce a function body.
You could also note the 2 ** 31 is outside the guaranteed range of an integer in VHDL equal to 2147483648, while the INTEGER value range guaranteed to be from -2147483647 to +2147483647 at a minimum.
This implies that were ever you are using a value that derived from an expression equivalent to 2 ** 31 you can incur a range error during execution (either at elaboration or during simulation).
This pretty much says you need a VHDL implementation with a larger INTEGER value range or you need to rethink what you're doing.
As a matter of course there are integer to unsigned and integer to signed functions found in package numeric_std in library IEEE.
The result of such can be type converted to std_logic_vector, and the source code can make great learning aids on how to wend through the limitations VHDL imposes. These to_signed or to_unsigned functions would be capable of dealing with the maximum value an INTEGER can hold and specify the length of the resulting array type while providing zero or sign filling for array lengths greater than the INTEGER's binary value. That utility extends to clipping using length as well.
VHDL -2008 package numeric_std_unsigned contains a function To_StdLogicVector that does what your int_slv function is intended to do although limited to a NATURAL range for the integer type input.
As #user1155120 has already indicated, the VHDL-2008 package numeric_std_unsigned has a builtin to_stdlogicvector. And #user1155120 already pointed out the to_signed and to_unsigned in numeric_std are available as well.
So, to expand on the previous answer, you can do:
constant C : integer := -6817563;
constant C_VEC : std_logic_vector(31 downto 0) := std_logic_vector(to_signed(c, 32));
And this mechanism will accept the full range of integer. You can also use to_unsigned, but this is limited to the range of natural.

ModelSim does not compile overloaded functions and undefined range types

I'm running ModelSim 10.3d, and I have this code in a package:
package core_params_types is
type array_1d_logic is array (natural range <>) of std_logic;
type array_1d_logic_vector is array (natural range <>) of std_logic_vector (natural range <>);
type array_2d_logic is array (natural range <>, natural range <>) of std_logic;
type array_2d_logic_vector is array (natural range <>, natural range <>) of std_logic_vector (natural range <>);
function or_reduce_2d_logic(a : array_2d_logic; i : integer) return std_logic;
function or_reduce_2d_logic_vector(a : array_2d_logic_vector; i : integer) return std_logic_vector;
function bitwise_cmp(a : std_logic_vector; b : std_logic_vector) return std_logic;
function bitwise_cmp(a : std_logic; b : std_logic) return std_logic;
function full_adder(a : std_logic_vector; b : std_logic_vector; ci : std_logic) return std_logic_vector;
function sign_extend(a : std_logic_vector; b : integer) return std_logic_vector;
function sign_extend(a : std_logic; b : integer) return std_logic_vector;
function logic_extend(a : std_logic_vector; b : integer) return std_logic_vector;
function logic_extend(a : std_logic; b : integer) return std_logic_vector;
ModelSim spits the following errors:
-- Loading package STANDARD
# -- Loading package TEXTIO
# -- Loading package std_logic_1164
# -- Loading package NUMERIC_STD
# -- Loading package MATH_REAL
# -- Loading package ATTRIBUTES
# -- Loading package std_logic_misc
# -- Compiling package core_params_types
# ** Error: core_params_types.vhd(40): near "<>": syntax error
# ** Error: core_params_types.vhd(42): near "<>": syntax error
# ** Error: core_params_types.vhd(45): (vcom-1136) Unknown identifier "array_2d_logic_vector".
# ** Error: core_params_types.vhd(48): (vcom-1295) Function "bitwise_cmp" has already been defined in this region.
# ** =====> Prior declaration of "bitwise_cmp" is at core_params_types.vhd(47).
# ** Error: core_params_types.vhd(53): (vcom-1295) Function "sign_extend" has already been defined in this region.
# ** =====> Prior declaration of "sign_extend" is at core_params_types.vhd(52).
# ** Error: core_params_types.vhd(55): (vcom-1295) Function "logic_extend" has already been defined in this region.
# ** =====> Prior declaration of "logic_extend" is at core_params_types.vhd(54).
# ** Error: core_params_types.vhd(310): VHDL Compiler exiting
The .do file contains the following commands:
transcript on
if {[file exists rtl_work]} {
vdel -lib rtl_work -all
}
vlib rtl_work
vmap work rtl_work
vcom -2008 -work work {core_params_types.vhd}
vcom -2008 -work work {alu.vhd}
vcom -2008 -work work {tb_alu.vhd}
vcom -2008 -work work {alu.vhd}
vsim -t 1ps -L altera -L lpm -L sgate -L altera_mf -L altera_lnsim -L cyclonev -L rtl_work -L work -voptargs="+acc" tb_alu
add wave *
view structure
view signals
run -all
I run the ModelSim simulation from Quartus, which compiles the code without errors, and generates a circuit. ModelSim says that the functions are already defined. That is correct, but they have different types, so they should be overloaded. And also ModelSim does not understand the declaration of the array types.
A type declaration
type array_1d_logic_vector is array (natural range <>) of std_logic_vector (natural range <>);
is not valid. You do not declare the index type of the element type.
Instead try:
type array_1d_logic_vector is array (natural range <>) of std_logic_vector;
You constrain the element subtype in an object declaration for example:
variable foo: array_1d_logic_vector(0 to 1)(7 downto 0);
Where the element subtype constraint is 7 downto 0 and the array constraint is 0 to 1.
See IEEE Std 1076-2008 5.3.2 Array types, 5.3.2.1 General paragraph 6:
An unbounded array definition in which the element subtype indication denotes either an unconstrained composite subtype or a subtype that is not a composite subtype defines an array type and a name denoting that type. For each object that has the array type, the number of indices, the type and position of each index, and the subtype of the elements are as in the type definition. The index subtype for a given index position is, by definition, the subtype denoted by the type mark of the corresponding index subtype definition. The values of the left and right bounds of each index range are not defined, but shall belong to the corresponding index subtype; similarly, the direction of each index range is not defined. The symbol <> (called a box) in an index subtype definition stands for an undefined range (different objects of the type need not have the same bounds and direction).
There is a code example found in 5.3.2.1 (toward the end).
And if the second form looks easy to mess up, it is. You can declare objects of the same type with elements that have different subtype constraints and are incompatible when their lengths differ.
Without seeing the log file output for any synthesis operations using the original successful synthesis would not be compliant to the VHDL standard.
Without going through everything with a fine tooth comb your test case package declaration doesn't match the line numbers given in example code. It seems like you are re-declaring functions in the package body (noting the line number 310). Try removing the duplicate function declarations.
(You could also provide an actual Minimal, Complete, and Verifiable example, it'd do wonders for telling exactly what's going on).

Why can't I call a function in a constant declaration, that is defined in the same package in ModelSim?

I have a VHDL package that defines a function (forward declaration) and a constant. The constant's value is calculated by that function, whose body is located in the package body.
As of now ModelSim/QuestaSim is the only tool that does not like this code. It needs 2 packages so the body was parsed before the constant declaration.
package test is
function mytest(param : boolean ) return boolean;
constant value : boolean := mytest(TRUE);
end package;
package body test is
function mytest(param : boolean ) return boolean is
begin
return not param;
end function;
end package body;
Is this not allowed in VHDL and other tools use relaxed parsing rules, or is that a ModelSim issue?
With a deferred constant, and assign in package body after mytest function is elaborated, it is possible even in ModelSim:
package test is
function mytest(param : boolean ) return boolean;
constant value : boolean;
end package;
package body test is
function mytest(param : boolean ) return boolean is
begin
return not param;
end function;
constant value : boolean := mytest(TRUE);
end package body;
Handling across different tools appears to be inconsistent, since as you notice ModelSim requires the deferred constant, but Altera Quartus II allows assign of constant before function elaboration, thus without deferred constant.
The VHDL-2008 standards covers subprogram elaboration in:
14.4.2.1 General: ..., it is illegal to call a subprogram before its corresponding body is elaborated.
Effect of subprogram body elaboration is described in:
14.4.2.2 Subprogram declarations, bodies, and instantiations: ... Elaboration of a subprogram body, other than the subprogram body of an uninstantiated subprogram, has no effect other than to establish that the body can, from then on, be used for the execution of calls of the
subprogram.
Alternative way is to suppress this warning by inserting the following lines into modelsim.ini file:
[msg_system]
; Downgrade the following error:
; Error (suppressible): (vcom-1594) Cannot call subprogram before it is elaborated.
; See more on: https://stackoverflow.com/a/29764446/2506522
warning = 1594

Resources