Language Change Specification for Long Integers

LCS Number: LCS-2016-026a
Version: 1 {10-Jan-2017}
2 {11-Jan-2017}
3 {13-Jan-2017}
4 {26-Jan-2017}
Date: 26-Jan-2017
Status: Voting
Author: Patrick Lehmann
Email: Main.PatrickLehmann
Source Doc: Long Integers
Summary: Extends the range of integer types values.

Voting Results: Cast your votes here

Yes:

  1. Yann Guidon - 2017-01-11 - ver 2
  2. Martin Zabel - 2017-02-10 - ver 4
  3. Daniel Kho - 2017-01-19 - ver 3
  4. Lieven Lemiengre - 2017-01-27 - ver 4
  5. Hendrik Eeckhaut - 2017-01-27 ver 4
  6. Martin Thompson- 2017-02-17 ver 4
  7. Mark Zwolinski - 2017-02-28 ver 4

No:

  1. Thomas Preusser - 2017-01-13 - ver 3 - see comment below: 64-bit yes, new types no
  2. Farrell Ostler - 2017-01-31 - ver 4 - I align with the viewpoint of ThomasPreusser.
  3. Rob Gaddi - 2017-03-04 - ver 4 - New types will require explicit typecasts all over the place. Prefer 026c
  4. Patrick Lehmann - 2017-03-04 - ver 4 LCS 026c has a lower impact

Abstain:

  1. Brent Hayhoe - 2017-02-16 Version 4 - Abstain due to lack of personal time for review.

Style Notes

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

Reviewing Notes

Version 1:
I don't want to minimize the effort from Kevin Jennings, which he put into this proposal and especially answering all the user comments, but the
discussion seams to be stuck...

This LCS proposes a little step forward with only 64 bit (LONG_INTEGER). It also declares INTEGER as a subtype using only 32 bit. It also drops
compatibility for one's complement machines. A research unveiled that these machines are dead. If one finds a way (and an LCS) that brings us an
512 bit or even 1 MiBit universal_integer, please write it!

I strongly recommend that we continue on this LCS and the matching proposal for VHDL-202x.

Version 2:
Declared predefined array types with an index range of LONG_NATURAL.

Version 3:
Renamed predefined type to INTEGER64, POSITIVE64, NATURAL64, INTEGER32, POSITIVE32, NATURAL32 and created aliases to the old names.

Version 4:
Introduced SYSTEM_INTEGER as a longterm name for a integer of growing size with an guaranteed minimal range.

Details of Language Change

5.2.3.1 General

[Editor note: Paragraph 8]

An implementation may restrict the bounds of the range constraint of integer types other than type universal_integer . However, an implementation
shall allow the declaration of any integer type whose range is wholly contained within the bounds -(2**63)-2147483647 and +(2**63)-1+2147483647
inclusive.

5.2.3.2 Predefined integer types

The only predefined integer type is the type SYSTEM_INTEGER. The range of SYSTEM_INTEGER is implementation dependent, but it is guaranteed
to include the range -(2**63)-2147483647 to +(2**63)-1+2147483647. It is defined with
an ascending range. The declaration of type SYSTEM_INTEGER appears in package STANDARD in Clause 16.

NOTE - The range of SYSTEM_INTEGER in a particular implementation is determinable from the values of its 'LOW and 'HIGH attributes.

5.2.3.3 Predefined integer subtypes [New]

The following integer subtypes are predefined: INTEGER64, NATURAL64, POSITIVE64, INTEGER32, NATURAL32 and POSITIVE32. The listed subtypes
appears in package STANDARD in Clause 16.


subtype INTEGER64  is SYSTEM_INTEGER range -2**63 to 2**63-1;
subtype NATURAL64  is SYSTEM_INTEGER range 0 to INTEGER64'HIGH;
subtype POSITIVE64 is SYSTEM_INTEGER range 1 to INTEGER64'HIGH;

