Date and Time
Proposal Editing Information
Requirement Summary
Information about current date and time should be available in VHDL code through system function call.
Conversion of the date and time information to often used formats should be possible.
It must be feasible for the designer to make functions that format the system date and time to alternative representations that are used in the design.
It must also be feasible for the designer to make functions that determine time difference between two provided system data and times, or between current system date and time and a fixed date and time that is hard coded in the design.
Motivation for Requirement
Synthesis
Complex systems with CPU interface do typically contain some registers where information about the design version can be read by the CPU. Amongst such registers are typically information about the synthesis date and time of the design. Designer request can also be seen for such features in
Stack Overflow: Compile Date and Time in FPGA
.
Simulation
Random Seed Initialization.
Simulation performance is relevant for lengthy simulations, and it is sometimes required to optimize the VHDL code used in the simulation in to improve the simulation performance and thereby shorten the simulation time. The system time (wall time) is relevant to measure the performance, and access to system time in VHDL will make it possible to directly measure for example cycles per second for different VHDL constructions.
Use Model
Absolut Date and Time for read in CPU Register
Steps to make absolute (ordinary calendar date and time) date and time in a CPU register:
- Declare constant for current date and time, and assign based on single atomic call to function that provides system date and time
- Convert constant value to fields with various data and time information in std_logic_vector type
- Absolute date and time representation is used, giving for example year 2013
- Time zone information may be applied
Relative Date and Time for read in CPU Register
Steps to make relative (based on project start time) date and time in a CPU register:
- Declare constant for project start date and time, and assign with value
- Declare constant for current date and time, and assign based on single atomic call to function that provides system date and time
- Declare constant for relative date and time, and assign with difference from project start to current date and time based on above constants
- Convert constant with relative date and time to fields with various data and time information in std_logic_vector type
- Relative date and time representation is used, giving for example year 0000
- Time zone information may be applied
Performance Measurement in Simulation
Steps to show simulation performance:
- Declare variable with start date and time, and assign based on single atomic call to function that provides system date and time
- Execute the code to be measured
- Declare variable with stop date and time, and assign based on single atomic call to function that provides system date and time
- Declare variable with delta date and time, and assign with (stop - start) date and time
- Report to delta time to user
Proposal
Some of the functions proposed below are not covered in use models above (mainly these for ISO 8601 string representation of date and time), but the use will be very similar, so it appears reasonable that these are included.
Add to package std.env.
-- Return system time as seconds since UNIX epoch (1970-01-01 00:00:00 Z)
-- including fraction of second as system allows, but not counting leap
-- seconds
impure function system_time_time return real;
-- Convert system time to record structure with integer,
-- based on 24 * 60 * 60 seconds per day
type system_time_int_t is record
year : integer; -- 0 <= year <= 4095
month : integer; -- 1 <= month <= 12
day : integer; -- 1 <= day <= number of days in the given month and year
day_of_year : integer; -- 0 <= day_of_year < number of days in the given year
hour_pm : boolean; -- FALSE: AM, TRUE: PM
hour_12 : integer; -- 1 <= hour_12 <= 12
hour : integer; -- 0 <= hour < 24
minute : integer; -- 0 <= minute < 60
second : integer; -- 0 <= second < 60
microsecond : integer; -- 0 <= microsecond < 1000000
end record;
impure function system_time_int(t : real := -1.0; -- Time to represent (before timezone adjust); < 0.0: Use system_time_time
timezone : real := 0.0; -- Add 3600 * timezone to t before representation
relative : boolean := FALSE) -- FALSE: Show as after UNIX epoch, TRUE: Show as after year 0000 with no leap year
return system_time_int_t;
-- Convert system time to record structure with std_logic_vector
-- Range of values as in system_time_int_t
type system_time_slv_t is record
year : std_logic_vector(11 downto 0);
month : std_logic_vector( 3 downto 0);
day : std_logic_vector( 4 downto 0);
day_of_year : std_logic_vector( 8 downto 0);
hour_pm : std_logic;
hour_12 : std_logic_vector( 3 downto 0);
hour : std_logic_vector( 4 downto 0);
minute : std_logic_vector( 5 downto 0);
second : std_logic_vector( 5 downto 0);
microsecond : std_logic_vector(19 downto 0);
end record;
impure function system_time_slv(t : real := -1.0; timezone : real := 0.0; relative : boolean := FALSE) return system_time_slv_t; -- Arguments as for system_time_int
impure function system_time_slv(t_int : system_time_int_t) return system_time_slv_t; -- Arguments as for system_time_int
-- Convert system time to string in ISO 8601 like format with micro seconds,
-- for example "2013-01-12_23:34:45.567890".
subtype system_time_iso_t is string(1 to 26);
impure function system_time_iso(t : real := -1.0; timezone : real := 0.0; relative : boolean := FALSE) return system_time_iso_t; -- Arguments as for system_time_int
impure function system_time_iso(t_int : system_time_int_t) return system_time_iso_t; -- Arguments as for system_time_int
-- Convert integers with system time to real
impure function system_time_make(year : integer := 0; -- Range as for system_time_int_t
month : integer := 1; -- --||--
day : integer := 1; -- --||--
hour : integer := 0; -- --||--
minute : integer := 0; -- --||--
second : integer := 0; -- --||--
microsecond : integer := 0; -- --||--
timezone : real := 0.0; -- Subtract 3600 * timezone after conversion of t_int
relative : boolean := FALSE) -- FALSE: Shown as after UNIX epoch, TRUE: Shown as after year 0000 with no leap year
return real;
Examples of Use
Code examples based on use models.
Absolut Date and Time for read in CPU Register
-- Declare constant for current date and time, and assign based on single
-- atomic call to function that provides system date and time
constant EG_ABSREG_TIME : real := system_time_time;
-- Convert constant value to fields with various data and time information in
-- std_logic_vector type
constant EG_ABSREG_SLV : system_time_slv_t := system_time_slv(EG_ABSREG_TIME, +1.0); -- Timezone UTC+1, and absolute rep.
-- Signal with hour
signal eg_absreg_hour : std_logic_vector(EG_ABSREG_SLV.hour'range);
begin
-- Assign signal with hour
eg_absreg_hour <= EG_ABSREG_SLV.hour;
Relative Date and Time for read in CPU Register
-- Declare constant for project start date and time, and assign with value
constant EG_RELREG_PROJ : real := system_time_make(year => 2013,
month => 3,
day => 1); -- Time 2013-03-01, timezone UTC, and absolute rep.
-- Declare constant for current date and time, and assign based on single
-- atomic call to function that provides system date and time
constant EG_RELREG_TIME : real := system_time_time;
-- Declare constant for relative date and time, and assign with difference
-- from project start to current date and time based on above constants
constant EG_RELREG_DIFF : real := EG_RELREG_TIME - EG_RELREG_PROJ;
-- Convert constant with relative date and time to fields with various data
-- and time information in std_logic_vector type
constant EG_RELREG_SLV : system_time_slv_t := system_time_slv(EG_RELREG_DIFF, -- Time from project start
timezone => -8.0, -- Timezone UTC-8 (PST)
relative => TRUE); -- Relative reprensetation
-- Signal with hour
signal eg_relreg_year : std_logic_vector(EG_RELREG_SLV.year'range);
begin
-- Assign signal with year
eg_relreg_year <= EG_RELREG_SLV.year;
Performance Measurement in Simulation
process is
variable dat_begin_v : real; -- Date and time at begin of code
variable dat_end_v : real; -- Date and time at end of code
variable dat_diff_v : real; -- Seconds in difference
begin
dat_begin_v := system_time_time; -- Assign based on single atomic call to function that provides system date and time
wait for 100 us; -- Execute the code to be measured
dat_end_v := system_time_time; -- Assign based on single atomic call to function that provides system date and time
dat_diff_v := dat_end_v - dat_begin_v; -- Assign with (stop - start) date and time
report "Time to run code: " & real'image(dat_diff_v); -- Report to delta time to user
end process;
Questions
--
MortenZilmer - 2013-11-30: Should system_time_int_t use natural type instead of integer, since all values are >= 0 ?
--
MortenZilmer - 2013-11-30: Should system_time_int_t integer types have range, e.g. 0 to 59 ?
--
MortenZilmer - 2013-11-30: system_time_iso: What delimiter to use between date and time; "T" is ISO 8601 standard, but is hard to read, so maybe use " " (space) or "_" (underscore) instead ?
--
MortenZilmer - 2013-11-30: No string formatting support, except ISO 8601 similar string; is this acceptable ?
--
MortenZilmer - 2013-11-30: What names to use for different types and functions; current names are just used as placeholders ?
General Comments
The concept of time, used for both time in day and for specific date, is complex, as can be seen from the numerous Internet pages discussing different time systems like TAI, UTC, GPS, etc.
The suggested handling of system time must be easy to implement in order to get support in the tools. The suggestion above should possible to implement based on C library time functions, and should therefore be relatively easy to implement in the tools.
The suggestion also provides time of day and date in the same call, to ensure that the set of date and time of day is consistent. Otherwise, if separate date and time calls are provided, then some amount of system time may pass between the call, whereby the date and time may returned for different days, resulting in an incorrect set of date and time values.
The basic internal date and time type is a real with seconds after UNIX epoch. It is thereby easy to do arithmetic on the time information, and for example determine time difference in seconds between two value.
Time zone support is provided when the UNIX epoch time is converted for representation, and the time zone is simply given as an hour offset from UTC. It is thereby straight forward to represent the same date and time in different time zones. Daylight saving can be controlled through use of the time zone option.
Format of system_time_int_t is inspired by Python
datetime.datetime class
.
I'd make use of this in synthesis, where I like to bake a epoch timestamp into a read-only register somewhere in the design as a unique ID of a particular build. Right now I have to fudge that in with some ugly Tcl scripts. My only concern about the extended versions, with the conversion functions to records, is that I can't think of anywhere else in the standard library where the language is taking advantage of records; it's not like a C (<time.h> struct tm) or a Python (datetime.datetime) where record/struct/class based APIs make up so many interfaces. Not saying that's inherently bad, but it's definitely a break from tradition. --
RobGaddi - 2015-04-22
Supporters
--
MartinThompson - 2012-09-14
--
JakkoVerhallen - 2012-09-14
--
BrentHahoe - 2012-10-08
--
MatthiasAlles - 2013-02-14
--
TrondDanielsen - 2013-11-20
--
MortenZilmer - 2013-11-20
--
RobGaddi - 2015-04-22
--
PatrickLehmann - 2016-02-19
Add your signature here to indicate your support for the proposal