Previous - Up - Next

15.1   Time client library

The client library provides non-threaded C primitives for all features of the time server protocol. Using the time client library, interfacing to the time server is as easy as a C function call.

The following primitives exists:

    typedef enum {
            Simtime_No_Error,
            Simtime_Socket_Error,         // errno contains last error
            Simtime_Timeout,              // global timeout (as specified in
                                          // simtime_connect)
            Simtime_Receive_Buffer_Full,  // the received message did not fit
                                          // in the buffer. It's probably a bug
                                          // in the time client library if it
                                          // happens
            Simtime_Parse_Error           // received message could not be
                                          // parsed
    } simtime_error_t;


    simtime_error_t simtime_query_time(simtime_context_t *ctx,
                                       double *time);

    simtime_error_t simtime_sleep(simtime_context_t *ctx,
                                  double seconds,
                                  double *time);

    simtime_error_t simtime_periodic_ping(simtime_context_t *ctx,
                                          double interval,
                                          double how_long,
                                          simtime_callback_t cb,
                                          void *user_data);

simtime_query_time will return the current virtual time. It is not expected to block very long (the time server will respond immediately when it receives the query).

Although tempting, simtime_query_time should not be used in a tight polling loop, as it will degrade Simics performance quite noticeable.

Depending on what the timing code looks like, one of the other primitives should be used instead.

The simtime_sleep function will block for a specified number of virtual seconds. Note that this function will never return if Simics is not simulating, unless a global timeout is specified (see the simtime_connect function). This is obviously because the virtual time is not progressing when the simulation is not running.

If the timeout is not known beforehand, it may not be possible to use simtime_sleep. In this case, simtime_periodic_ping might be the solution. It will cause Simics to send periodic pings to the client. The interval between each ping is in real seconds, i.e. host time, not Simics time. It is also possible to specify a duration, also in real seconds, after which Simics will stop sending ping messages. If duration is negative or zero, Simics will continue to send ping messages until told to stop (non-zero return value from ping message callback function).

For every ping message, the callback function cb will be called:

    typedef int (*simtime_callback_t)(void *data,
                                      simtime_context_t *ctx,
                                      int seq_no, double time);

seq_no contains the sequence number of the received ping message and time contains the current virtual time.

If the callback function returns a value other than zero, the periodic pings will be aborted, even though duration real seconds has not yet passed.

Note that simtime_periodic_ping will not return until duration real seconds has passed, or until the callback function returns a non-zero value. Also note that no simtime API calls should be made from the callback.

Before any of the above primitives can be used, a connection to the time server has to be established:

    simtime_context_t *simtime_connect(const char *host,
                                       int port,
                                       int global_timeout);
    void simtime_disconnect(simtime_context_t *ctx);

The time client will connect to a time server on host at port port. If global_timeout is larger than zero, all calls to simtime will timeout after global_timeout real seconds. This is useful to detect, for example, a crashed Simics session. But note that a call to e.g. simtime_sleep may take very long real time, depending on how fast Simics is simulating (and, of course, how long the sleep time is).

To disconnect from the time server, call the function simtime_disconnect.

If the client is threaded, care must be taken to not make more than one API call at a time. The time client library is not designed to handle simultanious calls.

Previous - Up - Next