subtype INTEGER32  is SYSTEM_INTEGER range -2**31 to 2**31-1;
subtype NATURAL32  is SYSTEM_INTEGER range 0 to INTEGER32'HIGH;
subtype POSITIVE32 is SYSTEM_INTEGER range 1 to INTEGER32'HIGH;

For compatibility, the following aliases are defined:


alias INTEGER  is INTEGER32;
alias NATURAL  is NATURAL32;
alias POSITIVE is POSITIVE32;

5.2.4.1 General

[Editor note: Paragraph 14]

An implementation may restrict the bounds of the range constraint of a physical type. However, an implementation shall allow the declaration of any
physical type whose range is wholly contained within the bounds -(2**63)-2147483647 and +(2**63)-1+2147483647 inclusive.

5.2.4.2 Predefined physical types

The only predefined physical type is type TIME. The range of TIME is implementation dependent, but it is guaranteed to include the range
-(2**63)-2147483647 to +(2**63)-1+2147483647. It is defined with an ascending range. All specifications of delays and pulse rejection limits shall
be of type TIME. The declaration of type TIME appears in package STANDARD in Clause 16.

5.2.5.2 Predefined floating-point types

The only predefined floating-point type is the type REAL. The range of REAL is host-dependent, but it is guaranteed to be the largest allowed by the
chosen representation. It is defined with an ascending range. The declaration of type REAL appears in package STANDARD in Clause 16.

5.3.2.2 Index constraints and discrete ranges

An index constraint determines the index range for every index of an array type and, thereby, the corresponding array bounds. For a discrete range
used in a constrained array definition and defined by a range, an implicit conversion to the predefined type SYSTEM_INTEGER is assumed if the type of
both bounds (prior to the implicit conversion) is the type universal_integer. Otherwise, the type of the range shall be determined by applying the rules
of 12.5 to the range, considered as a complete context, using the rules that the type shall be discrete and that both bounds shall have the same type.
These rules apply also to a discrete range used in a loop parameter specification (see 10.10) or a generate parameter specification (see 11.8).

5.3.2.3 Predefined array types

The predefined array types are STRING, BOOLEAN_VECTOR, BIT_VECTOR, SYSTEM_INTEGER_VECTOR, INTEGER64_VECTOR, INTEGER32_VECTOR, REAL_VECTOR, and
TIME_VECTOR, defined in package STANDARD in Clause 16. For compatibility, the alias INTEGER_VECTOR is declared.

The values of the predefined type STRING are one-dimensional arrays of the predefined type CHARACTER, indexed by values of the predefined
subtype POSITIVE64:

subtype POSITIVE is INTEGER range 1 to INTEGER'HIGH;
type STRING is array (POSITIVE64 range <>) of CHARACTER;

The values of the predefined types BOOLEAN_VECTOR, BIT_VECTOR, SYSTEM_INTEGER_VECTOR, INTEGER64_VECTOR, INTEGER32_VECTOR, REAL_VECTOR, and
TIME_VECTOR, are one-dimensional arrays of the predefined types BOOLEAN, BIT, SYSTEM_INTEGER, INTEGER64, INTEGER32, REAL, and TIME, respectively, indexed
by values of the predefined subtype NATURAL64:

subtype NATURAL is INTEGER range 0 to INTEGER'HIGH;
type BOOLEAN_VECTOR is array (NATURAL64 range <>) of BOOLEAN;
type BIT_VECTOR is array (NATURAL64 range <>) of BIT;
type SYSTEM_INTEGER_VECTOR is array (NATURAL64 range <>) of SYSTEM_INTEGER;
type INTEGER64_VECTOR is array (NATURAL64 range <>) of INTEGER64;
type INTEGER32_VECTOR is array (NATURAL64 range <>) of INTEGER32;
type REAL_VECTOR is array (NATURAL64 range <>) of REAL;
type TIME_VECTOR is array (NATURAL64 range <>) of TIME;

For compatibility, the following aliases are defined:

alias INTEGER_VECTOR is INTEGER32_VECTOR;

