TWiki> P1076 Web>VHDL2017>LCS2016_059 (revision 36)EditAttach

Language Change Specification for Improved Type Generics

LCS Number: LCS-2016-059
Version: 10
Date: 26-Mar-2017
Status: Voting
Author: Patrick Lehmann
Martin Zabel
Jim Lewis
Email: Main.PatrickLehmann
Main.MartinZabel
Main.JimLewis
Source Doc: Array Type Generics
Summary: Adds type class insurances (discrete, integer, float, array, ...) for generic types.

Voting Results: Cast your votes here

Yes:

  1. Lieven Lemiengre - 2017-02-16 - ver 5
  2. Daniel Kho - 2017-01-19 - ver 1
  3. Thomas Preusser - 2017-01-19 - ver 3 - but consider comment of 2017-02-08
  4. Jim Lewis - 22-Mar-2017 - ver 9
  5. Patrick Lehmann - 26-Mar-2017 - ver 10

No:

Abstain:

  1. Brent Hayhoe - 2017-02-16 Version 5 - Abstain due to lack of personal time for review.
  2. Martin Thompson - 2017-02-17 Version 2 - Abstain due to lack of personal time for review.

Style Notes

Additions are shown in red font.
Deletions are crossed out.
Restructuring is shown in crossed out gray font somewhere else in gray font.
Editing or reviewing notes in green font.

Reviewing Notes

Version 1: 19-Jan-2017
VHDL's current generic types allow the user to pass an arbitrary type to a subprogram, entity or package, but such a generic type has no type class, because the class of the mapped type is only known at elaboration time, whereas the generic type is already needed at analysis time. So currently, VHDL can not guarantee, if a generic type is e.g. an array. Without knowledge of the type class, we have no predefined operators except for equal/unequal and we have no attributes like 'length or 'range.

This LCS adds type class assurances to generic type definitions in the generic list. It extends the list of predefined operators (implicitly declared in an interface list) if the type class is known. It also adds predefined attributes form types and objects.

Version 2: 20-Jan-2017
Definitions regarding attributes defined for interface types and objects thereof have been unified.

Version 3: 05-Feb-2017

Version 4: 11-Feb-2017

  • Improved paragraphs

Version 5: 12-Feb-2017

  • Restored lost changes from Version 2

Version 6: 10-Mar-2017

  • Updated text in 6.5.7.2 Generic map aspects

Version 7: 19-Mar-2017

  • Introduce type classes
  • Remove named implicit generic types
  • Add syntax for anonymous types to describe implicit types (from LCS 016)
  • Use the private keyword like in Ada

Version 8: 21-Mar-2017

  • Renamed typeclass to incomplete type definition
  • Moved operator and attributes to 5.8
  • revised text about unknown types to specify an anonymous type indication

Version 9: 22-Mar-2017

  • Minor grammar and edits

Version 10: 26-Mar-2017

  • Concatenation is only for single dimensional arrays
  • Added aggregation as a basic operation

Details of Language Change

5.1 General

On page 35 Edit 4th paragraph as below

There are five primary classes of types. Scalar types are integer types, floating-point types, physical types, and types defined by an enumeration of their values; values of these types have no elements. Composite types are array and record types; values of these types consist of element values. Access types provide access to objects of a given type. File types provide access to objects that contain a sequence of values of a given type. Protected types provide atomic and exclusive access to variables accessible to multiple processes.

On page 35 add new paragraph after 4th paragraph (above)

For ports, parameters, and external names the type of an object may also be specified as an anonymous type. An anonymous type is an incomplete type indication that defines a set of allowed operations.

5.5.1 General

A file type definition defines a file type. File types are used to define objects representing files in the host system environment. The value of a file object is the sequence of values contained in the host system file.

file_type_definition ::= file of type_mark

The type mark in a file type definition defines the subtype of the values contained in the file. The type mark may denote either a fully constrained, a partially constrained, or an unconstrained subtype. The base type of this subtype shall not be a file type, an access type, or a protected type , or a formal generic type. If the base type is a composite type, it shall not contain a subelement of an access type. If the base type is an array type, it shall be a one-dimensional array type whose element subtype is fully constrained. If the base type is a record type, it shall be fully constrained.

