Language Change Specification for New Predefined Attributes: 'actual, and 'formal

LCS Number: LCS-2016-060
Version: 1 {06-Jan-2017}
2 {10-Jan-2017}
Date: 10-Jan-2017
Status: Voting
Author: Patrick Lehmann
Email: Main.PatrickLehmann
Source Doc: New Predefined Attributes: 'actual, and 'formal
Summary: Adds attributes to access attributes of an actual.

Voting Results: Cast your votes here

Yes:

No:

  1. Kevin Jennings - 2017-01-10 - Ver 1, overlaps with 72a which I think provides a better implementation for end users.
  2. Thomas Preusser - 2017-01-17 - Ver 1: postpone until use case is illustrated and understood, see comments below.
  3. Martin Zabel - 2017-01-21 - ver 2: see my comment dated from 2017-01-21.
  4. Patrick Lehmann - 2017-01-25 - ver 2: I see currently no way to solve the issues in the LCS and in LCS 072a
  5. Lieven Lemiengre- 2017-01-27

Abstain:

Style Notes

Changes are shown in red font.
Deletions are crossed out.
Editing or reviewing notes in green font.

Reviewing Notes

Version 1:
The proposed attribute works for generic and port maps. It allows a user to access attribute return types or values of an associated actual to a formal.

Version 2:
Changed name from 'ACTUAL_SUBTYPE to 'ACTUAL .

Details of Language Change

16.2.2 Predefined attributes of types and objects

P'ACTUAL Kind: Subtype
  Prefix: Any prefix P that is an interface object.
  Result: The subtype of an actual associated to a formal.
  Restrictions: This attribute is allowed only as the prefix of the name of another attribute; for example, P'ACTUAL'LEFT.



Comments

Version 1

This is non-technical critique so ignore if you want, but I think it is still relevant since it involves how an end user is going to get acquanted to this new feature. When the "VHDL-2017 What's New for Dummies" book comes out, and you turn to the section talking about how one accesses attributes within a subprogram, this is what you might see:
function foo(s: std_logic; v: std_logic_vector) return integer is
    variable a, b: integer;
begin
    a := v'left; -- This is how one retrieves the left bound of a vector
    b := s'actual_subtype'left; -- This is how one retrieves the left bound of a scalar
    return(a);
end function foo;

The user will, I think, rightly look at this and question why in the world is there so much typing in order to get the left bound of a scalar when it is so straightforward to get it for a vector? They will also have a valid beef about lack of consistency. There was precedence in how to get the attributes of a vector, how come that same mathod wasn't chosen for scalars?

The users (and the tool makers) ultimately bear whatever convenience or burden the LRM puts on them. I think that once a person understands what 'bounds' are, that one has a mental model of what it means to talk about the 'bounds of a scalar' and the 'bounds of a vector' and would probably find it intuitive to access the 'bounds' of scalars and vectors in the same way. The less frequent user would be rightly ticked off that they need to use different methods to get at what they consider to be the same type of thing...after having to go back to the 'Dummies' book to see once again how to get the left bound of a scalar again.

My two cents is, if you vote for this proposal, I think you should be comfortable explaining your answer to an end user to the question "Is this really the best that can be done here? Really???"

I'm not trying to get into a debate on this and, as I said it is non-technical, just putting it out there asking people to consider the end user's view and how this feature could very likely be perceived out in the world. I'm not trying to go all 'Marketing' on folks, but this one doesn't look pretty to an end user and it easily could have. Plus we are all end users as well, do you really want to be accessing scalars and vectors differently when you're writing code?

-- Kevin Jennings - 2017-01-06

I'll think about your notes and maybe come up with some improvements, but just for now, this LCS is a basis for the LCS 072 series, right?

For your example, if v is a constrained vector, which is mostly the case on entity port lists, then v'ACTUAL_SUBTYPE'LEFT can refer to the actual's bounds, whereas v'LEFT returns the bounds of the formal. Both values might be different.

The difference is not the handling of attributes for arrays and scalars. The difference is that array bounds can be moved in an assignment and association, whereas type ranges can not be moved. But this is all independent on how you access the information. 'LEFT for scalar and arrays is not semantically the same operation. It just happens that both attributes have the same name, because they are defined on different types.

-- Patrick Lehmann - 2017-01-07

While it appears that this feature can be implemented technically, I have a hard time identifying its utility. Isn't it that function or entity interfaces simply use what they need? If the interface is constrained, you have successfully grounded the uncertainty of direction and concrete bounds. What is the use case for recovering it? If a function is to behave slightly differently if the actual ranges of its parameters vary, shouldn't it be generic with different instantiations using the appropriate subtypes?

-- Thomas Preusser - 2017-01-10