9.2.4 Shift operators

[Editor note: first table]

Operator Operation Left operand type Right operand type Result type
sll Shift left
logical
Any one-dimensional array type whose
element type is BIT or BOOLEAN
SYSTEM_INTEGER Same as left
srl Shift right
logical
Any one-dimensional array type whose
element type is BIT or BOOLEAN
SYSTEM_INTEGER Same as left
sla Shift left
arithmetic
Any one-dimensional array type whose
element type is BIT or BOOLEAN
SYSTEM_INTEGER Same as left
sra Shift right
arithmetic
Any one-dimensional array type whose
element type is BIT or BOOLEAN
SYSTEM_INTEGER Same as left
rol Rotate left
logical
Any one-dimensional array type whose
element type is BIT or BOOLEAN
SYSTEM_INTEGER Same as left
ror Rotate right
logical
Any one-dimensional array type whose
element type is BIT or BOOLEAN
SYSTEM_INTEGER Same as left

9.2.7 Multiplying operators

[Editor note: second table]

Operator Operation Left operand type Right operand type Result type
* Multiplication Any physical type SYSTEM_INTEGER Same as left
    Any physical type REAL Same as left
    SYSTEM_INTEGER Any physical type Same as right
    REAL Any physical type Same as right
/ Division Any physical type SYSTEM_INTEGER Same as left
    Any physical type REAL Same as left
    Any physical type The same type Universal integer
mod Modulus Any physical type Same type Same type
rem Remainder Any physical type Same type Same type

Multiplication of a value P of a physical type Tp by a value I of type SYSTEM_INTEGER is equivalent to the following computation:

Tp'Val( Tp'Pos(P) * I )

Multiplication of a value P of a physical type Tp by a value F of type REAL is equivalent to the following computation:

Tp'Val( SYSTEM_INTEGER( REAL( Tp'Pos(P) ) * F ))

Division of a value P of a physical type Tp by a value I of type SYSTEM_INTEGER is equivalent to the following computation:

Tp'Val( Tp'Pos(P) / I )

[...]

The exponentiating operator ** is predefined for each integer type and for each floating-point type. In either case the right operand,
called the exponent, is of the predefined type SYSTEM_INTEGER.

[Editor note: last table]

Operator Operation Left operand type Right operand type Result type
** Exponentiation Any integer type SYSTEM_INTEGER Same as left
    Any floating-point type SYSTEM_INTEGER Same as left

16.3 Package STANDARD

package STANDARD is
[...]
  type SYSTEM_INTEGER is range implementation_defined;
  -- The predefined operations for this type are as follows:
  -- function "**"(anonymous: universal_integer; anonymous: SYSTEM_INTEGER) return universal_integer;
  -- function "**"(anonymous: universal_real; anonymous: SYSTEM_INTEGER) return universal_real;
  -- function "="(anonymous, anonymous: SYSTEM_INTEGER) return BOOLEAN;
  -- function "/="(anonymous, anonymous: SYSTEM_INTEGER) return BOOLEAN;
  -- function "<"(anonymous, anonymous: SYSTEM_INTEGER) return BOOLEAN;
  -- function "<="(anonymous, anonymous: SYSTEM_INTEGER) return BOOLEAN;
  -- function ">"(anonymous, anonymous: SYSTEM_INTEGER) return BOOLEAN;
  -- function ">="(anonymous, anonymous: SYSTEM_INTEGER) return BOOLEAN;
  -- function "+"(anonymous: SYSTEM_INTEGER) return SYSTEM_INTEGER;
  -- function "-"(anonymous: SYSTEM_INTEGER) return SYSTEM_INTEGER;
  -- function "abs"(anonymous: SYSTEM_INTEGER) return SYSTEM_INTEGER;
  -- function "+"(anonymous, anonymous: SYSTEM_INTEGER) return SYSTEM_INTEGER;
  -- function "-"(anonymous, anonymous: SYSTEM_INTEGER) return SYSTEM_INTEGER;
  -- function "*"(anonymous, anonymous: SYSTEM_INTEGER) return SYSTEM_INTEGER;
  -- function "/"(anonymous, anonymous: SYSTEM_INTEGER) return SYSTEM_INTEGER;
  -- function "mod"(anonymous, anonymous: SYSTEM_INTEGER) return SYSTEM_INTEGER;
  -- function "rem"(anonymous, anonymous: SYSTEM_INTEGER) return SYSTEM_INTEGER;
  -- function "**"(anonymous: SYSTEM_INTEGER; anonymous: SYSTEM_INTEGER) return SYSTEM_INTEGER;
  -- function MINIMUM (L, R: SYSTEM_INTEGER) return SYSTEM_INTEGER;
  -- function MAXIMUM (L, R: SYSTEM_INTEGER) return SYSTEM_INTEGER;