NOTE -- A type mark in a file type declaration may be a formal generic type or have a subelement of a formal generic type. However, for an instance of the enclosing declaration that defines the formal generic type, a check is required that the actual generic type is neither an access type, protected type or file type nor contains a subelement of an access type, protected type or file type. Depending on the implementation, this check may be done during analysis of the instantiation, or it may be deferred until the design hierarchy is elaborated.

5.8 Anonymous Types [new]

5.8.1 General [new]

An anonymous type is an incomplete type indication that defines a set of allowed operations. An anonymous type is a superset of type classes.

An anonymous type can be classified as a private, scalar, discrete, integer, physical, floating, array, access, or file incomplete type definition.


anonymous_type_indication ::=             [Moved from LCS 016]
  type is incomplete_type_definition

incomplete_type_definition ::=
    private_incomplete_type_definition
  | scalar_incomplete_type_definition
  | discrete_incomplete_type_definition
  | integer_incomplete_type_definition
  | physical_incomplete_type_definition
  | floating_incomplete_type_definition
  | array_incomplete_type_definition
  | access_incomplete_type_definition
  | file_incomplete_type_definition

incomplete_subtype_indication ::=
    subtype_indication
  | anonymous_type_indication

incomplete_type_mark ::=
    type_mark
  | anonymous_type_indication

private_incomplete_type_definition ::= private

scalar_incomplete_type_definition ::= <>

discrete_incomplete_type_definition ::= ( <> )

integer_incomplete_type_definition ::= range <>

physical_incomplete_type_definition ::= units <>

floating_incomplete_type_definition ::= range <> . <>

array_incomplete_type_definition ::=
  array ( array_index_incomplete_type_list )
    of element_incomplete_subtype_indication
 
array_index_incomplete_type_list ::= 
    array_index_incomplete_type { , array_index_incomplete_type } 

array_index_incomplete_type ::=
    index_subtype_definition
  | index_constraint
  | anonymous_type_indication

access_incomplete_type_definition ::=
  access access_incomplete_subtype_indication

file_incomplete_type_definition ::=
  file of file_incomplete_type_mark

The following basic operations are defined for all incomplete type definitions: assignment, allocation, type qualification and type conversion. In addition, each incomplete type definition may include additional predefined operators and attributes.

5.8.2 Private incomplete type [new]

A private incomplete type is an anonymous type that denotes any type except file and protected types.

The following operators are implicitly defined for a private incomplete type: equality (=) and inequality (/=). The predefined attributes for a private incomplete type, and objects thereof, are the same as the predefined attributes common to all types other than a file type or protected type, and objects thereof, respectively, as listed in section 16.2.

5.8.3 Scalar incomplete type [new]

A scalar incomplete type is an incomplete type definition that denotes any scalar type.

The following operators are implicitly defined for a scalar incomplete type: equality (=), inequality (/=), less than (<), less than or equal (<=), greater than (>), greater than or equal (>=), MINIMUM, MAXIMUM, and TO_STRING. The predefined attributes for the scalar incomplete type, and objects thereof are the same as the predefined attributes for scalar types, and objects thereof, respectively, as listed in section 16.2.

5.8.4 Discrete incomplete type [new]

A discrete incomplete type is an anonymous type that denotes any discrete type.

The following operators are implicitly defined for a discrete incomplete type: equality (=), inequality (/=), less than (<), less than or equal (<=), greater than (>), greater than or equal (>=), MINIMUM, MAXIMUM, and TO_STRING. The predefined attributes for the discrete incomplete type, and objects thereof are the same as the predefined attributes for discrete types, and objects thereof, respectively, as listed in section 16.2.

5.8.5 Integer incomplete type [new]

An integer incomplete type is an anonymous type that denotes any integer type.

The following operators are implicitly defined for an integer incomplete type: equality (=), inequality (/=), less than (<), less than or equal (<=), greater than (>), greater than or equal (>=), positive (+), negation (-), plus (+), minus (-), multiply (*), divide (/), power (**), remainder (rem), modulo (mod), absolute (abs), MINIMUM, MAXIMUM, and TO_STRING. The predefined attributes for the integer incomplete type, and objects thereof are the same as the predefined attributes for integer types, and objects thereof, respectively, as listed in section 16.2.

