44 Connecting to the External World 46 Integrating with Other Applications
Model Builder User's Guide  /  VII Extending Simics  / 

45 Time Synchronization Library

45.1 Introduction

This chapter describes the Time Synchronization Library, a system for synchronising Simics with external programs and exchange information in a deterministic way. It consists of a library that can be linked into the external application exposing a simple programming interface and a standard configuration object on the Simics sidee.

45.2 Overview

A synchronised setup consists of a configuration on the Simics side and a follower process. Each follower needs four objects in Simics:

  1. A cell of its own.
  2. A clock. Just use the standard Simics clock class. The clock approximates the time of the follower for Simics.
  3. A leader object (instance of the leader class). This manages the connection to the follower and keeps it in sync with the clock.
  4. A follower agent object. This is a user-written object that represents the follower in Simics—it can send and receive link messages and use the Simics API. It talks to the follower via the leader.

The clock, leader and agent all belong to the same cell, which is not used for any other simulation objects.

The follower is the user-provided external simulator. It links to libfollower, which contains a simple API to help it staying in sync with Simics and to communicate with the agent.

Figure 28. Follower system overview.

45.3 Time

All interfaces use the same time type, follower_time_t, for specifying points in simulated time. All such times are absolute, and local to the follower. A follower_time_t may be converted to and from picoseconds (as integers). It can also be converted to and from seconds (as a floating point value), although this is not without loss. In Python, a follower_time_t is represented as an integer, counting picoseconds.

The follower's time starts at zero each time it connects to Simics.

45.4 The follower

The follower must keep track of its own simulation time. It must also listen for messages from Simics by calling handle_simics_message(), either periodically or when the descriptor used by libfollower (simics_follower_descriptor()) is readable, using poll() or select().

In handle_simics_message(), any of the supplied functions may be called zero or more times:

The param argument to handle_simics_message() is passed on unchanged to the callbacks above.

When the follower reaches its current time limit, given by proceed_to(), it must go no further. Before waiting for new instructions from Simics, it should report its current time.

The leader must be configured before the follower can connect. The leader can be set to use a specific port number, or (the default) it can pick an available port which can be read out when the configuration is complete.

To send a deterministic message to the agent, the follower calls simics_follower_send_message() with its current time and the message data. This message will be passed to the agent's .accept() method.

To send an asynchronous (non-deterministic) message to the agent, the follower calls simics_follower_send_async_message(). This message will be passed to the agent's .accept_async() method.

45.5 The follower agent

The agent must implement the follower_agent interface. Its .accept() method is called with a message sent from the follower, and the agent can do whatever it wants with it. When that method is sent, the clock is on the same point in time that the follower was on when it sent the message.

Typically, the agent will be connected to links to other parts of the Simics configuration, and send link messages as instructed by the follower.

Any link endpoint connected to the follower must have its indirect_delivery attribute set to true. This causes all link messages from that endpoint to be sent immediately, instead of on time. Instead, in the method receiving a link message, the agent should retrieve the delivery time and a secondary sorting key from the endpoint by calling .delivery_time() and .delivery_skey() in the link_endpoint interface.

It is an error to invoke the functions `.delivery_time()` and `.delivery_skey()` in the `link_endpoint` interface if there is no message in flight.

The leader implements the leader_message interface, and the agent will call the .send() method therein to send back information to the follower. It supplies the delivery time and skey it got from the endpoint when the agent received the message from the link.

For asynchronous (non-deterministic) communication with the follower, the agent implements the .accept_async() method and can send data using the .send_async() method implemented by the leader.

Asynchronous messages are delivered in order and as soon as possible, with no attempts to synchronise them with any simulated time. They should therefore only be used where this is acceptable, such as in configuration, set-up, interactive control, logging, debugging, and so on.

Contrary to .accept(), .accept_async() may be called to deliver a message from the follower even when Simics is standing still.

Any messages, deterministic or non-deterministic, sent with no follower connected are silently dropped.

45.6 Saving and restoring configurations

When a configuration is saved, no information about attached followers is included. The user is responsible for saving and restoring the state of the follower; such information could be managed by the agent, for example.

When a configuration is restored, the leader will attempt to use the same TCP port number, and if it is not available, this will result in an error.

45.7 Code example

To run the provided code example, first start Simics and run the follower-test-with-link.py script. It will print the selected port to the console.

Next, start follower-example:

$ bin/follower-example HOSTNAME PORT

where HOSTNAME is the machine running Simics (probably localhost), and PORT is the selected port.

$ bin/follower-example localhost 12345

The follower will start running as soon as it connects, but no further than allowed by Simics. Type "c" in Simics to go on. The follower will run as fast as it is allowed and send a "hello" message to its agent once every second (see the source code for details).

The sample script follower-test-with-link.py works in the same way, but with a link-attached text console to receive the messages from the follower. Typing in this console will send characters back to the follower.

The client-side code example, follower-example, currently only works on Linux for reasons of code clarity. The libfollower library itself can be used on Windows without restrictions.
44 Connecting to the External World 46 Integrating with Other Applications