[...]
  -- Predefined type TIME:
  type TIME is range implementation_defined
    units
      fs;             -- femtosecond
      ps  = 1000 fs;  -- picosecond
      ns  = 1000 ps;  -- nanosecond
      us  = 1000 ns;  -- microsecond
      ms  = 1000 us;  -- millisecond
      sec = 1000 ms;  -- second
      min =   60 sec; -- minute
      hr  =   60 min; -- hour
    end units;
  -- The predefined operations for this type are as follows:
  -- function "="(anonymous, anonymous: TIME) return BOOLEAN;
  -- function "/="(anonymous, anonymous: TIME) return BOOLEAN;
  -- function "<"(anonymous, anonymous: TIME) return BOOLEAN;
  -- function "<="(anonymous, anonymous: TIME) return BOOLEAN;
  -- function ">"(anonymous, anonymous: TIME) return BOOLEAN;
  -- function ">="(anonymous, anonymous: TIME) return BOOLEAN;
  -- function "+"(anonymous: TIME) return TIME;
  -- function "- (anonymous: TIME) return TIME;
  -- function "abs"(anonymous: TIME) return TIME;
  -- function "+"(anonymous, anonymous: TIME) return TIME;
  -- function "-"(anonymous, anonymous: TIME) return TIME;
  -- function "*"(anonymous: TIME; anonymous: SYSTEM_INTEGER) return TIME;
  -- function "*"(anonymous: TIME; anonymous: REAL) return TIME;
  -- function "*"(anonymous: SYSTEM_INTEGER; anonymous: TIME) return TIME;
  -- function "*"(anonymous: REAL; anonymous: TIME) return TIME;
  -- function "/"(anonymous: TIME; anonymous: SYSTEM_INTEGER) return TIME;
  -- function "/"(anonymous: TIME; anonymous: REAL) return TIME;
  -- function "/"(anonymous, anonymous: TIME) return universal_integer;
  -- function "mod"(anonymous, anonymous: TIME) return TIME;
  -- function "rem"(anonymous, anonymous: TIME) return TIME;
  -- function MINIMUM (L, R: TIME) return TIME;
  -- function MAXIMUM (L, R: TIME) return TIME;
[...]
  -- Predefined numeric subtypes:
  subtype INTEGER64  is SYSTEM_INTEGER range -2**63 to 2**63-1;
  subtype NATURAL64  is SYSTEM_INTEGER range 0 to INTEGER64'HIGH;
  subtype POSITIVE64 is SYSTEM_INTEGER range 1 to INTEGER64'HIGH;
  
  subtype INTEGER32  is SYSTEM_INTEGER range -2**31 to 2**31-1;
  subtype NATURAL32  is SYSTEM_INTEGER range 0 to INTEGER32'HIGH;
  subtype POSITIVE32 is SYSTEM_INTEGER range 1 to INTEGER32'HIGH;

  alias INTEGER  is INTEGER32;
  alias NATURAL  is NATURAL32;
  alias POSITIVE is POSITIVE32;
[...]
  -- Predefined array types:
  type STRING is array (POSITIVE64 range <>) of CHARACTER;
  -- The predefined operations for these types are as follows:
[...]
 
  type BOOLEAN_VECTOR is array (NATURAL64 range <>) of BOOLEAN;
  -- The predefined operations for this type are as follows:
[...]

  type BIT_VECTOR is array (NATURAL64 range <>) of BIT;
  -- The predefined operations for this type are as follows:
[...]

  type SYSTEM_INTEGER_VECTOR is array (NATURAL64 range <>) of SYSTEM_INTEGER;
  -- The predefined operations for this type are as follows:
  -- function "="(anonymous, anonymous: SYSTEM_INTEGER_VECTOR) return BOOLEAN;
  -- function "/="(anonymous, anonymous: SYSTEM_INTEGER_VECTOR) return BOOLEAN;
  -- function "<"(anonymous, anonymous: SYSTEM_INTEGER_VECTOR) return BOOLEAN;
  -- function "<="(anonymous, anonymous: SYSTEM_INTEGER_VECTOR) return BOOLEAN;
  -- function ">"(anonymous, anonymous: SYSTEM_INTEGER_VECTOR) return BOOLEAN;
  -- function ">="(anonymous, anonymous: SYSTEM_INTEGER_VECTOR) return BOOLEAN;
  -- function "&"(anonymous: SYSTEM_INTEGER_VECTOR; anonymous: SYSTEM_INTEGER_VECTOR) return SYSTEM_INTEGER_VECTOR;
  -- function "&"(anonymous: SYSTEM_INTEGER_VECTOR; anonymous: SYSTEM_INTEGER) return SYSTEM_INTEGER_VECTOR;
  -- function "&"(anonymous: SYSTEM_INTEGER; anonymous: SYSTEM_INTEGER_VECTOR) return SYSTEM_INTEGER_VECTOR;
  -- function "&"(anonymous: SYSTEM_INTEGER; anonymous: SYSTEM_INTEGER) return SYSTEM_INTEGER_VECTOR;
  -- function MINIMUM (L, R: SYSTEM_INTEGER_VECTOR) return SYSTEM_INTEGER_VECTOR;
  -- function MAXIMUM (L, R: SYSTEM_INTEGER_VECTOR) return SYSTEM_INTEGER_VECTOR;
  -- function MINIMUM (L: SYSTEM_INTEGER_VECTOR) return SYSTEM_INTEGER;
  -- function MAXIMUM (L: SYSTEM_INTEGER_VECTOR) return SYSTEM_INTEGER;
 
  type INTEGER64_VECTOR is array (NATURAL64 range <>) of INTEGER64;
  -- The predefined operations for this type are as follows:
  -- function "="(anonymous, anonymous: INTEGER64_VECTOR) return BOOLEAN;
  -- function "/="(anonymous, anonymous: INTEGER64_VECTOR) return BOOLEAN;
  -- function "<"(anonymous, anonymous: INTEGER64_VECTOR) return BOOLEAN;
  -- function "<="(anonymous, anonymous: INTEGER64_VECTOR) return BOOLEAN;
  -- function ">"(anonymous, anonymous: INTEGER64_VECTOR) return BOOLEAN;
  -- function ">="(anonymous, anonymous: INTEGER64_VECTOR) return BOOLEAN;
  -- function "&"(anonymous: INTEGER64_VECTOR; anonymous: INTEGER64_VECTOR) return INTEGER64_VECTOR;
  -- function "&"(anonymous: INTEGER64_VECTOR; anonymous: INTEGER64) return INTEGER64_VECTOR;
  -- function "&"(anonymous: INTEGER64; anonymous: INTEGER64_VECTOR) return INTEGER64_VECTOR;
  -- function "&"(anonymous: INTEGER64; anonymous: INTEGER64) return INTEGER64_VECTOR;
  -- function MINIMUM (L, R: INTEGER64_VECTOR) return INTEGER64_VECTOR;
  -- function MAXIMUM (L, R: INTEGER64_VECTOR) return INTEGER64_VECTOR;
  -- function MINIMUM (L: INTEGER64_VECTOR) return INTEGER64;
  -- function MAXIMUM (L: INTEGER64_VECTOR) return INTEGER64;
 
  type INTEGER32_VECTOR is array (NATURAL64 range <>) of INTEGER32;
  -- The predefined operations for this type are as follows:
  -- function "="(anonymous, anonymous: INTEGER32_VECTOR) return BOOLEAN;
  -- function "/="(anonymous, anonymous: INTEGER32_VECTOR) return BOOLEAN;
  -- function "<"(anonymous, anonymous: INTEGER32_VECTOR) return BOOLEAN;
  -- function "<="(anonymous, anonymous: INTEGER32_VECTOR) return BOOLEAN;
  -- function ">"(anonymous, anonymous: INTEGER32_VECTOR) return BOOLEAN;
  -- function ">="(anonymous, anonymous: INTEGER32_VECTOR) return BOOLEAN;
  -- function "&"(anonymous: INTEGER32_VECTOR; anonymous: INTEGER32_VECTOR) return INTEGER32_VECTOR;
  -- function "&"(anonymous: INTEGER32_VECTOR; anonymous: INTEGER32) return INTEGER32_VECTOR;
  -- function "&"(anonymous: INTEGER32; anonymous: INTEGER32_VECTOR) return INTEGER32_VECTOR;
  -- function "&"(anonymous: INTEGER32; anonymous: INTEGER32) return INTEGER32_VECTOR;
  -- function MINIMUM (L, R: INTEGER32_VECTOR) return INTEGER32_VECTOR;
  -- function MAXIMUM (L, R: INTEGER32_VECTOR) return INTEGER32_VECTOR;
  -- function MINIMUM (L: INTEGER32_VECTOR) return INTEGER32;
  -- function MAXIMUM (L: INTEGER32_VECTOR) return INTEGER32;

  alias INTEGER_VECTOR is INTEGER32_VECTOR;
[...]
 
  type REAL_VECTOR is array (NATURAL64 range <>) of REAL;
  -- The predefined operations for this type are as follows:
[...]
  
  type TIME_VECTOR is array (NATURAL64 range <>) of TIME;
  -- The predefined operations for this type are as follows:
[...]

  -- Predefined TO_STRING operations on scalar types
  -- function TO_STRING (VALUE: BOOLEAN) return STRING;
  -- function TO_STRING (VALUE: BIT) return STRING;
  -- function TO_STRING (VALUE: CHARACTER) return STRING;
  -- function TO_STRING (VALUE: SEVERITY_LEVEL) return STRING;
  -- function TO_STRING (VALUE: universal_integer) return STRING;
  -- function TO_STRING (VALUE: universal_real) return STRING;
  -- function TO_STRING (VALUE: SYSTEM_INTEGER) return STRING;
  -- function TO_STRING (VALUE: REAL) return STRING;
  -- function TO_STRING (VALUE: TIME) return STRING;
  -- function TO_STRING (VALUE: FILE_OPEN_KIND) return STRING;
  -- function TO_STRING (VALUE: FILE_OPEN_STATUS) return STRING;
  -- Predefined overloaded TO_STRING operations
  -- function TO_STRING (VALUE: REAL; DIGITS: NATURAL64) return STRING;
  -- function TO_STRING (VALUE: REAL; FORMAT: STRING) return STRING;
  -- function TO_STRING (VALUE: TIME; UNIT: TIME) return STRING;

Annex D (Potentially nonportable constructs)