5.8.6 Physical incomplete type [new]

A physical incomplete type is an anonymous type that denotes any physical type.

The following operators are implicitly defined for a physical incomplete type: equality (=), inequality (/=), less than (<), less than or equal (<=), greater than (>), greater than or equal (>=), positive (+), negation (-), plus (+), minus (-), multiply (*), divide (/), remainder (rem), modulo (mod), absolute (abs), MINIMUM, MAXIMUM, and TO_STRING. The predefined attributes for the physical incomplete type, and objects thereof are the same as the predefined attributes for physical types, and objects thereof, respectively, as listed in section 16.2.

5.8.7 Floating incomplete type [new]

A floating incomplete type is an anonymous type that denotes any floating-point type.

The following operators are implicitly defined for a floating incomplete type: equality (=), inequality (/=), less than (<), less than or equal (<=), greater than (>), greater than or equal (>=), positive (+), negation (-), plus (+), minus (-), multiply (*), divide (/), power (**), absolute (abs), MINIMUM, MAXIMUM, and TO_STRING. The predefined attributes for the floating incomplete type, and objects thereof are the same as the predefined attributes for floating-point types, and objects thereof, respectively, as listed in section 16.2.

5.8.8 Array incomplete type [new]

An array incomplete type is an anonymous type that denotes any array type.

The array index incomplete type list may consist of an index subtype definition, an index constraint, or an anonymous type indication. For an array incomplete type that has more than one dimension, it is an error if the array index incomplete type list has both an index subtype definition and an index constraint.

The element incomplete subtype indication may either be a subtype indication or an anonymous type indication.

The basic operation aggregation is defined for any array incomplete type. The following operators are implicitly defined for any array incomplete type: equality (=), and inequality (/=). In addition, the operator concatenation (&) is implicitly defined, if the array incomplete type denotes a single dimensional array. If the array incomplete type denotes a scalar array type, then the following operators are defined: less than (<), less than or equal (<=), greater than (>), greater than or equal (>=), MINIMUM and MAXIMUM. The predefined attributes for the array incomplete type, and objects thereof, are the same as the predefined attributes for array types, and objects thereof, respectively, as listed in section 16.2. Objects created from array incomplete type can be used as a prefix in indexed names (see 8.4) and slice names (see 8.5).

5.8.9 Access incomplete type [new]

An access incomplete type is an anonymous type that denotes any access type.

The access incomplete subtype indication may either be a subtype indication or an anonymous type indication.

The following operators are implicitly defined for an access incomplete type: equality (=), inequality (/=), and DEALLOCATE. The predefined attributes for the interface access type, and objects thereof are the same as the predefined attributes for access types, and objects thereof, respectively, as listed in section 16.2.

[If LCS-2016-030 (Garbage Collection) is approved, the operation DEALLOCATE is not listed as the previous section.]

5.8.10 File incomplete type [new]

A file incomplete type is an anonymous type that denotes any file type.

The file incomplete type mark may either be a type mark or an anonymous type indication.

The following operators are implicitly defined for a file incomplete type: FILE_OPEN, FILE_CLOSE, READ, WRITE, FLUSH and ENDFILE. The predefined attributes for the file incomplete type, and objects thereof are the same as the predefined attributes for file types, and objects thereof, respectively, as listed in section 16.2.

[Editor note: If LCS-2016-006a is approved, then the new file operations from the list of predefined operators needs to be extended.]
[Editor note: FILE_REWIND, FILE_SEEK, FILE_TRUNCATE, FILE_STATE, FILE_MODE, FILE_POSITION, FILE_SIZE, FILE_CANSEEK]

6.5.1 General [For reviewers to follow the chain of EBNF rules.]

An interface declaration is an interface object declaration, an interface type declaration, an interface subprogram declaration, or an interface package declaration.

interface_declaration ::=
      interface_object_declaration
    | interface_type_declaration
    | interface_subprogram_declaration
    | interface_package_declaration

6.5.3 Interface type declarations

6.5.3.1 General [NEW; new level]

An interface type declaration declares an interface type that appears as a formal generic of a generic clause.

[For reviewers to follow the chain of EBNF rules.]

