Changes are shown in red font.
Deletions are crossed out.
Editing or reviewing notes in green font.
Reviewing Notes
Version 1:
A pair of procedures (ENV_OPEN, ENV_CLOSE) is provided to read the host environment of a tool. All conditional compilation identifiers
and their values are provided as well as a list of available environment variables. An environment variable can be queried by ENV_GETVALUE.
Version 2:
Version 3:
- Made all conditional analysis identifiers a record element in a deferred constant.
- Created function and procedure overloads to address different use cases
Version 4:
- Specified returned values if operation fails
Details of Language Change
16.5 Standard environment package
16.5.1 General [NEW headline level]
Package ENV contains declarations that provide a VHDL interface to the host environment.
package ENV is
procedure STOP (STATUS: INTEGER);
procedure STOP;
procedure FINISH (STATUS: INTEGER);
procedure FINISH;
function RESOLUTION_LIMIT return DELAY_LENGTH;
[... LCS-2016-011 ...]
[... LCS-2016-006c ...]
type ENV_VARIABLE_NAMES is access LINE_VECTOR;
-- The predefined operations for this type are as follows:
-- function"=" (anonymous, anonymous: ENV_VARIABLE_NAMES) return BOOLEAN;
-- function"/=" (anonymous, anonymous: ENV_VARIABLE_NAMES) return BOOLEAN;
-- procedure DEALLOCATE (P: inout ENV_VARIABLE_NAMES);
type COND_ANALYSIS_IDS is access LINE_VECTOR;
-- The predefined operations for this type are as follows:
-- function"=" (anonymous, anonymous: COND_ANALYSIS_IDS) return BOOLEAN;
-- function"/=" (anonymous, anonymous: COND_ANALYSIS_IDS) return BOOLEAN;
-- procedure DEALLOCATE (P: inout COND_ANALYSIS_IDS);
type ENVIRONMENT is record
-- Resolution_Limit : DELAY_LENGTH; --
Variables : ENV_VARIABLE_NAMES; -- list of pointers to environment variable names
Identifiers : COND_ANALYSIS_IDS; -- list of pointers to conditional analysis identifiers
end record;
procedure ENV_OPEN(Env : out ENVIRONMENT);
impure function ENV_OPEN return ENVIRONMENT;
procedure ENV_CLOSE(Names : in ENVIRONMENT); -- deallocate all internal access values
procedure ENV_GETVARIABLE(Value : out LINE; Name : in STRING; Good : out BOOLEAN);
impure function ENV_GETVARIABLE(Name : in STRING; Good : out BOOLEAN) return LINE;
impure function ENV_GETVARIABLE(Name : in STRING) return LINE;
impure function ENV_GETVARIABLE(Name : in STRING; Good : out BOOLEAN) return STRING;
impure function ENV_GETVARIABLE(Name : in STRING) return STRING;
procedure ENV_GETIDENTIFIER(Value : out LINE; Name : in STRING; Good : out BOOLEAN);
impure function ENV_GETIDENTIFIER(Name : in STRING; Good : out BOOLEAN) return LINE;
impure function ENV_GETIDENTIFIER(Name : in STRING) return LINE;
impure function ENV_GETIDENTIFIER(Name : in STRING; Good : out BOOLEAN) return STRING;
impure function ENV_GETIDENTIFIER(Name : in STRING) return STRING;
type CONDITIONAL_ANALYSIS_IDENTIFIER is record
VHDL_Version : STRING; -- see 24.2 Conditional Analysis Tool Directives
Tool_Type : STRING; -- see 24.2 Conditional Analysis Tool Directives
Tool_Vendor : STRING; -- see 24.2 Conditional Analysis Tool Directives
Tool_Name : STRING; -- see 24.2 Conditional Analysis Tool Directives
Tool_Edition : STRING; -- see 24.2 Conditional Analysis Tool Directives
Tool_Version : STRING; -- see 24.2 Conditional Analysis Tool Directives
end record;
constant COND_ANALYSIS_ID : CONDITIONAL_ANALYSIS_IDENTIFIER;
end package ENV;
[Editor note: Three notes ...]
16.5.5 System Environment and Conditional Analysis Identifier API [NEW]
The procedure ENV_OPEN, with parameter Env, returns a record of type ENVIRONMENT, which describes the current tool environment. The record member Variables
references an array of access values (LINE_VECTOR) representing the names of each available environment variable.
The impure function ENV_OPEN, implements the same behavior as the procedure ENV_OPEN. The procedure's output parameter Env of type ENVIRONMENT
in the return value of the function.
The procedure ENV_CLOSE, with parameter Env, deallocated objects allocated by ENV_OPEN.
The procedure ENV_GETVARIABLE, with parameters Value, Name and Good, returns the value of an environment variable from the host environment as a LINE value. If
the environment variable denoted by Name is not available in the host environment, an error is signaled by setting the status parameter Good to FALSE, otherwise TRUE.
The value of Value is null if the operation is not successful.
The impure function ENV_GETVARIABLE, with parameters Name and Good returning type LINE, implements the same behavior as the procedure ENV_GETVARIABLE, with parameters
Value, Name and Good. The procedure's output parameter Value of type LINE in the return value of the function.
The impure function ENV_GETVARIABLE, with parameter Name returning type LINE, implements the same behavior as the impure function ENV_GETVARIABLE, with parameters
Name and Good returning type LINE. It is an error if Name denotes an environment variable, that doesn't exist in the host environment.
The overloaded impure function ENV_GETVARIABLE, with parameters Name and Good returning type STRING, implements the same behavior as the impure function ENV_GETVARIABLE,
with parameters Name and Good returning type LINE. The function returns the designated object: an object of type STRING.
The impure function ENV_GETVARIABLE, with parameter Name returning type STRING, implements the same behavior as the impure function ENV_GETVARIABLE, with parameters
Name and Good returning type STRING. It is an error if Name denotes an environment variable, that doesn't exist in the host environment.
The procedure ENV_GETIDENTIFIER, with parameters Value, Name and Good, returns the value of a conditional analysis identifier from the tool environment as a LINE value. If
the identifier denoted by Name is not available in the tool environment, an error is signaled by setting the status parameter Good to FALSE, otherwise TRUE.
The value of Value is null if the operation is not successful.
The impure function ENV_GETIDENTIFIER, with parameters Name and Good returning type LINE, implements the same behavior as the procedure ENV_GETIDENTIFIER, with parameters
Value, Name and Good. The procedure's output parameter Value of type LINE in the return value of the function.
The impure function ENV_GETIDENTIFIER, with parameter Name returning type LINE, implements the same behavior as the impure function ENV_GETIDENTIFIER, with parameters
Name and Good returning type LINE. It is an error if Name denotes an identifier, that doesn't exist in the tool environment.
The overloaded impure function ENV_GETIDENTIFIER, with parameters Name and Good returning type STRING, implements the same behavior as the impure function ENV_GETIDENTIFIER,
with parameters Name and Good returning type LINE. The function returns the designated object: an object of type STRING.
The impure function ENV_GETIDENTIFIER, with parameter Name returning type STRING, implements the same behavior as the impure function ENV_GETIDENTIFIER, with parameters
Name and Good returning type STRING. It is an error if Name denotes an identifier, that doesn't exist in the tool environment.
The record type CONDITIONAL_ANALYSIS_IDENTIFIER describes the set of available conditional analysis identifiers. The record shall contain all identifiers
as defined in 24.2 Conditional Analysis Tool Directives as well as all tool and user defined identifiers. Each identifier is represented by a corresponding record
element of the same name. Each element is a STRING object holding the associated value of an identifier. None of these record elements shall be a null value.
A deferred constant COND_ANALYSIS_ID of type CONDITIONAL_ANALYSIS_IDENTIFIER is defined in the package. It's content is assigned in the tool dependent package body.
Comments
Version 1
For ENV_GETVALUE, how do I pick the appropriate length for Value? How does the procedure indicate the size of the object?
See Sread. It returns a length value in this situation.
Why do I need anything other than ENV_GETVALUE? Why do I want to get the entire object as a data structure?
--
Jim Lewis - 2017-02-06
Or even go crazy and have:
procedure ENV_GETVALUE(Name : in STRING; Value : out STRING; Good : out BOOLEAN);
impure function ENV_GETVALUE(Name : in STRING) return STRING;
But I can't see a scenario where I need anything more complex than that from VHDL.
--
Rob Gaddi - 2017-02-06
For the procedure, I think it needs STRLEN (like sread) rather than Good. Like sread, if there is an error, STRLEN = 0.
procedure ENV_GETVALUE(Name : in STRING; Value : out STRING; STRLEN : out Natural);
I agree with Rob about the procedure though
--
Jim Lewis - 2017-02-06
So I need to return either a size or a LINE parameter, right?
Some users demanded that the values for the conditional compilation should be available in code too. By adding all the identifiers
from 24.2 this demand is fulfilled.
I think a user should have access to all available environment variable names. If I start to use such a feature in a language, I
get quickly to the point that I can't list all available variables.
--
Patrick Lehmann - 2017-02-07
IMHO this appears too big a hack right now. Too many compromises to make it work with the current version of VHDL. The record ENVIRONMENT appears especially obscure
to me as it is an artificial join of the identifiers for conditional compilation (CC) and the OS environment variables both delivered through different abstractions.
Some kind of a map abstraction would be appropriate in both cases so as to warrant maximum flexibility. LCS 061 allows to have a CC identifier set extended by the tool
or the user. The current approach leaves those inaccessible. With what we have in VHDL, the map abstraction is best represented by a function. So, I would expect a
core set of functions like this:
function GETENV(name : in string) return string; -- would have to return an empty string for a name not defined in the environment
OR closely following the POSIX function:
function GETENV(name : in string) return line; -- returns null for a name not defined in the environment
AND, a similar access to CC identifiers:
function GETDEF(name : in string) return string/line;
Optionally, you might want to consider to give access to a list of defined names. I think functions returning a line_vector would be most appropriate:
function GETENV_NAMES return line_vector;
function GETDEF_NAMES return line_vector;
--
Thomas Preusser - 2017-02-07
"For the procedure, I think it needs STRLEN (like sread) rather than Good. Like sread, if there is an error, STRLEN = 0. "
But what if the variable exists, and is empty?
e.g. setenv MYLIST ""
I think the STRLEN should be -1 in case of an error, 0 in case of empty.
I would vote definately YES on the impure function.
--
Jakko Verhallen - 2017-02-07
WRT the names defined by conditional compilation, why not create a set of similarly named deferred constants here in the package std.env?
--
Jim Lewis - 2017-02-10
@Jim
: Introducing such constants may help for the standard identifiers, which Patrick also included in this environment record. Both approaches are not really
suitable to cope with tool- and user-defined identifiers. At least I would avoid having a record type or set of pre-defined constants that are adjusted in each
run to reflect the currently defined set of conditional compilation identifiers.
IMHO, a lookup mechanism just as used by Patrick for the environment variables should be provided for conditional compilation identifiers as well. This:
- keeps them in their own name space,
- makes them easily accessible from VHDL code, and
- is fully flexible with respect to tool- and user-defined identifiers.
See LCS 006e for an alternative pursuing this approach.
--
Thomas Preusser - 2017-02-10
It would be polite to get a chance to address the comments and have some time to rewrite the LCS.
--
Patrick Lehmann - 2017-02-11
string return values are awkward to work with. It would need to be called with a corresponding call to justify to be even usable. Otherwise, the only thing one
can do with it is use the return value in an expression.
We need some indication to size the string return value. see SREAD.
--
Jim Lewis - 2017-02-14
Version 4
These functions still have undefined behavior:
impure function ENV_GETVARIABLE(Name : in STRING; Good : out BOOLEAN) return STRING;
impure function ENV_GETIDENTIFIER(Name : in STRING; Good : out BOOLEAN) return STRING;
The definition for ENV_GETVARIABLE is (ENV_GETIDENTIFIER is similar):
The overloaded impure function ENV_GETVARIABLE, with parameters Name and Good returning type STRING, implements the same behavior as the impure function ENV_GETVARIABLE, with parameters Name and Good returning type LINE. The function returns the designated object: an object of type STRING.
But, if the environment variable denoted by Name is not availbale in the host environment, then the function ENV_GETVARIABLE(Name : in STRING; Good : out BOOLEAN) return LINE; returns a null access value. Thus, the function above cannot return the designated object (as already expressed in my private e-mail to you before). There are two options here:
- It is an error if Name denotes an environment variable, that doesn't exist in the host environment. (Like it is done for the function
ENV_GETVARIABLE(Name : in STRING) return STRING;.)
- Return a null string
"", and check for existence using Good.
Why I dislike this version of the LCS:
1) For each namespace (environment variables and identifiers), this LCS defines 5 functions where only 2 functions are required. For example, the procedure call
constant Name : string := "test";
variable Value : line;
variable Good : boolean;
...
ENV_GETVARIABLE(Value, Name, Good);
could be simply replaced by:
Value := ENV_GETVARIABLE(Name, Good);
And this call could be even more simplified to:
Value := ENV_GETVARIABLE(Name);
because the out parameter Good is never needed. Whether the variable exists in the host environment or not could be simply determined by the returned Value:
Value := ENV_GETVARIABLE(Name);
if Value = null then
report "Environment variable does not exist in host environment." severity error;
elsif Value.all = "" then
report "Environment variable is defined but empty.";
else
report "Environment variable has value: " & Value.all;
end if;
The discussion for the function ENV_GETVARIABLE(Name : in STRING; Good : out BOOLEAN) return STRING;" depends on how the undefined behavior is solved:
- If an error is raised anyway, then Good needs not to be checked and one can simply call the function
ENV_GETVARIABLE(Name : in STRING) return STRING;".
- If a null string is returned, then Good must be checked after the returned value is used in an expression. I expect less readable code here.
The function ENV_GETVARIABLE(Name : in STRING) return STRING; is fine, especially, if the (synthesis) tool does not support access types.
Thus, the only required functions are:
impure function ENV_GETVARIABLE(Name : in STRING) return LINE;
impure function ENV_GETVARIABLE(Name : in STRING) return STRING;
Same discussion applies to ENV_GETIDENTIFIER.
2) Why should there be a function ENV_OPEN and a procedure ENV_OEPN?
3) Why are there two types ENV_VARIABLE_NAMES and COND_ANALYSIS_IDS representing both an access type of LINE_VECTOR?
4) According to the LCS text, the type ENVIRONMENT does describe the current tool environment. But why does it contain only the identifiers and not also the values?
Added later:
5) I find writing something like if COND_ANALYSIS_ID.Tool_Type = "SIMULATION" then just too long. The prefix COND_ANALYSIS_ID is also hard to remember. I prefer LCS 006f instead.
--
Martin Zabel - 2017-03-07