The use of the following constructs may lead to nonportable VHDL descriptions:
  • Resolution functions that do not treat all inputs symmetrically
  • The comparison of floating-point values
  • Events on floating-point-valued signals
  • The use of explicit type conversion to convert floating-point values to integer values
  • Any value that does not fall within the minimum guaranteed range for the type
  • The use of architectures and subprogram bodies implemented via the foreign language interface (the 'FOREIGN attribute)
  • Processes that communicate via file I/O, including TEXTIO
  • Impure functions
  • Linkage ports
  • Ports and generics in the root of a design hierarchy
  • Use of a time resolution greater than 1 fs
  • Shared variables
  • Procedure calls passing a single object of an array or record type to multiple formals where at least one of the formals is of mode out or inout
  • Models that depend on a particular format of T'IMAGE
  • Declarations of integer or physical types that have a secondary unit whose position number is outside of the range -(2**31-1) to 2**31-1
  • The predefined attributes 'INSTANCE_NAME or 'PATH_NAME, if the behavior of the model is dependent on the values returned by the attributes
  • Use of a conversion specifier F, a, or A in the value for the FORMAT parameter of a call to the predefined function TO_STRING

Comments

Most of the objections to LCS-2016-026 have to do with the '512 bits' and a smaller number grousing over the lack of providing any subtype that map back to VHDL-87 integers. In that vein, changing LCS 26 to '64 bits' would fairly simply address the majority of the concerns. If that is acceptable then it provides precedence down the road for a similarly minor edit when 128 bit integer math becomes the norm and there is pressure to expand integers yet again.

In addition to 64 bits, LCS 26a addresses the perceived need for a 32 bit integer subtype, but does so by making a lot more edits and would be harder to scale that to the next larger size. Now that there would be INTEGER and LONG_INTEGER, what comes next? REALLY_LONG_INTEGER when VHDL gets to 128 bit integers? REALLY_REALLY_LONG_INTEGER when VHDL gets to 256 bits?

The current LRM provides no guarantee about the maximum integer size so there is no fundamental requirement to provide a 32 bit integer subtype and create LONG_INTEGER type. That is only a perceived need (that might also be accurate).

I'm not trying to lobby here for or against LCS 26 versus LCS 26a, just providing a discussion topic for comparing the two LCS on some future Thursday call.

-- Kevin Jennings - 2017-01-11

I was also thinking about other names like IMPL_INTEGER for implementation integer, UNI_INTEGER or VHDL_INTEGER ... Such an integer could grow in each revision.

Personally, I wouldn't be so friendly with the EDA industry (vendor and users). If they rely on false code, then they might get broken code when using a new VHDL revision. But language designers are still willing to satisfy their audience at every cost.

Creating a subtype INTEGER, catches every design which falsely relies on fixed 32-bit integers, by using e.g. 'LEFT or hoping for overflow arithmetic in the tool.

@Kevin If you really want to make 512 bit or even more possible, then we need a "derived types LCS" and especially derived integers. I don't know if I have enough time to write such a big text, because I still need to write the Spaceship LCS ...

-- Patrick Lehmann - 2017-01-11

PL: Creating a subtype INTEGER, catches every design which falsely relies on fixed 32-bit integers, by using e.g. 'LEFT or hoping for overflow arithmetic in the tool.

MZ: The new INTEGER (backed up by a >= 64-bit implementation) will not overflow as the old INTEGER which is often backed-up by a 32-bit implementation. An out-of-bounds exception should be happen now.

Having a subtype INTEGER with range -2**31 to 2**31-1 only catches designs which falsely rely on the values of INTEGER'LEFT, 'RIGHT, and so on.

Another (major) benefit of a such a subtype INTEGER is that the simulator can (!) keep the memory footprint the same for existing designs and finally also the simulation performance.

-- Martin Zabel - 2017-01-12

MZ: Another (major) benefit of a such a subtype INTEGER is that the simulator can (!) keep the memory footprint the same for existing designs and finally also the simulation performance

KJ: Doesn't that assumes that all intermediate calculations do not overflow 64 bit? When I went looking, I didn't see anything specifying what to do if an intermediate calculation overflows so an implementation today might use 64 bit operations (or at least something larger than 32 bits) in order to try to guarantee correct 32 bit results. If they now have to guarantee correct 64 bit results and they applied a similar strategy then 64 bit low level operations wouldn't cut it. Either that or it assumes that the operations to use are determined based on the subtype ranges.

-- Kevin Jennings - 2017-01-12

KJ: When I went looking, I didn't see anything specifying what to do if an intermediate calculation overflows so an implementation today might use 64 bit operations (or at least something larger than 32 bits) in order to try to guarantee correct 32 bit results.

MZ: My interpretation of the LRM is: one has to use an arbitrary precision during calculation of an integer expression, and then check the range during assignment. This cannot be even achieved by using a 64-bit arithmetic for a 32-bit INTEGER type as you already demonstrated by your exponentiation example in the e-mail discussion between you and Tristan. Another example is n*n*n/n/n where n is INTEGER'high.

Unfortunately the current situation is even worse: I have tested 4 simulators: G, M, I, X. Given a variable n of type INTEGER, all of them use 32-bit modulo arithmetic for the expression n : n+1=, thus the result is -2**31 (negative!) if n was 2**31-1. Only I and X detect the overflow if it is visible from static elaboration. When requesting 64-bit for universal integer, the intermediate result would be 2**31 (positive) and the range check during the assignment to the INTEGER n will fail as expected. Nevertheless, the simulator can still use only 4 bytes to store n in memory, thus the memory footprint for the current state of the model will not grow.

Addendum: I do not expect that simulators will ever use arbitrary precision for integer expressions. I think, if the vendors are lazy then they will use 64-bit arithmetic and 8 byte storage for any integer type. If they optimize a bit, then they will use 64-bit for arithmetic and 8 byte storage for LONG_INTEGER, but only 4 byte storage for INTEGER. Having a small memory footprint (cache utilization) is important for simulation speed.

-- Martin Zabel - 2017-01-12

After the renaming to INTEGER64, one might intuitively expect that the size is exactly 64 bits as is the case for the int64_t in C or C++ for example.

Thus, I would argue to change Section 5.2.3.2 so that INTEGER64 is defined as exactly the range -2**63 to 2**63-1.

-- Martin Zabel - 2017-01-13

No technical objections. However, I do not like the approach of fuzzing things up and introduce (INTEGER|NATURAL|POSITIVE)(32|64) or whatever. Couldn't we just require implementors of the new language revision to have INTEGER support, at least, the range of signed 64-bit values: no new types, only new bounds.

-- Thomas Preusser - 2017-01-13

What is the impact if we alias INTEGER to INTEGER64 instead of INTEGER32, and do the same for the other 64-bit types?

-- Daniel Kho - 2017-01-19

I am fine with having INTEGER64 and INTEGER32, with INTEGER aliasing to either of these. In future revisions, INTEGER could alias UNIVERSAL_INTEGER which could be a more generic and complete implementation of the integer type.

-- Daniel Kho - 2017-01-19

@Danielkho: If we alias INTEGER to INTEGER64 instead of INTEGER32, then the memory footprint will increase because now each INTEGER has to be stored in 8 bytes instead of 4 bytes. Having a small memory footprint (cache utilization) is important for simulation speed.

The intention of Patrick was to "catch every design which falsely relies on fixed 32-bit integers, by using e.g. 'LEFT", see his comment dated from 2017-01-11.

-- Martin Zabel - 2017-01-21

I feel that no code should exist that relies on the range of VHDL's INTEGER type being exactly -2**31 to 2**31+1. Wherever this was needed, the user could have declareded, e.g., "type integer_32 is integer range -2**31 to 2**31-1". Users who failed to handle this properly can make the correction going forward.

VHDL users have always known that the range of integer could be more than 32 bits. In some ways it is surprising that no vendor has supported 64 bits (or at least, say, -2**31 to 2**32-1) for a competitive advantage.

-- Farrell Ostler - 2017-01-31

RG: New types will require explicit typecasts all over the place.
*PL: I think you mean LCS 026b not this (LCS 026a).

-- Patrick Lehmann - 2017-03-04

Topic revision: r29 - 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