interface_type_declaration ::=
  interface_incomplete_type_declaration
    type identifier [ is incomplete_type_definition ]

interface_incomplete_type_declaration ::=
    type identifier

An interface type provides a means for the environment to determine a type to be used for objects in a particular portion of a description. The set of values and applicable operations for an interface type may be determined by an associated subtype in the environment. The manner in which such associations are made is described in 6.5.7. A generic type declared by an interface type declaration without an incomplete type definition is called an unclassified generic type, otherwise it is called a classified generic type. An unclassified type denotes a private incomplete type. A classified generic type is any interface type declaration except a private incomplete type.

Within an entity declaration, an architecture body, a component declaration, or an uninstantiated subprogram or package declaration that declares a given interface type, the type declared by the given interface type declaration is distinct from the types declared by other interface type declarations and from explicitly declared types. The name of the given interface type denotes both an undefined base type and a subtype of the base type. The class (see 5.1) of the base type is not defined. The following operations are defined for the interface type:

  • The basic operations of assignment, allocation, type qualification and type conversion
  • The predefined equality (=) and inequality (/=) operators, implicitly declared as formal generic subprograms immediately following the interface type declaration in the enclosing interface list.

The name of an interface type declaration of a block statement (including an implied block statement representing a component instance or a bound design entity), a generic-mapped package or a generic mapped subprogram denotes the subtype specified as the corresponding actual in a generic association list.

The type declared by a given interface type declaration is distinct from the types declared by other interface type declarations and from types explicitly declared within the construct. The following basic operations are defined for all interface types: assignment, allocation, type qualification and type conversion. Each interface type definition includes the additional predefined operators and attributes that are defined for corresponding incomplete type definition (see 5.8). These additional operators are implicitly declared as formal generic subprograms with an interface subprogram default in form of a box (<>) immediately following the interface type declaration in the enclosing interface list.

Within a construct that has an interface type declaration, but does not map it, the name of the given interface type denotes both an undefined base type and a subtype of the base type. Within a construct that maps a given interface type declaration, the name of the given interface type declaration denotes the subtype specified as the corresponding actual in a generic association list.

6.5.3.2 Array interface type declarations [new]

A formal array type and the associated actual array type must both be constrained or both be unconstrained. Both must have the same dimensionality, the same index types in each dimension, and the same element types. For a formal constrained array type, the index constraint must be specified in the form of a type mark, and the actual array type must have the same index range as the formal array type.

Example:


package P1 is
  generic (
    type element_type is private;                         -- any type
    type index_type is (<>);                              -- a discrete type
    type array_type is array(index_type) of element_type  -- an array type
  );
end package;

entity E is
end entity;

architecture A of E is
  package I1 is new P1
    generic map (
      element_type => bit,
      index_type =>   natural,
      array_type =>   bit_vector
    );
begin
end architecture;

If the array index incomplete type is specified with an anonymous type indication, then an implicit formal anonymous type with the same incomplete type defintion is declared immediately before the array interface type declaration. If the element incomplete subtype indication is specified with an anonymous type indication, then an implicit formal anonymous type with the same incomplete type defintion is declared immediately before the array interface type declaration.

Example:


package P2 is
  generic (
    -- type anonymous is (<>);              -- implicitly declared anonymous generic discrete type
    -- type anonymous is private;           -- implicitly declared anonymous unclassified generic type
    type array_type is array(type is (<>)) of type is private
  );
  -- example usage of type aliases to create shorter names
  alias index_type   is array_type'INDEX;    -- alias the implicit type with a name
  alias element_type is array_type'ELEMENT;  -- alias the implicit type with a name
end package;

architecture A of E is
  package I2 is new P2
    generic map (
      -- anonymous => bit_vector'INDEX,   -- implicitly associated; see 6.5.7.2
      -- anonymous => bit_vector'ELEMENT, -- implicitly associated; see 6.5.7.2
      array_type =>   bit_vector
    );
begin
end architecture;

6.5.3.3 Access interface type declarations [new]

A formal access type and the associated actual access type must both have the same designated type.

Example:


package P1 is
  generic (
    type designated_subtype;                       -- any type
    type access_type is access designated_subtype  -- an access type
  );
end package;

entity E is
end entity;

architecture A of E is
  package I1 is new P1
    generic map (
      designated_subtype => string,
      access_type        => line
    );
begin
end architecture;
If the access incomplete subtype indication is specified with an anonymous type indication, then an implicit formal anonymous type with the same incomplete type defintion is declared immediately before the array interface type declaration.

Example:


package P2 is
  generic (
    -- type anonymous is private;                    -- implicitly declared unclassified generic type
    type access_type is access type is private
  );
  -- example usage of type aliases to create shorter names
  alias designated_subtype is access_type'DESIGNATED_SUBTYPE;  -- alias the implicit type with a name
end package;

architecture A of E is
  package I2 is new P2
    generic map (
      -- anonymous => line'DESIGNATED_SUBTYPE, -- implicitly associated; see 6.5.7.2
      access_type => line
    );
begin
end architecture;

6.5.3.4 File interface type declarations [new]

A formal file type and the associated actual file type must both have the same designated type.

Example:


package P1 is
  generic (
    type designated_subtype;                      -- any type
    type file_type is file of designated_subtype  -- an file type
  );
end package;

entity E is
end entity;

architecture A of E is
  package I1 is new P1
    generic map (
      designated_subtype => string,
      file_type          =>  line
    );
begin
end architecture;

If the file incomplete type mark is specified with an anonymous type indication, then an implicit formal anonymous type with the same incomplete type defintion is declared immediately before the array interface type declaration.

Example:


package P2 is
  generic (
    -- type anonymous is private;                    -- implicitly declared unclassified generic type
    type file_type is file of type is private
  );
  -- example usage of type aliases to create shorter names
  alias designated_subtype is file_type'DESIGNATED_SUBTYPE;  -- alias the implicit type with a name
end package;

architecture A of E is
  package I2 is new P2
    generic map (
      -- anonymous => line'DESIGNATED_SUBTYPE, -- implicitly associated; see 6.5.7.2
      file_type => line
    );
begin
end architecture;

NOTE -- A type mark in a file interface type declaration may be a formal generic type or have a subelement of a formal generic type. However, for an instance of the enclosing declaration that defines the formal generic type, a check is required that the actual generic type is neither an access type, protected type or file type nor contains a subelement of an access type, protected type or file type. Depending on the implementation, this check may be done during analysis of the instantiation, or it may be deferred until the design hierarchy is elaborated.

6.5.7.2 Generic map aspects

[Editor note: Paragraph 7]

An actual associated with a formal generic constant in a generic map aspect shall be an expression or the reserved word open. An actual associated with a formal generic type shall be a subtype indication. An actual associated with a formal generic subprogram shall be a name that denotes a subprogram whose profile conforms to that of the formal, or the reserved word open. The actual, if a predefined attribute name that denotes a function, shall be one of the predefined attributes 'IMAGE, 'VALUE, 'POS, 'VAL, 'SUCC, 'PRED, 'LEFTOF, or 'RIGHTOF.

For a formal generic array interface type declaration, if the array index subtype is represented by an implicit formal generic type, then an implicit association element is added that associates the implicit formal with the subtype returned when 'INDEX is applied to the actual of the corresponding array type association element.

For a formal generic array interface type declaration, if the element subtype is represented by an implicit formal generic type, then an implicit association element is added that associates the implicit formal with the subtype returned when 'ELEMENT is applied to the actual of the corresponding array type association element.

For a formal generic access interface type declaration, if the designated subtype is represented by an implicit formal generic type, then an implicit association element is added that associates the implicit formal with the subtype returned when 'DESIGNATED_SUBTYPE is applied to the actual of the corresponding access type association element.

For a formal generic file interface type declaration, if the designated subtype is represented by an implicit formal generic type, then an implicit association element is added that associates the implicit formal with the subtype returned when 'DESIGNATED_SUBTYPE is applied to the actual of the corresponding file type association element.

An actual associated with a formal generic package in a generic map aspect shall be a name that denotes an instance of the uninstantiated package named in the formal generic package declaration, as follows:

[...]

Section 14.3.3.1 General

[Removed operator names. Instead hint to section 6.5.3 for the list of operators.]