While the presented attribute works on any type, the major use case is for scalar types. It's are requirement for the LCS 072 series. In FunctionKnowsVectorSize, a function can no access range constraints of an associated actual, because all attribute are applied to the type of the formal, so for example if you pass in a paramter X of subtype integer range 0 to 7, then X'high will result in INTEGER'high and not to 7.

-- Patrick Lehmann - 2017-01-10

Reviewing the LCS072(a) documents, it appears that they have both diverted and extended the original goal of the proposal significantly. It is only those scalar extras that may motivate this LCS. The scalar extras of LCS072(a) also appear to be limited to signal parameters, which appears to me to have a very confined use scenario and hence little impact whatsoever. This LCS, on the other hand, makes scalar attribute inheritance a general feature, which might even impact compilation times on a broad scale as each call of a function with subtypes may require its own full elaboration run. The re-use of intermediate compilation results is complicated as the invariance with respect to inherited attributes must be proven by the compiler.

In any case, I cannot find a convincing practical use case neither here nor there. Circular references to the mutual other LCS would not be helpful either.

-- Thomas Preusser - 2017-01-10

TP: The scalar extras of LCS072(a) also appear to be limited to signal parameters

KJ: Not intentionally, it is supposed to cover variables as well.

TP: In any case, I cannot find a convincing practical use case neither here nor there.

KJ: One use case would be when implementing a function that provides some modulo arithmetic functionality before returning a value out the function. By virtue of LCS 72, the function would be able to access the attributes of the target of a function. By virtue of LCS 72a (or LCS 60), scalars would now have attributes so the 'wrapping around' part could be implemented with an 'if' statement that uses target'low, target'high. A related example would be to provide upper and lower limits that are defined by target'low and target'high rather than wrapping.

-- Kevin Jennings - 2017-01-10

KJ: Sorry for being annoying but I am still not convinced.

#1: I suppose attributes are also to be propagated to constant parameters then? In the end, this is the default input class and probably the most frequently used one in actual function implementations.

#2: Even though your example builds some scenario aiming to render the propagation of scalar attributes useful, it still follows the idea of the original proposal to make result properties accessible to function implementations. It may be a good idea to regularize everything and extend this notion of attribute propagation to the parameters of all interfaces, subprograms or entities. However, this is a drastically broader modification that should be motivated by a convincing use case. I would also feel much more comfortable with this extended version if tool vendors indicated that the implicit generic subtyping implied by this modification will not notably effect simulation performance.

-- Thomas Preusser - 2017-01-10

Version 2

TP: I suppose attributes are also to be propagated to constant parameters then?

KJ: Yes, constants are covered in 72a. You may or may not like what is defined, but constants are covered.

TP: It may be a good idea to regularize everything and extend this notion of attribute propagation to the parameters of all interfaces, subprograms or entities. However, this is a drastically broader modification that should be motivated by a convincing use case.

KJ: I agree and LCS 72a goes only as far as needed by the use case which is a slight derivative of the proposal associated with LCS 72. I'll also say that LCS 18, 60 and 72a do not currently have an articulated use case unless LCS 72 is approved.

TP: I would also feel much more comfortable with this extended version if tool vendors indicated that the implicit generic subtyping implied by this modification will not notably effect simulation performance.

KJ: I won't pretend to speak for the tool implementer but the subtype information for objects is already available and being used at run time in order to verify that an actual is within the range of the subtype of the formal for a subprogram call and to insure that assignments to an actual are within the bounds of the subtype so I don't think it should be much of a stretch to make that information available inside the subprogram. LCS 72a intends to provide this connection using existing syntax currently only available to arrays, LCS 60 chooses a different path to make the connection to meet the same goal. It also goes beyond the use case needed goal (whether that is 'good' or not).

Thanks for your input.

-- Kevin Jennings - 2017-01-11

If P denotes an array, which subtype is returned: the element or the index subtype? Maybe 'ACTUAL should be restricted to interface objects of scalar types or subtypes.

I think the description of the return value should be changed to that of O'SUBTYPE:

"The fully constrained subtype that is the subtype of O, together with constraints defining any index ranges that are determined by applica- tion of the rules of 5.3.2.2. (If O is an alias for an object, then the result is determined by the declaration of O, not that of the object.)"

Note: I prefer 'ACTUAL_SUBTYPE.

-- Martin Zabel - 2017-01-11

Function interfaces regularly comprise constant parameters. These can be associated with literals, which are formally typed as universal_(integer|real). Is there any sensible interpretation of the attributes accessible through 'actual in this case?

-- Thomas Preusser - 2017-01-13

Noting that implementing this LCS there are new problems presented to the user. In my opinion, avoiding the creation of new hassles for an end user should be a strong consideration.

- New error condition is introduced.

    signal S: natural range 3 to 8;
    constant Sleft:  integer := S'actual'left; -- This is a new error condition since S is not an interface object.  User needs to remember to NOT use 'actual here
    constant Sleft:  integer := S'left; -- This will be allowed by LCS-2016-018.
- Creates an unreported user design issue when code gets refactored because of sensitivity to context.

Consider if the user decides to refactor their code a bit and move the 'Sleft' out of the architecture and into a procedure. Furthermore, the procedure is applicable to the full range of type natural. Copy/paste refactoring would likely produce:

    signal S: natural range 3 to 8;
    ...
    Call the procedure foo as foo(S);
    ...
    procedure foo (signal S: natural) is
        constant Sleft:  integer := S'left; -- This form is now 'wrong' since it will return 0 rather than the value 3 from the actual.
        constant Vleft:  integer := V'left; -- This is correct and returns the value 7 from the actual
The above will compile without error but will not produce the same value of 3 for Sleft as it did before refactoring. Instead, the user must now modify their previously working code and instead use S'actual'left. But since there was no compiler error produced, the user is likely to have to debug in simulation to find the error.

- Vector and scalar usage is different for no apparent reason to the end user.

    signal S: natural range 3 to 8;
    signal V: std_ulogic_vector(7 downto 0);
procedure foo (signal S: natural; V: std_ulogic_vector) is
    constant Sleft:  integer := S'actual'left; -- Why is it that I need to say S'actual rather than S...
    constant Vleft:  integer := V'left; -- when you could figure out what I wanted for a vector???
Alternatives: Neither of these end user problems are encountered if LCS-2016-072a is implemented instead.

- No new errors are produced

- S'left will work properly in all of these contexts without the end user having to make any code adjustments and without having to know which context they are in.

- No debug required when copy/pasted code is refactored and the code context changes and yet no errors are reported.

I think the basic problem here is that folks are clinging to attributes and how they are used today and thinking that there must be something 'different' in the code in order to distinguish the new usage. What you should consider instead is what do you think the end user should expect to get when they say "Sleft = S'left"? Then ask why they should have to alter their code based on code context to get what they want?

-- Kevin Jennings - 2017-01-16

TBP: Function interfaces regularly comprise constant parameters. These can be associated with literals, which are formally typed as universal_(integer|real). Is there any sensible interpretation of the attributes accessible through 'actual in this case?

PL: Each literal is implicitly converted (before ?) association. As far as I understand this, the literal (actual) gets the subtype (and bounds) of the formal.

-- Patrick Lehmann - 2017-01-16

@KevinJennings

PL: I think we are going a bit off-topic here ... I is not a languages concern how a user or his IDE refactors the code! VHDL is still a strong typed language with mostly very precise rules and not JavaScript. So the user must know some specifics about the used statements, objects and types.

PL: It's wrong to assume that scalar values and arrays should behave in the same way. One is an atomic type, the other one is a composite type. It is also wrong to assume a similar behavior for an attribute like 'LEFT, just because the authors chose to use the same name for two different things. One is a scalar type's range boundary and the other one is an array index's range boundary.

PL: As far as I understand the LRM, objects are already classified in interface objects and locally declared objects, so it is not difficult to track if 'actual is allowed.

-- Patrick Lehmann - 2017-01-16

PL: Each literal is implicitly converted (before ?) association. As far as I understand this, the literal (actual) gets the subtype (and bounds) of the formal.

TBP: The very purpose of using 'actual is to give you access to the situation before this conversion. And I am afraid, there is no such intuitive before in the case of constant literals. So as to avoid diversion among implementations, a clear specification is needed. Acceptable choices may be (a) to disallow 'actual on constant parameters, (b) to make the actual subtype equivalent to the formal subtype or (c) to create an implicit one-element subtype of the formal whose range coincides with the exact constant value. As I am still short of a convincing use case, I do not know which of these choices fits best.

-- Thomas Preusser - 2017-01-16

As the 'actual is not as firmly defined as it may appear at a first glance (see above), specifications are required to eliminate uncertainty and prevent tool divergence. Without an illustrative example that helps to understand the usage scenario, those specification choices can only go wrong. That's why I have changed my vote to a straight no and would ask for postponing this LCS until real demand and well-understood usage patterns become available.

-- Thomas Preusser - 2017-01-17

Even with LCS-2016-018, attributes like 'LEFT can be only retrieved from objects or subtypes, but not from expressions. But, according to clause 4.2.2.1: "The actual designator associated with a formal of class constant shall be an expression." For parameters of class signal, variable or file, there is no problem, because these parameters must already be associated with objects.

For functions which access the attribute 'ACTUAL of the formal parameter, the associated actual designator shall be a name denoting an object. Such formal parameters cannot have a default expression.

I have posted a similar comment below LCS-2016-072a because it has the same problem.

-- Martin Zabel - 2017-01-21

Topic revision: r23 - 2020-02-17 - 15:34:41 - JimLewis
 
Copyright © 2008-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback