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:

  1. Declare constant for current date and time, and assign based on single atomic call to function that provides system date and time
  2. 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:

  1. Declare constant for project start date and time, and assign with value
  2. Declare constant for current date and time, and assign based on single atomic call to function that provides system date and time
  3. Declare constant for relative date and time, and assign with difference from project start to current date and time based on above constants
  4. 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:

  1. Declare variable with start date and time, and assign based on single atomic call to function that provides system date and time
  2. Execute the code to be measured
  3. Declare variable with stop date and time, and assign based on single atomic call to function that provides system date and time
  4. Declare variable with delta date and time, and assign with (stop - start) date and time
  5. 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

Topic revision: r15 - 2020-02-17 - 15:34:52 - JimLewis
 
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