Elaboration of a generic map aspect consists of elaborating the generic association list. The generic association list contains an implicit association element for each generic constant that is not explicitly associated with an actual or that is associated with the reserved word open; the actual part of such an implicit association element is the default expression appearing in the declaration of that generic constant. Similarly, the generic association list contains an implicit association element for each generic subprogram that is not explicitly associated with an actual or that is associated with the reserved word open; the actual part of such an implicit association element is determined by the interface subprogram default as described in 6.5.6.2. The generic association list also contains implicit association elements for the predefined equality (=) operator and inequality (/=) operators of each generic type (see 6.5.3); the actual part of such an implicit association element is the name of the predefined equality operator or inequality operator for the base type of the subtype indication in the actual part of the association element corresponding to the generic type.

Annex C - Syntax Summary

anonymous_type_indication ::=             [Moved from LCS 016]
  type is incomplete_type_definition

incomplete_type_definition ::=
    private_incomplete_type_definition
  | scalar_incomplete_type_definition
  | discrete_incomplete_type_definition
  | integer_incomplete_type_definition
  | physical_incomplete_type_definition
  | floating_incomplete_type_definition
  | array_incomplete_type_definition
  | access_incomplete_type_definition
  | file_incomplete_type_definition

incomplete_subtype_indication ::=
    subtype_indication
  | anonymous_type_indication

incomplete_type_mark ::=
    type_mark
  | anonymous_type_indication

private_incomplete_type_definition ::= private

scalar_incomplete_type_definition ::= <>

discrete_incomplete_type_definition ::= ( <> )

integer_incomplete_type_definition ::= range <>

physical_incomplete_type_definition ::= units <>

floating_incomplete_type_definition ::= range <> . <>

array_incomplete_type_definition ::=
  array ( array_index_incomplete_type_list )
    of element_incomplete_subtype_indication
 
array_index_incomplete_type_list ::= 
    array_index_incomplete_type { , array_index_incomplete_type } 

array_index_incomplete_type ::=
    index_subtype_definition
  | index_constraint
  | anonymous_type_indication

access_incomplete_type_definition ::=
  access access_incomplete_subtype_indication

file_incomplete_type_definition ::=
  file of file_incomplete_type_mark
  
interface_type_declaration ::=
  interface_incomplete_type_declaration
    type identifier [ is incomplete_type_definition ]

interface_incomplete_type_declaration ::=
    type identifier

Comments

Version 1

Scalar needs to include any pre-defined operation that is defined for scalars. Currently you are missing to_string. Likewise for anything else that has to_string implemented, it should be indicated as supported.

Why break out physical and floating separately? Why not have a numeric that includes integer, physical, and floating point types? This way if later we introduce fixed point types (like ADA), that too could be supported.

Rather than using syntax for integer, I was wondering if it would work to allow use of universal_integer? Likewise for floating point.

-- Jim Lewis - 2017-01-21

Any thoughts about allowing composition of type classes? I have been thinking about printf. Is there a way we would designate that a type allows any type that supports to_string?

-- Jim Lewis - 2017-01-21

JL: Currently you are missing to_string.

*PL: * Is to_string defined per type class (haven't found it there.) OR per type. Operations per type can not implicitly be visible, because VHDL has no interfaces. If to_string is defined for each type individually, it should be considered to be defined per type class to it can be visible for generic interface types too.

JL: Why break out physical and floating separately? Why not have a numeric that includes integer, physical, and floating point types?

PL: The predefined operations on integer, physical and floating are not the same. Restricting all types to numeric would mean to select the least common set of operations.

JL: Rather than using syntax for integer, I was wondering if it would work to allow use of universal_integer.

PL: The syntax range <> denotes every integer value, thus universal_integer . It's a type class and does not restrict values to be in range of INTEGER.

JL: Is there a way we would designate that a type allows any type that supports to_string?

PL: VHDL and Ada have no guarantees that a type supports certain operations, because operations are not part of a type like in other OO languages. From my point, this is a short coming of both languages and can't be changed. It neither supports interfaces. If VHDL gets interfaces, we can consider such ideas. Moreover, I think it requires types as first class objects.

Example for a type declaration plus operator.

Public Class Train
  Public Property Length as Int32

  Public Sub New(length as Int32)
    me.Length = length
  End Sub

  Operator +(ByVal left As Train, ByVal right As Train)
    Return new Train(left.Length + right.Length)
  End Operator
End Class

-- Patrick Lehmann - 2017-01-21

I am not real thrilled with the notation. Trying to remember <> is scalar. (<>) is discrete. range <> - integer. This does not promote the readability that is prevalent in the rest of the language. Note that for subprograms the notation <> designates a default mapping that uses a subprogram of the same name. It is also used in interface package declarations.

OTOH, what do we do? I don't have a great answer to this. Perhaps abstract packages. Then pre-define packages for each of these. However, we don't have a proposal for abstract packages.

Back to composition, how do I say I want a numeric operation that is permitted to be integer or real? Can we get more commonality between operators supported for integer, physical, and real if we were to move some of the functions from ieee.math_real to std.standard? VHDL-2008 did some clever things with ieee.std_logic_textio to keep the language changes from breaking it (especially a reference of the form ieee.std_logic_textio.hwrite). Similar things could be done for ieee.math_real.

-- Jim Lewis - 2017-01-24

The syntax (<>) is also used by Ada. It is like the definition of the matching type. Here are the equivalences:

-- any type (as currently used)
type T;

-- scalar types (enum, integer, floating, physical)
type T is <>; -- scalar type

-- discrete types (enum, integer)
type enum is (e1, e2);
type T is ( <> )

-- integer types
type int is range 0 to 7;
type T is range <>
-- also used in "array(natural range <>)"

-- floating types
type float is range 0.0 to 1.0;
type T is range <>.<>

-- physical types
type mem is units
  byte;
  kbyte = 1014 byte;
end units
type T is units <>;

-- array types
type arr is array(integer range <>) of bit;
type T is array(integer range <>) of bit;

-- access types
type acc is access string;
type T is access string;

-- file types
type f is file of string;
type T is file of string;

Even with abstract package, there will be no numeric type. A user needs to use a scalar type and pass in the operators by hand.

-- Patrick Lehmann - 2017-01-25

Version 3

Fixed some typos - some of them very often due to the copy-and-paste of errors. Is there any way we can avoid all this repetition in 6.5.3.x? Also, the references to normal xyz types are very informal. Could we maybe avoid the re-iteration of the implicit standard operations inherited from these types altogether? In the end, all this copying and re-stating is only an opportunity for maintenance hazards.

-- Thomas Preusser - 2017-02-08

What if a generic type T declaration is used in an array interface type declarations and in an access interface type declarations, and the formal is not associated in a generic map aspect. Then clause 6.5.7.2 is ambiguous, whether the generic type T is automatically determined:

  • from 'ELEMENT applied to the actual of the corresponding array type association element, or
  • from 'DESIGNATED_SUBTYPE applied to the actual of the corresponding access type association element.

I propose the following solution: remove all the new paragraphs for clause 6.5.7.2 and update all examples.

If this solution is accepted by Patrick or further reviewers, I will edit it in.

-- Martin Zabel - 2017-02-10

Can you give an example? I don't see it.

You can't remove 6.5.7.2! Without it the whole LCS gets a big problem...

-- Patrick Lehmann - 2017-02-10

@PL: Here is the example, I have mentioned above:

package P1 is
  generic (
    type element_type;                                    -- any type
    type index_type is (<>);                              -- a discrete type
    type array_type is array(index_type) of element_type  -- an array type
    type access_type is access element_type               -- an access type
  );
end package;

entity E is
end entity;

architecture A of E is
  package I1 is new P1
    generic map (
      array_type => bit_vector,
      file_type  => line
    );
begin
end architecture;

Then, according to the rules of clause 6.5.7.2, index_type is implicitly associated with bit_vector'INDEX. That works as expected.

But, element_type can be either implicitly associated with:

  • bit_vector'ELEMENT because the "unassociated formal is a generic type and this formal is the element subtype indication of an array type definition", or
  • line'DESIGNATED_SUBTYPE because the " unassociated formal is a generic type and this formal is the designated subtype of an access type definition".

Thus, the additions to clause 6.5.7.2 are ambiguous. Of course, the example is not valid. A check is required, that if a generic type is used within other generic types, then the former generic type must be always associated.

I see no problem in removing the additions to clause 6.5.7.2. These are only syntatic sugar. The package instantiation can still be:

entity E is
end entity;

architecture A of E is
  package I1 is new P1
    generic map (
      element_type => bit,
      index_type => natural,
      array_type => bit_vector,
      file_type  => line         -- an error will be reported here.
    );
begin
end architecture;

-- Martin Zabel - 2017-02-11

Version 5

@MZ: For an formal generic array type, whose index type and element type are not defined, the name of these types are part of the declaration. Hence, either of the following are ok:

    type array_type is array(index_type) of element_type ;
    type FlintStoneArrayType is array (FredIndexType) of WilmaElementType ; 

Hence, if on were to write:

    type array_type is array(index_type) of element_type ;
    type access_type is access element_type ;

And during association, if element_type is not of the same subtype for both, then one would expect an error. We probably do need to specify that this is an error somewhere.

-- Jim Lewis - 2017-03-10

@Jim: Are you talking about my issue reported on 2017-02-10? This was already fixed with version 4 / 5 of this LCS.

-- Martin Zabel - 2017-03-10

The syntax <>, (<>), range <>, units <> and range <>.<> is not human friendly, so, please consider the following:

type typ1 is scalar  ;
type typ2 is discrete;
type typ3 is integer ;
type typ4 is physical;
type typ5 is real    ; -- or floating
Where the identifiers scalar, discrete, integer, physical and real (or floating) would be new keywords, but not reserved words, so the language will be fully backwards compatible.

This is not new to VHDL, an identifier can already have dual behaviour as keyword and identifier as is the case for range in a range_constraint or in a range_attribute_name.

I am not sure of the usefulness of classifying scalar types, in which case would suggest not adding the feature. Can a real world use case be provided for it?

-- Vicente Bergas - 2017-03-11

VB: Where the identifiers scalar, discrete, integer, physical and real (or floating) would be new keywords, but not reserved words, so the language will be fully backwards compatible.
PL: This syntax is not possible. It would require that integer and real become reserved words (keywords), but they are already used as types.

VHDL has no concept of context sensitive reserved words and does strictly distinguish between a lexer and a parser. This means, all "keywords" must be reserved words for the lexer. This would also complicate the already very complex grammar and parser infrastructure.

VB: The syntax <>, (<>), range <>, units <> and range <>.<> is not human friendly
PL: Please see my comment from 25.01.2017. It shows the similarity of the used syntax and how types are currently declared. Moreover this syntax is the same as used by Ada (VHDL is derived from Ada) and is in sync with the proposed VHDL extension called SUAVE.

VB: This is not new to VHDL, an identifier can already have dual behaviour as keyword and identifier as is the case for range in a range_constraint or in a range_attribute_name
PL: This is possible, because attribute names are handled with an exception. You can call them secondary or context dependent keywords.

VB: I am not sure of the usefulness of classifying scalar types, in which case would suggest not adding the feature.
PL: All type classes and all type sub-classes of scalar are covered by this LCS. It's:

  1. A question of orthogonality and
  2. the only possibility to get ordering operations for a type without specifying a more exact type class.

-- Patrick Lehmann - 2017-03-11

In 5.2.1, the production for file_incomplete_type_definition appears to be mangled:

file_incomplete_type_definition ::= file_type_definition
  file of type_mark_or_incomplete_type_definition

It should be one of the following:

file_incomplete_type_definition ::=  file of type_mark_or_incomplete_type_definition
or
file_incomplete_type_definition ::=  file_type_definition

Then in the examples in 6.5.3.10 Interface file type declarations the "of" is missing in some (all?) of the examples:

package P1 is
  generic (
    type designated_subtype;                   -- any type
    type file_type is file designated_subtype  -- an file type
  );

It should be the following right?

    type file_type is file designated_subtype  -- an file type

-- Jim Lewis - 2017-03-20

Version 10

Edit | Attach | Print version | History: r55 | r38 < r37 < r36 < r35 | Backlinks | Raw View | Raw edit | More topic actions...
Topic revision: r1 - 2017-04-02 - 15:47:54 - TWikiGuest
 
Copyright © 2008-2025 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback