1.1 Programming Concepts 1.3 API usage rules
API Reference Manual  /  1 Introduction  / 

1.2 Simics API Information

This chapter describes the organization of the Simics API, and how to use it. It also shows how it interacts with system, Device, Simulator, Processor, and Link Library APIs.

1.2.1 The Simics API

Simics provides a number of unique APIs designed to allow the integration of new modules with the Simics family of products.

The Simics API is partitioned into three major parts, and an additional three groups of interfaces. There is one header file to include for each part of the Simics API, while the interfaces are split over several independent header files.

With a partitioned API the part needed by models can be kept as small and simple as possible, and the boundary between models and the simulator infrastructure is more clearly defined. A small Device API makes device modeling easier and reduces the risk of writing code with the potential to break determinism, reverse execution, or multi-threading.

For a model representing a piece of hardware, you should only need to use the Device API together with the necessary model-to-model and model-to-simulator interfaces.

To find out how to get access to a particular API function or data type, you can use the api-help CLI command. This will tell you which header file, if any, to include (in either DML or C/C++).

1.2.1.1 Device API

The basic functionality of the Simics API and the only part available to device models.
The Device API is always accessible from DML; from C/C++ it is available using:

C/C++: #include <simics/device-api.h>

1.2.1.2 Model-to-Model Interfaces

Interfaces between models typically represent standard hardware interfaces such as PCI, IC, Ethernet and interrupt lines. These interfaces are included in the Device API.


Accessible from DML and C/C++ using:

DML:   import "simics/devs/interface.dml";
C/C++: #include <simics/devs/interface.h>

where interface should be replaced with the actual header file name.

To find out which header file the foo interface is defined in, you can use the Simics CLI command api-help foo_interface_t.

1.2.1.3 Model-to-Simulator Interfaces

These interfaces fall into two categories:

Interfaces included in this list are part of the Device API.


They are accessed from DML and C/C++ using:

DML:   import "simics/model-iface/interface.dml";
C/C++: #include <simics/model-iface/interface.h>

where interface should be replaced with the actual header file name.

To find out which header file the foo interface is defined in, you can use the Simics CLI command api-help foo_interface_t.

1.2.1.4 Simulator API

The Simulator API contains the complete Simics API, including parts that are not available to models. This API may be used by simulator extensions.


Accessible from DML and C/C++ using:

DML:   import "simics/simulator-api.dml";
C/C++: #include <simics/simulator-api.h>

1.2.1.5 Simulator-to-Simulator Interfaces

Interfaces that are only used between simulator extensions and that should not be used by any model are collected into this group. These interfaces are part of the Simulator API.


Accessible from DML and C/C++ using:

DML:   import "simics/simulator-iface/interface.dml";
C/C++: #include <simics/simulator-iface/interface.h>

where interface should be replaced with the actual header file name.

To find out which header file the foo interface is defined in, you can use the Simics CLI command api-help foo_interface_t.

1.2.1.6 Processor API

The Processor API extends the Device API with functions needed when modeling processors in Simics.
Accessible from DML and C/C++ using:

DML:   import "simics/processor-api.dml";
C/C++: #include <simics/processor-api.h>

1.2.1.7 Link Library API

The Link Library API extends device modeling capabilities with Simics by allowing users to write Simics link models.
Accessible from DML and C/C++ using:

DML:   import "simics/devs/liblink.dml";
C/C++: #include <simics/devs/liblink.h>

1.2.1.8 Python API

Simics users may utilize Python to interact with the Simics API. For example, Python can be used to write or run Simics commands. Python may also be used to write components and modules for Simics.

The API is accessible from Python by importing the respective modules listed in chapter 10.

Python can also be used directly from the Simics command line and in set-up scripts.

1.2.2 API Version

Device makefiles have a variable called SIMICS_API, which specifies which version of the Simics API the model uses. It is a good idea to set SIMICS_API to the current Simics API. This will cause compile errors for uses of deprecated features.

SIMICS_API := 6

Python modules do not have a SIMICS_API flag to force compiler checking and thus need to be checked manually. Command line options can be passed to Simics to ensure any runtime usage of deprecated features trigger errors.

1.2.3 System Calls and Signals

On Linux, Simics will register its built-in signal handlers to make system calls restartable after the signal has been handled (cf. the SA_RESTART flag in the sigaction(2) man page).

However, only some system calls are restartable, so when writing modules for Simics, you have to make sure that you restart the other system calls yourself:

do {
        res = accept(sock, &saddr, &slen);
} while (res == -1 && errno == EINTR);

1.2.4 Text Output

Simics has its own text output routines that use the command-line window for display and also allow output to be directed elsewhere. To maintain this functionality these output routines should be used instead of the standard C library output routines: Use SIM_printf instead of printf, SIM_putchar instead of putchar, and so on.

The Simics output functions (SIM_write, SIM_printf, etc.) also send the resulting text to handlers registered using SIM_add_output_handler.

Here is an example showing how a module could get Simics to write a copy of all its text output to a log file:

static void
output_handler(void *file, const void *buf, size_t count)
{
    fwrite(buf, 1, count, (FILE *)file);
}

static void
init_local(void)
{
    SIM_add_output_handler(output_handler,
                           (void *)fopen("my.log", "a"));
}

1.2.5 Using Threads in Simics Modules

It is possible to write modules for Simics that use POSIX threads, but only a restrictive part of the Simics API can be used directly from such threads. It is possible, however, to post callbacks that have access to the entire API. One way to do that is through the SIM_thread_safe_callback API function. It is also possible to enter a context where a larger part of the Simics API is available. This, and the threading model in general, is discussed in some detail in chapter 2.

1.2.6 Header Inclusion Order

For modules written in C or C++, the general order of header file inclusion should be from most to least general:

Language e.g., <stdio.h> (C), <map> (C++)
Operating system e.g., <unistd.h> (Linux), <windows.h> (Windows)
Simics e.g., <simics/device-api.h>
Application specific to your module

When this order is observed problems related to interference between include files should be minimized. In particular, Simics may redefine some standard functions with preprocessor macros and this can cause problems unless the standard headers are included first.

1.1 Programming Concepts 1.3 API usage rules