VHDL uses the physical type Time to represent the current simulation time. The type is defined as an integer-based representation with constant absolute precision over its entire range. In contrast, a typical analog solver algorithm requires a floating point representation for time, which has a constant relative precision. Most computation is performed with relative times near zero, thus taking advantage of the fact that the absolute precision of a floating point number is extremely high near zero and decreases as absolute value increases.
Synchronization between the solver and the VHDL kernel process (see Mixed-Mode Simulation) requires a common formulation for time that encompasses both requirements.
The table of contents for this paper is available here.
[at LRM 12 -- a new section]
The anonymous predefined floating point type that is called Universal_Time in this standard is the representation for simulation time used by the analog solver.
The following four anonymous functions on Universal_Time are called by their corresponding names in this standard:
function universal_to_physical_time (U: Universal_Time) return Time; function universal_to_real_time(U: Universal_Time) return Real; function physical_to_universal_time(N: Time) return Universal_Time; function real_to_universal_time(R: Real) return Universal_Time;
The bounds and precision of Universal_Time must be chosen and the implementations of the four functions on Universal_Time must be defined so as to have the following characteristics. For U0, U1, U2 of type Universal_Time, N, N0 of type STD.Standard.Time, and R,R0 of type STD.Standard.Real, all non-negative:
R0 = universal_to_real_time(U0+U1+U2) -
universal_to_real_time(U1+U2) > 0,
then
0.0 <= universal_to_real_time(U1+U2) -
universal_to_real_time(U1) - universal_to_real_time(U2) <= R0.
The kernel process variables Tc and Tn are objects of the type Universal_Time. The function denoted STD.Standard.NOW is equivalent to universal_to_physical_time(Tc). The pre-defined quantity denoted ANOW is constrained to the value universal_to_real_time(Tc).
A value of Universal_Time U is said to correspond to or be the universal time corresponding to a value of Time N if physical_to_universal_time(N) = U. The value of STD.Standard.NOW is said to be the current discrete time.
The following changes in the existing LRM text are required. Paragraphs enclosed in brackets set the context and are not part of the definition itself. A reference in the form 12.6-435 is to the IEEE 1076-1993 Language Reference Manual, Section 12.6 at line 435. . The prefix "x" indicates text to be deleted, and the prefix "+" text to be added.
[LRM 12.6.4-633 -- define the initial value of Tc to be of type Universal_Time]
x At the beginning of initialization, the current time, Tc, is assumed to be 0 ns. + At the beginning of initialization, the current time, Tc, is assumed to be 0.0.
[LRM 12.6.4-646 -- clear up the comparison of Tn with TIME'HIGH]
x Simulation is complete when Tn=TIME'HIGH ... + Simulation is complete when Tn corresponds to TIME'HIGH ...
[LRM 12.6.4-655 -- clear up the calculation of Tn in the simulation cycle]
x 1) TIME'HIGH + 1) the value of type Universal_Time corresponding to TIME'HIGH
[LRM 14.2-829 -- correct the comment in package Standard concerning function NOW]
x -- A function that returns the current simulation time, Tc (see 12.6.4): + -- A function that returns universal_to_physical_time (Tc) (see 12.6.4).
[LRM 8.4.1-237 -- use NOW in calculating the time of a transaction when interpreting a signal assignment statement]
x The time component of the transaction is determined by the current time added to the value of the time expression in the waveform element.
+ The time component of the transaction is the greater of 1) the current time, and 2) the universal time corresponding to the sum of the current discrete time and the value of the time expression in the waveform element.
[LRM 8.1-71 -- use the current discrete time as the base for calculating when a "wait for" will wake up]
x The suspended process will resume, at the latest, immediately after the timeout interval has expired.
+ The suspended process will resume, at the latest, at the greater of 1) the current time, and 2) the universal time corresponding to the sum of the current discrete time and the value of the timeout interval.
[LRM 14.1-246 -- Delete two of the three specifications of the result of S'DELAYED(T)]
x A signal equivalent to signal S delayed T units of time. The value of S'DELAYED(t) at time Tn is always equal to the value of S at Tn-t. Specifically:
[LRM 14.1-263 -- Correct the description of the result of S'STABLE(T)]
x A signal that has the value TRUE when an event has not occurred on signal S for T units of time, and the value FALSE otherwise (See 12.6.2).
+ A signal that has the value TRUE when the time of the last event on S is less than the time corresponding to NOW-T, and the value FALSE otherwise (See 12.6.2).
[LRM 14.1-273 -- Correct the description of the result of S'QUIET(T)]
x A signal that has the value TRUE when the signal has been quiet for T units of time, and the value FALSE otherwise (See 12.6.2).
+ A signal that has the value TRUE when the time of the last transaction on S is less than the time corresponding to NOW-T, and the value FALSE otherwise (See 12.6.2).
Type Time is a member of the class of physical types. It seems probable that the physical types were invented to create a generalized language feature that would encompass the requirements for the representation of time. The physical types (with the exception of type Time) have not proved very functional, and are seldom used in practical models.
A physical type declaration defines a collection of "physical units". These are the "primary unit" for the type and any number of "secondary units", each a scaled multiple of a previously defined unit of the same type. Each value of a physical type is constrained to be an integral multiple of the primary unit for the type.
The primary unit of type Time is "fs". The position number corresponding to a (primary or secondary) physical unit is the number of primary units represented by the unit name. We deduce that the position number of "fs" is 1. The position number of a unit of type Time is independent of the chosen "resolution limit". The type of a position number is the predefined type Universal_Integer.
The "resolution limit" of type Time is one of the units of type Time. The resolution limit is "fs" by default, but a different unit can be chosen each time a model is executed. The implementation must choose a representation for type Time that makes it possible to represent a single "resolution limit" unit exactly. We deduce that any integer multiple of the resolution limit unit can also be represented exactly. Values less than the resolution limit must be truncated to zero. The definition allows the implementation to "restrict the precision" of type Time, but does not specify an algorithm. However, the only sensible choice is to truncate non-integer multiples of the resolution limit unit, just as values less than the resolution limit are required to be truncated.
If a resolution limit unit is made to correspond to a low order bit of the stored representation then the available range of time is maximized. The variable resolution limit allows the shift of the radix point to the left, but not to the right; sub-femtosecond resolution in type Time cannot be obtained by adjusting the resolution limit.
The allowed truncation of values of type Time is performed after the calculation of the value of an expression of type Time. Some of the operators in the expression may cause rounding of intermediate results. Thus, both rounding and truncation have a role in computing the final result.
The multiplication and division operators on physical types are defined in terms of computations on the corresponding position numbers.
A physical literal is a physical unit, optionally preceded by an integer or real literal. The physical literal represents that value of the physical type whose position number is the largest integer not greater than the product of the integer or real literal and the position number of the physical unit. This calculation always truncates the low order bits of the product. It is an error if a physical unit smaller than the resolution limit appears anywhere in the design.
The function valued attribute Time'High is defined as the "upper bound" of the type Time. This upper bound cannot be a single, implementation-defined upper limit on the range constraint used in the declaration of type Time in package Standard. A variable upper limit is required if shifting the resolution limit unit is to have the effect of increasing the range of type Time.
The LRM text might be construed to allow the implementation-defined upper limit of the range of type Time to shift so as to take advantage of the increased range provide by a shift in the resolution limit. In that case, it would be consistent to identify the upper bound with the time corresponding to the position number of the upper limit of the range. This creates unit dependency problems, however; the current language would require that every design unit be re-analyzed after a change to package Standard.
A reasonable choice would be to explicitly define the "upper bound" of Time as the fixed upper limit of the range constraint multiplied by the position number of the resolution limit unit.
The impure function NOW returns a value of type Time equal to Tc, as defined in section 12.6.4 on the simulation cycle.
The following tables illustrate the resolution (in seconds) and approximate positive range limit (in appropriate units) for values of type Time, assuming the indicated representations and choice of resolution limit unit. Two additional resolution limit units are illustrated as well that are not currently in the definition of type Time, corresponding to attoseconds and thousanths of attoseconds.
unit res range, 64 bit 2's comp range, 32 bit 2's comp ---- --- ---------------------- ---------------------- hr 3600 100 thousand u.l. 245 thousand years min 60 1,750 univ lifetimes 4 thousand years sec 1E+00 30 universe lifetimes 68 years ms 1E-03 300 million years 25 days us 1E-06 300 thousand years 36 minutes ns 1E-09 300 years 2 seconds ps 1E-12 3 years 2 milliseconds fs 1E-15 3 hours 2 microseconds (at) 1E-18 9 seconds 2 nanoseconds () 1E-21 9 milliseconds 2 picoseconds unit res range,53 bit mag + 1 bit sign ---- --- ----------------------------- hr 3600 102 universe lifetimes min 60 2 universe lifetime sec 1E+00 286 million years ms 1E-03 286 thousand years us 1E-06 286 years ns 1E-09 104 days ps 1E-12 2.5 hours fs 1E-15 9 seconds (at) 1E-18 9 milliseconds () 1E-21 9 microseconds
The 64 bit 2's complement representation is universal among current-day VHDL simulators. 32 bit 2's complement representation fits the minimum required by the definition, but the range limit at the typical time resolutions required by designers is too severe, even with the ability to change the resolution limit. The definition of the minimum range for type Time is an obsolete artifact of the narrow CPU data paths and expensive memory of former days. The 53 bit magnitude plus sign limits are interesting because an IEEE double precision floating point representation has a 52 bit fraction (see below).
The required precision of the exponent and fraction of a value of the floating-point class is defined in the LRM in an indirect way. For the exponent, a range of values that must be representable is defined. For the fraction, a mandatory decimal precision is specified. The result is equivalent to saying that the exponent must have at least 8 and the fraction at least 20 binary digits of precision. An IEEE Std 754 single precision number has an 8 bit exponent and a 23 bit fraction, and so exceeds the requirement.
Every analog simulator we know of uses a double precision representation for unknowns, presumably as a consequence of hard-won experience with the numerical problems presented by typical designs when a lower precision representation is used. We have adopted the same approach. We will require a range of +-1E308, and a decimal precision of 14 digits for all floating-point types in a VHDL 1076.1 implementation. The IEEE Std 754 double precision representation, with 11 bit exponent and 52 bit fraction, just exceeds this requirement.
The representation used for time must be considered separately. If time is represented in seconds as a value of a floating-point type, the resolution is dependent on the absolute value. Here is a table showing the resolution of an IEEE Std 754 double precision number in several ranges bounded by powers of 2 and centered around 1 second:
range low range hi resolution --------- -------- ---------- 0.0009766 0.0019531 2.168E-19 0.0019531 0.0039063 4.337E-19 0.0039063 0.0078125 8.674E-19 0.0078125 0.015625 1.735E-18 0.015625 0.03125 3.469E-18 0.03125 0.0625 6.939E-18 0.0625 0.125 1.388E-17 0.125 0.25 2.776E-17 0.25 0.5 5.551E-17 0.5 1 1.110E-16 1 2 2.220E-16 2 4 4.441E-16 4 8 8.882E-16 8 16 1.776E-15 16 32 3.553E-15 32 64 7.105E-15 64 128 1.421E-14 128 256 2.842E-14 256 512 5.684E-14 512 1024 1.137E-13 1024 2048 2.274E-13
The resolution drops below 1 fs after 8 seconds of simulation time, and so the absolute precision of a 64 bit physical type Time representation is greater than that of the floating point representation after 8 seconds have elapsed. For purposes of comparison, a range of 4.5 seconds at a resolution of 1 fs is achieved with a physical type representation of 52 bits of magnitude, and a range of 9 seconds with 53 bits.
Despite the varying resolution, a double precision floating point representation for time is almost universal in existing analog simulators. The only place absolute time is used in analog simulators is in the abstract representation of source functions (e.g., sin(omega*T) ). All other times are maintained as values relative to the last established ASP. Since steps are closely spaced in time, all times values are close to zero and the effective resolution is quite high.
Those few resolution problems that arise in users' models are the result of ignoring the loss of resolution inherent in products like omega*T as T gets large. But many source functions are periodic, and the problem can be avoided by using, for example, T modulus 1/omega in place of T; that is, effectively resetting T to zero at the beginning of each period. (1/omega must be exactly representable in the chosen floating-point system for this to work perfectly). The minimum resolution is now a function of omega rather than a function of the length of the simulation run. Source functions with long periods tend to change fairly slowly, so a precise value of time is not necessary to get a precise value for the function value. Thus, the unavoidable loss in precision as simulation time increases is often easy to tolerate in practice. It is important to note, however, that those few cases in which the loss or precision does matter produce simulation failures that are difficult to recognize and debug.
Most decimal fractions can only be approximated in a floating point notation that interprets the exponent as a power of two. It follows that since all process resumptions in a VHDL-1076 model are at absolute times represented by decimal fractions of a second, the time of a process resumption cannot be exactly represented by a floating point number regardless of its precision. We conclude that the implementation must pay careful attention to the rounding and truncation errors that will occur if and when physical time values are converted back and forth to floating-point values.
The idea that the current time is a value of physical type Time is never made explicit in the LRM. In this and other respects, time is treated without sufficient formality.
We must assume that all VHDL-1076-1993 events occur at times represented by integer multiples of the resolution limit. This is nowhere explicitly stated. It was probably intended to be a consequence of the way the "current time" is initialized and incremented, but those definitions are defective. The time values Tc and Tn, used in the simulation cycle, are never given a type, although various arithmetic operations are performed using them as operands. The function NOW is defined only by a comment in package standard. The time of execution of a process containing a given statement is variously referred to as "the current time", "the current simulation time" or "the current simulation time, Tc". For the attributes 'STABLE and 'QUIET, the time against which intervals are measured is not defined at all. The function valued attribute T'High is defined as the "upper bound" of the type T. The upper bound of a physical type is not defined. This list is not exhaustive.
A new definition for time must overcome these obstacles while adding the appropriate extensions for VHDL 1076.1. We have adopted what you might call a normative strategy; if the words in the LRM have been interpreted in one way by all the existing implementations and everyone seems to agree that nobody made a mistake, then that interpretation is assumed, even if the words aren't completely clear. In this way, we change as little as possible of the existing text and minimize potential arguments.
The definition calls for a new predefined floating point type, Universal_Time, and four predefined conversion functions (to and from STD.Standard.Time and STD.Standard.Real). Universal_Time is the type of the time variables Tc and Tn used in the description of the simulation cycle (see Mixed-Mode Simulation).
The conversion functions and the range and precision of Universal_Time are defined by a set of constraining rules. Rules 1 and 2 require Universal_Time to exceed in precision both type Time and type Real -- that is, every value of Time and Real can be exactly represented by a unique corresponding value of Universal_Time. Rules 3 and 4 guarantee that Time and Real conversions to Universal_Time have identical slopes and intercepts if the mappings are linear -- that 1.0 is the same as 1 sec, 2.0 is the same as 2 seconds and so on. Rules 5 and 6 guarantee that the mappings are linear within the accuracy of the representation of Real or Time, and that upon conversion a Universal_Time always rounds down to the nearest Real or Time value.
The type name Universal_Real and the names of the conversions functions are not visible so they cannot be referred to directly in the user's model.
The advance of time is marked by the monotonic increase of the value of Tc under the control of the analog solver; see Mixed-Mode Simulation for details on this and other aspects of the treatment of time that are important for understanding the consequences of these definitions. Events caused by the analog solver can occur at arbitrary universal times. In particular, they can occur at times that are not integral multiples of the resolution limit unit ("offset times"). Processes sensitive to the signals Q'Above (see Mixed-Mode Simulation ) can execute at arbitrary universal times. Other processes, not necessarily sensitive to signals Q'Above, may execute in the following series of delta cycles.
The function STD.Standard.NOW (the "current discrete time") is redefined as the value of physical time corresponding to Tc. The type conversion truncates the universal time to the nearest multiple of the resolution limit. All calculations performed in a process that implicitly reference the current time use the current discrete time. Thus, events caused by a non-zero delayed signal assignment, and process resumption consequent to a wait for with non-zero delay always occur at times exactly representable as a value of physical type Time. This preserves the discrete time semantics of a purely digital VHDL description. This should be contrasted with zero delayed assignments and zero delayed process resumption which may occur at offset times.
The new predefined quantity ANOW is implicitly constrained to be the value of type Real corresponding to the Universal_Time Tc, where the Real value is dimensioned in seconds. The type conversion truncates the universal time to the nearest representable value of Real.
Events caused by signal assignments with zero delay ("delta-delayed" assignments) occur at the current simulation time, which may be an offset time. A process that resumes as a consequence of a wait statement with a time-out of zero seconds may also execute at an offset time. A process may therefore execute in one of a series of delta cycles at an offset time even if it is not itself sensitive to a signal Q'Above. In particular, a postponed process may execute in the last cycle of such a series.
Under this new scheme, when NOW is called from a process executing at an offset time it yields only an approximation of the actual time. This means that two processes executing at different actual times my "see" the same value for NOW. In particular, a non-postponed process executing immediately after a postponed process may see the same value for NOW as the preceding postponed process. The implied semantics of postponed processes is unaffected by this fact. It continues to be the case that postponed processes execute only when time is ready to advance, and that processes executing in subsequent cycles execute at future times. The only change is that the advance of time cannot always be detected by examining the values of NOW (or, for that matter, ANOW). This is strictly an extension to the semantics of time since it is only visible in processes executing at offset times.
The time associated with a transaction is of the new type Universal_Time according to the scheme outlined above. The common practice among existing implementations is to use the stored representation of physical type Time to represent the time aspect of a transaction. But by definition the time of every transaction with a time aspect that is different from the current time is an integer multiple of the time represented by one resolution limit unit. Each such value of Universal_Time can be represented as a value of physical type Time for times less than Time'High. Thus, no change in the representation of transactions used by existing simulators is necessary. At worst, the implementor needs to squeeze only one extra state (not one extra bit!) into the stored representation for the time of a transaction over and above the states representing the non-negative physical time values. The additional state would be used to indicate that a transaction is to be scheduled at the current simulation time (which may be an offset time).
The constraints on type Universal_Time allow the use of an IEEE double precision internal representation if Time'High is restricted to Time'pos((2**53)*res_limit). In that case Time'High would be less than the value that would naturally fall out of a 2**N byte integer representation for type Time; for example, 2**63-1 for a 64 bit signed integer. Examination of the tables in section 3.2 will show that the resulting range of time is adequate for most applications even with a resolution limit of fs. Other resolution limit units yield correspondingly greater ranges. Alternatively, a quad precision floating point form could be used for Universal_Time.