API Reference Manual

1 Introduction

This manual contains the reference documentation for most Simics APIs. It describes the Device API, as well as the interfaces and haps that are available for developing models. The manual also describes the Simulator API and its interfaces, for use when developing extensions to Simics. Furthermore, the manual details the Link Library API - that's used to create link models to connect devices in different cells. The Processor API is used to create models of processors for use in Simics; the reference documentation for the Processor API is also present in this manual. The manual is concluded with the reference documentation of the Python API.

This manual is primarily meant to be used as reference documentation, but it also describes some concepts of central importance closely related to the API. Refer to the other Simics manuals, listed in the Documentation Contents document, for more details about other things.

1.1 Programming Concepts

This chapter describes the major programming concepts in Simics. It is intended for anyone who wants to write extensions or modules for Simics.

A Simics module is just some executable code loaded dynamically into the simulator, so it could perform virtually any operation. To be of any practical use however, a module has to interact with Simics, other modules, or the user. Simics provides a set of functions (the Simics API) for the modules to work within the simulator framework. The API defines a number of concepts like classes, objects, interfaces, haps, and events, which will be presented below.

Simics modules can be written using different programming languages:

DML
Device Modeling Language (DML) has been designed to make writing new device model as simple as possible. It integrates in the language many of the concepts defined by the Simics API so that the user can focus on the model rather than on the interaction with Simics. This is by far the best language for writing device models. Note that although it was designed with device models in mind, DML can be used to develop other types of modules.
Python
Python can be used to quickly write a new Simics module. It is well suited for Simics extensions that are not called very often, like some types of statistics gathering, or BIOS emulation. It can also be used for fast prototyping of more complex extensions that later on will be rewritten in a compiled language like DML or C. Note that in all cases, DML is easier to use than Python to write a device model.
C/C++
C and C++ can be used for writing any type of Simics module. Writing in C or C++ exposes all interactions with Simics, which can be sometimes cumbersome. C or C++ development is only recommended for specialized cases when DML or Python do not provide the functionality needed. A few specialized functions in the API are only available to C and C++ modules.
SystemC
Integrating existing SystemC device models into Simics simulations is supported by the SystemC Library. The library provides a set of gaskets that bridge from TLM-2.0 interface to Simics interfaces and from Simics interfaces to TLM-2.0 interface. See the SystemC Library Programming Guide for details. For new device modeling, DML is recommended since it is more efficient to model in and automatically supports all Simics features.

This chapter will cover the concepts that the Simics API defines. It will also present how to use them, first in DML, then in Python and C/C++.

1.1.1 Classes and Objects

Each device is represented by an object whose attributes correspond to the state of the device.

Most Simics modules work the same way: they define classes describing the properties of an object. This includes its attributes, interfaces and the class name. The objects are created by instantiating a class and setting the required attributes.

Note that modules and classes are not the same thing. A module can define two or more classes, or none at all. But many modules define a single class with the same name as the module.

1.1.2 Type

When registering an attribute, a type definition should be provided for Simics to check that the attribute is always set properly. This type definition is a string that is defined according to the following rules:

As an example, the "[s*]|s" string defines an attribute that can hold either a string or a (possibly empty) list of strings.

When writing complex attributes, you may notice that the type description strings do not cover all the possibilities offered by the attribute structure definition. If you need to register attributes that cannot be described in a type string (like complex variable size lists), you will need to use the a type and perform the type checking by yourself in the set() function. You may also want to review your attribute and change its definition to match a possible type description, or divide your attribute into several simpler attributes.

For example, an attribute accepting a list composed of one object and one or more integers can not be described in a type string (list definition with variable size can only have one element). You may want to rewrite your attribute to use a sub-list for the integers: [o[i+]], or you can perform type checking yourself.

1.1.3 Interfaces

Interfaces allow objects to interact with each other. An interface defines a number of functions. Every class that implements an interface (by registering it) must define those functions. In some cases, it is sufficient to implement just a subset of the functions. An object A may then ask for an interface registered by an object B, and thus use the interface's functions to communicate with B. Simics comes with many predefined interfaces but it is also possible to define new interfaces.

One of the most important interfaces for a device class is probably the io_memory interface. Implementing the io_memory interface enables a class to be mapped into a memory space and be accessed by the simulated machine. In C or DML, it is defined as:

typedef struct io_memory_interface {
        int (*_deprecated_map)(conf_object_t *NOTNULL obj,
                               addr_space_t memory_or_io,
                               map_info_t map_info);
        exception_type_t (*operation)(conf_object_t *NOTNULL obj,
                                      generic_transaction_t *NOTNULL mem_op,
                                      map_info_t map_info);
      } io_memory_interface_t;

Other interfaces can be used for things like raising processor interrupts or implementing PCI device functionality.

Interfaces are either implemented by the device class itself, or by one of its ports. This way, a device can have several ports implementing the same interface, for example interrupt controllers with several sources or memory mapped devices with separate banks of registers.

1.1.4 Logging

A device model should log its activities so that it is possible to see what happens. It is useful both while developing the model and while developing target software, or to help finding problems in the system. Logging should not be used in attribute accessor functions or in CLI commands where there are other ways to report errors. The Simics API provides logging facilities that classifies log messages based on the following criteria:

level
The verbosity level ranging from 1 through 4 in decreasing importance order. The term 'high' and 'low' for log-level is based on its priority, thus 1 is the highest log-level.
type
Each log message belongs to a specific category:

info
Info or debug message without any consequence on the simulation.
warning
Warning message about a problem in the simulation, which however still allows the simulation to continue.
error
An error occurred that prevents the simulation (or part of the simulation) from running properly. Note that error messages do not have any logging level and are always printed. If the sim->fail_on_warnings attribute is set to true, for example if Simics was started with the -werror command line flag, then Simics will exit with an error code when a log message of the error type is generated.
critical
Used to signal serious errors that the model may not be able to resume from. Simics will stop the simulation as soon as a critical error is logged.
unimplemented
A model does not implement a specific functionality, bit or register.
spec_violation
A model received commands from the target program that violates the device specification.

group
A bit-field, defined and registered by the module, used to separate different part of the device, for example to separate between the configuration of a device and using the device's services, or the PCI interface and the Ethernet interface, etc.

1.1.5 Events

When a device model wants some action to be taken at a later time, it posts an event and returns control to the simulation engine. This will cause a callback to be called after the requested simulated time has passed.

For example, a device that wants to raise a time interrupt every 10 ms would post an event with a callback that raises the interrupt and then reposts the event with a 10 ms delay.

The events are posted on a clock, which is usually one of the processor cores in the system. Typically, each device is associated with one clock on which it posts all its events, but it is possible to choose which clock to post on, as long as it is in the same simulation cell as the device.

Note: Some clocks, in particular the processor cores, also allow posting events on a step queue which doesn't count time, but CPU steps. This is usually not used by device models, but can be used for profiling extensions etc.
You can print out the current event queue by using the print-event-queue command (or peq for short).

1.1.6 Haps

Another way that models may react to Simics events is to use haps. (The term was chosen because happenstance was considered too long.) To react to a hap, a module can register a callback function to the hap. This callback function will then be called every time the hap occurs. A complete list of all haps, descriptions of what parameters the callback functions should take and all functions used to register callbacks and manipulate haps can be found in chapter 12.

In general, haps are slower than notifiers, and therefore less suitable for communication between models. However, haps allow sending additional parameters to the callback function.

1.1.7 Commands

A user interface for a module can be created by adding new commands to the Simics command line interface. Commands can be bound to a specific namespace (i.e., a class or an interface) or to the global namespace.

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 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:   #include <simics/device-api.h>
C++: #include <simics/cc-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:     #include <simics/devs/interface.h>
C++:   #include <simics/c++/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:     #include <simics/model-iface/interface.h>
C++:   #include <simics/c++/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:     #include <simics/simulator-iface/interface.h>
C++:   #include <simics/c++/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.3 API usage rules

1.3.1 Simics API value ownership rules

The owner of a value in memory is the code or object responsible for freeing the value when it is no longer needed. Failure to do so may cause excessive memory consumption (a memory leak). Deallocation of objects that are not owned, or use of objects after they have been freed, will likely result in a crash.

The ownership rules only apply to code written in C, C++ and DML. In Python, memory management is entirely automatic.

The general rules in Simics are:

Exceptions to the rules above are documented for each interface or API call.

Each data type has its own way of deallocation. It is generally documented where objects of that type are created; see below for some specific examples.

Strings
Null-terminated strings are freed using MM_FREE in C/C++, delete in DML. They are created using MM_MALLOC, MM_STRDUP or other functions that create heap-allocated strings. (The standard C library functions malloc, free etc should not be used.)

The pointer-to-const rule applies: a string returned as char * becomes owned by the caller, but not one returned as const char *.

Attribute values
Values of type attr_value_t are freed using SIM_attr_free.

Since the values may refer to heap-allocated data, they cannot be copied by simple (shallow) assignment. To create a (deep) copy of an attr_value_t that is safe to access after the original has been freed, use SIM_attr_copy.

The attr_value_t accessor functions return values that borrow references to parts of the argument. Therefore, the returned values cannot be altered, and cannot be used beyond the life-time of the argument. (This obviously does not apply to non-allocated values such as numbers or booleans.)

Simics-managed types
Values of some types are always owned and managed by Simics itself and should never be freed by the user. Examples are conf_object_t and conf_class_t.

1.3.2 API Execution Contexts

The set of Simics API functions and interface methods that can be called at a given point depends on the state of the execution thread at the time of the call. The thread states are classified into API execution contexts. Three distinct execution contexts are defined, and they are inclusive, as illustrated in the figure below:

The execution context defines the part of the Simics API that may be used


Below is a description of the defined execution contexts:

Global Context
Previously, this context was known as Outside Execution Context (OEC).

The most permissive context. A thread running in Global Context has exclusive access to all objects in the simulation.

In Global Context, either the simulation is not running or all simulation activity has temporarily been suspended. The front-end runs in this context, as do the callbacks from SIM_run_alone, SIM_thread_safe_callback and SIM_notify_on_socket with the run_in_thread argument set to 0. Module initialisation, object creation and object destruction are also performed in this context.

The full API is available, including functions and methods documented as callable in other contexts.

Cell Context (EC/IC)
This is a single context which was introduced in Simics 6 instead of Execution Context (EC) and Instruction Context (IC) that were around before.

The context used for most device simulation. Typically used when the simulation is running.

Only functions and methods documented as callable in Cell Context or Threaded Context are available in this context.

Other objects in the simulation may be accessed or referenced, but only objects belonging to the same simulation cell. The cell concept is discussed in some detail in section 2.3, but basically it is a partitioning of the simulation into groups of objects. Cell Context is always tied to a specific cell.

Most device code run in this context, for instance when a CPU accesses a device register, as do event callbacks and many hap handlers.

Threaded Context
Previously, this context was known as Foreign Thread Context (FTC).

The most restrictive context, denoting a thread which is in neither Cell Context nor Global Context.

Manually created threads and SIM_run_in_thread callbacks are examples where this context is applicable. Thread-aware models, like a CPU with support for multicore threading, also perform most of its simulation in Threaded Context.

The available API is limited to functions explicitly declared as being available in Threaded Context, but a more permissive context can be entered when needed. For example, SIM_thread_safe_callback posts a callback which is invoked in Global Context, and Cell Context can be reached with the SIM_ACQUIRE_CELL primitive.

While objects can be accessed in this context, it is only permitted after special primitives are used to ensure single-threaded access. This usually amounts to entering Cell Context, but thread-aware models can actually access their own object state directly from Threaded Context. This is discussed in chapter 2.

The reference manuals detail the permitted API execution context for each API function and interface method. Calls are allowed in the specified and more permissive contexts.

Violations of the API execution context rules have undefined consequences. They may result in warnings or error messages, but this is not guaranteed. In particular, a class implementing an interface method is under no obligation to perform any such checks.

1.4 Simics API Syntax

Most of the information in this chapter uses C syntax, extended with two additional keywords:

NOTNULL
The NOTNULL keyword means that this function argument must not be a null pointer. In Python, where None is used as the null pointer value, there will be an exception thrown if such a function is called with a None value.
PYTHON_METHOD
Most interfaces are in canonical form; i.e., they only contain function pointers, and the first argument is always the object whose interface is called.

For non-canonical interfaces, the keyword PYTHON_METHOD is used to mark regular methods. These should be called without their first argument when used from Python.

Note that there is no special mark-up for canonical interfaces.

2 Threading Model

This chapter describes the Simics threading model from a device model perspective. Important concepts as cells, thread domains and execution context are explained in some detail. The Standard Device Model and the Threaded Device Model are also defined.

2.1 Overview

At the highest level, a Simics configuration is partitioned into one or multiple simulation cells. Each cell can be simulated in parallel with the other cells, with maintained determinism.

Figure 1. Configuration is partitioned into cells. Cell membership is determined
by following queue and cell attributes to an actual cell object.

Distinct cells are loosely coupled. A typical example is a multi-machine configuration, where each machine consists of a single cell, and where the machines are connected with a simulated Ethernet network. Communication between cells occurs through special objects called links that forward messages between cells.

A device model should not access objects belonging to a different cell directly.

Each cell is partitioned into one or more thread domains. Models belonging to different thread domains can be simulated in parallel. However, objects within a single thread domain can only be accessed by a single thread at a time, namely by the thread currently holding the domain. A thread domain should be thought of as a high-level locking construct ensuring single-threaded access to the objects it contains.

Figure 2. Each cell is partitioned into thread domains.

Unlike the cell partitioning, which is static and given by the configuration, the partitioning of a cell into thread domains is performed by Simics as a function of the selected simulation mode, model capabilities, and any declared thread domain constraints.

The thread domains in a cell are not all equal. The thread domain which contains the cell object itself is special and is called the cell thread domain (cell TD). Objects residing in this domain use a very permissive device model, the Standard Device Model, described in section 2.6. Among other things, such models do not need to worry about thread domain boundary crossings or threading issues. Most models use this device model.

Models located in thread domains other than the cell TD are called thread-aware, and use the more restrictive Threaded Device Model, which is described in section 2.7.

The threads used to actually simulate the models are usually created by Simics, but models can also create their own threads. The Simics scheduler is briefly discussed in section 2.9.

2.2 Basic Module Requirements

To use multi-threading in Simics, all modules used in the simulation must be thread safe. This section describes what it means for a module to be thread safe, and what conditions must be fulfilled.

Note: In this section, thread safe is used in the sense that models instantiated in different cells can be simulated concurrently without issues. This is a weaker definition than normally used.
Simics checks each module it loads to see if it has been marked as safe. A module is thread safe if it fulfills the following conditions:

Below is an example makefile for a module marked as thread safe. It can be found in the [project]/modules/sample-user-decoder directory if the sample-user-decoder has been copied to the project.

MODULE_CLASSES = sample-user-decoder

SRC_FILES = sample-user-decoder.c

SIMICS_API := 6
THREAD_SAFE = yes

include $(MODULE_MAKEFILE)

To make a module thread safe, global state should be avoided, both in the form of global variables and in the form of local static variables in C. Having constant global variables are fine. Modules written in pure DML do not have this problem since the DML compiler does not emit any non-constant global state.

Simics checks for some execution context violations during run-time and emits warnings if they occur. When running with multi-threading disabled, violations result in warnings that can optionally be turned off. With multi-threading enabled, violations cause hard errors.

If a module that is not marked with THREAD_SAFE=yes is loaded, multi-threading will be turned off automatically and a warning will be shown. The list-modules command will show whether a module is marked thread safe or not.

2.3 Simulation Cells

A cell is a group of configuration objects which may interact with each other through direct function calls. If a model needs to communicate with objects in other cells during the simulation, it needs to do this through links (see section 2.3.4 or the Link Library Programming Guide). A link introduces a delay in the communication (unless immediate_delivery is set), which means that messages cannot be sent and received in the same cycle.

In a configuration, a cell is represented by a configuration object of class cell. All objects that implement the cycle interface (referred to as clocks) automatically have a cell attribute that will point to the cell they belong to. Since all Simics objects have a queue attribute pointing at a clock object, they will by extension belong to the cell of their clock object. This is illustrated in the figure below:

Figure 3. Configuration is partitioned into cells

Another example is the following configuration:
OBJECT cell0 TYPE cell {
}
OBJECT cell1 TYPE cell {
}
OBJECT cpu0 TYPE cpu {
       cell: cell0
}
OBJECT cpu1 TYPE cpu {
       cell: cell0
}
OBJECT cpu2 TYPE cpu {
       cell: cell1
}
OBJECT device0 TYPE device {
       queue = cpu0
}
OBJECT device1 TYPE device {
       queue = cpu0
}
OBJECT device2 TYPE device {
       queue = cpu2
}

In this example, device0 has cpu0 as a queue, and thus belongs to cell0, while device2 has cpu2 as a queue, and thus belongs to cell1.

2.3.1 Cells and Components

Simics provides an automatic cell partitioning based on top-level components. Each component object implements a create_cell() method that can return True or False to the question: should a simulation cell be created to contain this component and all its sub-components? By default, top-level components return True and all other components return False. By overriding this method, it is possible to automatically create cells at lower levels in the component hierarchy, or to disable cell creation altogether. In the latter case, the create_cell() should return False and the components should define cell objects themselves and assign clocks to them as appropriate, just as normal configuration objects.

The code snippets below show how to overload the create_cell() function for both old-style and hierarchical way of writing components.

class mycomp(component_object):
    ...
    def create_cell(self):
        return False

class mycomp(StandardConnectorComponent): # or StandardComponent
    ....
    class component(comp.StandardComponent.component):
        def create_cell(self):
            return False

Cells can also be created independently of components, by creating cell objects and setting the cell attribute of the clock objects which should belong to the cell.

2.3.2 Compatibility

If clock objects are created that do not point to a cell, then a default_cell object will be created, unless it exists already, to make sure these clock objects are scheduled as intended. This is a simple compatibility mechanism for use with older scripts. If you are building your configurations in several steps, but without using components, you will have to introduce your own cells and configure them.

2.3.3 Verifying the Cell Partitioning

The check-cell-partitioning command checks either a checkpoint or the currently loaded configuration for violations of the cell partitioning rules—namely, that objects belonging to one cell do not have any references to objects in another cell. Such references will be shown in the form of a chain of attributes connecting the cells.

An object is considered to belong to a cell if either it is a cell object, or if it refers to or is referred to by an object belonging to that cell. Object references are object values in (checkpointed) attributes.

False positives can be suppressed by defining the attribute outside_cell and setting it to true for objects that should not be considered part of any cell but still refer to other objects in cells. This can be necessary for objects that only use these references in safe ways, e.g., in Global Context.

2.3.4 Links

Links are the only Simics objects that should connect different cells together. In other words, link components are allowed to connect to device components belonging to different cells without breaking the cell isolation rules. This works because all communication over the links are asynchronous with a delay that is constrained by the synchronization parameters so that the information exchange never becomes indeterministic.

Note: While it is possible to perform cross-cell calls if special precautions are taken, it should be avoided since it likely prevents the simulation from being deterministic even when the simulation is running in the "serial" threading mode.

2.3.5 Synchronization domains

All cells are connected to a synchronization domain that controls the execution in the cells to ensure that they do not run too far apart in virtual time. The domain has a min_latency parameter that limits the allowed difference in time between clocks in all the cells connected to it. This works as a lower limit for the latency that link objects can use when communicating between cells.

2.4 Thread Domains

Each object in the simulation has a thread domain associated with it. The same thread domain can be associated with multiple objects.

The basic rule is that before the state of an object is accessed, the corresponding thread domain needs to be held by the thread performing the access. This ensures that an object is never accessed concurrently by two different threads.

The thread domain containing the cell object, the cell thread domain (cell TD), has some special properties. Sometimes it is referred to as just the "cell" for brevity, as in "acquiring the cell", and "holding the cell", which should be read as "acquiring the cell thread domain", and "holding the cell thread domain" respectively.

Division of a cell into thread domains

The cell TD should be thought of as a single-threaded domain. To a model in the cell TD, everything in the entire cell appears to be simulated from a single thread, even if this is not the case.

Note: In most cases, the appropriate thread domain is already held, and no special action needs to be taken. This is for instance the case for normal device models, which run in Cell Context, or for code running in Global Context.

Only models which use custom threads or use the Threaded Device Model need to acquire thread domains explicitly.

2.4.1 Relationship with API Execution Context

The relationship between the API execution context, defined in section 1.3.2, and thread domains is as follows:

Global Context
All thread domains (and by implication, all cells) in the simulation are held by the thread. The thread has exclusive access to all objects. CLI scripts, Python scripts, CLI commands, script-branches, and object initialization code, all run in Global Context.

Cell Context
The cell TD is held by the thread. The thread can freely access all other objects in the cell. Normal device models (i.e. models which are not thread-aware) can assume that they are invoked in this context.

Threaded Context
No thread domains are required to be held, but thread-aware models often hold their own thread domain.

Note: The locking model in Simics is asymmetrical. Models running in Cell Context can call interface functions on any object in the cell without taking any special measures, and this includes interfaces on objects belonging to a different TD. This is possible since thread-aware models are required to guard model entry points by acquiring their own domains. Conversely, thread-aware models are required to enter Cell Context explicitly, by using a special API call, before calling interface functions on objects in the cell TD.

2.4.2 Lock Semantics

A thread domain has the following basic properties:

The following macros are used to acquire thread domains.

SIM_ACQUIRE_OBJECT
Acquires the thread domain associated with the object.

This function is intended to be used by thread-aware objects to obtain its own thread domain before modifying internal state protected by the domain.

This primitive does not enter Cell Context, even if the cell TD is acquired. The reason is that the retention mechanism is not activated (see below).

SIM_ACQUIRE_TARGET
Enters Cell Context if the specified object belongs to the cell TD. As part of entering Cell Context, the cell TD is acquired.

This primitive does nothing if the object does not belong to the cell TD. In other words, it is a no-op if the specified object is thread-aware.

Thread-aware code, which is not running in Cell Context, uses this function before invoking an interface method on an external object.

SIM_ACQUIRE_CELL
Enters Cell Context unconditionally. The specified object is associated with a cell whose TD is acquired as part of entering Cell Context.

The function should be used before calling an API function, or callback, requiring Cell Context.

Each primitive above should be used together with the corresponding release function. Macros are used in order to allow lock statistics to be collected with information about where the lock was acquired. There are also corresponding SIM-functions available.

Note: If multiple thread domains are acquired, then they must be released in strict reverse order. Failure to do so will result in a hard error and a complaint about locks being released in an incorrect order.
Note: The difference between SIM_ACQUIRE_CELL and SIM_ACQUIRE_TARGET is really that the former always acquires the cell thread domain and enters Cell Context, whereas the latter is a no-op when a thread-aware object is specified.

The reason for the distinction is that thread-aware objects are required to protect incoming as needed; this self-protection usually involves a call to SIM_ACQUIRE_OBJECT, but models are free to use alternate locking schemes.

2.4.3 Contention

Note: This section describes how Simics handles thread domain contention, and it is mostly provided to allow for a deeper understanding of the Simics threading model.
When a thread tries to acquire a thread domain which is already held or requested by another thread, then the following happens:

The priority is assigned as follows:

 
Priority Name    Situation
1Execute TD acquired for instruction execution (lowest priority)
2Yield domains reacquired after explicit yield
3Entry TD acquired, no other domains held
4Entry 2 TD acquired, other TDs already held
5Cell Entry cell acquired with SIM_ACQUIRE_CELL/TARGET
6Elevated TD acquired in Cell Context
7Message TD acquired for delivery of direct memory message

In the table above, TD stands for a thread domain which is not the cell TD.

A contended thread domain is always assigned to the waiting thread with the highest priority. The domain is never released to a thread with lower priority, even if the domain is unused and the highest priority thread is waiting upon some other domain.

The priority scheme serves two purposes:

Note: For performance reasons, a thread waiting for a thread domain will typically spin for a certain amount of time before falling back to sleeping on some condition variable.

2.4.4 Domain Retention

In Cell Context, a special mechanism is used when additionally acquired thread domains are released:

Domain retention mechanism
The release of additionally acquired domains is deferred until Cell Context is exited, or in other words, until the cell TD is released.

As an example, consider a thread doing the following, with CPU1 belonging to thread domain TD_cpu1, CPU2 to TD_cpu2, and device DEV to TD_cell, respectively:

  1. CPU1 is simulated while holding TD_cpu1
  2. EC is entered before the model calls an interface on DEV. TD_cell is acquired when EC is entered.
  3. device DEV queries CPU2 for its cycle count. The TD_cpu2 domain is acquired and released during this operation, but the actual release of TD_cpu2 is deferred by the retention mechanism
  4. device DEV posts an event on CPU2, again taking and releasing TD_cpu2
  5. TD_cell is released when the DEV interface call returns, and the thread leaves Cell Context. The retention mechanism causes TD_cpu2 to be released for real at this point
The retention mechanism ensures that TD_cpu2, in the example above, is held until the device access is complete. Between point 3 and point 5, CPU2 will not be simulated, and its state will be stable.
Note: The retention mechanism ensures that a device model sees a stable state for all objects it interacts with. The mechanism allows CPUs to run concurrently with device models, but when a device model interacts with a CPU, it is stopped until the device operation is complete.

2.5 Concurrency Modes

A device model can run in one of three concurrency modes. The modes are as follows:

Sim_Concurrency_Mode_Serialized
The model can assume Cell Context.

The model is put in the cell thread domain.

The device may interact with all objects in the cell without having to acquire any thread domains or take threading into account.

Objects in the same cell, including objects belonging in other thread domains, always have a stable state when queried.

Sim_Concurrency_Mode_Serialized_Memory
The model runs in Threaded Context.

The model is put in a separate thread domain.

The model is required to handle locking explicitly for both incoming and outgoing interface calls.

Whenever the model crosses a thread domain boundary, or enters Cell Context, all devices in the cell can potentially undergo state transitions.

Models that share memory must be grouped together (see the section on Thread Domain Groups below).

Sim_Concurrency_Mode_Full
The model runs in Threaded Context.

The model is put in a separate thread domain.

The model is required to handle locking explicitly for both incoming and outgoing interface calls.

Whenever the model crosses a thread domain boundary, or enters Cell Context, all devices in the cell can potentially undergo state transitions.

The model cannot assume that pages granted through the direct-memory subsystem are not accessed concurrently from a different thread, unless exclusive access have been requested explicitly.

Note: The concurrency mode basically only affects whether the model is put in the cell thread domain or not. Simics cannot automatically detect needed grouping of models, therefore it is the responsibility of the platform developer to assure that models are grouped in a correct way.

2.5.1 Mode Selection

A model advertises its supported concurrency modes through the concurrency_mode interface. If the interface is omitted, and the object is not grouped with an object implementing the concurrency_mode interface (see the next section), then the model is assumed to only support Sim_Concurrency_Mode_Serialized.

If the model supports multiple modes, the interface is also used by Simics to select the concurrency mode the model should use. The mode is derived from the simulation mode set through the set-threading-mode command.

Device models normally run in the serialized concurrency mode, whereas CPU models preferably should support all the modes.

Note: The set-threading-mode command is used by the user to set the threading mode of the simulation.

The "serialized" mode puts models in the serialized concurrency mode.

The "subsystem" mode configures models to use the serialized memory concurrency mode, if supported, and serialized mode otherwise.

The "multicore" mode configures models to use the full concurrency mode, if supported, and serialized memory or just serialized mode otherwise.

2.5.2 Thread Domain Groups

Objects that are part of a thread domain group will be put in the same thread domain. There can be different reasons for models to be part of the same thread domain. To keep memory accesses serialized when subsystem threading is used all models that share memory should be put in the same group. Even when running in multithreading mode there are objects that should reside in the same thread domain. Examples include:

When forming thread domain groups, Simics queries all objects implementing the concurrency_group interface. The interface returns constraints of the type "these objects should be put in the same thread domain", and they are of two kinds:
  1. constraints that are used in all concurrency modes
  2. constraints that are only used in the serialized memory mode.

A port object is always placed in the same thread domain as its parent, unless it implements the concurrency_mode interface or is grouped explicitly with such an object.

For CPU models, the following is recommended:

Sim_Concurrency_Mode_Serialized_Memory
Tightly connected CPUs are grouped together.

In this context, tightly connected really means CPUs that run the same OS instance. CPUs which run distinct OS instances, but share memory, or devices, through some fabric, do not need to be placed in the same group.

Sim_Concurrency_Mode_Full
All CPU cores are placed in separate thread domains.

The above allows groups of tightly coupled CPUs to be simulated in parallel when the simulation is configured to use subsystem threading, while allowing all the CPUs to run in parallel in multicore mode.

2.6 Standard Device Model

By default, devices in Simics use the Standard Device Model. Such models run in the Sim_Concurrency_Mode_Serial concurrency mode.

Using the Standard Device Model amounts to being able to assume at least Cell Context when interface methods are invoked. Certain things, like object initialization, run in Global Context, which is the most permissive context.

2.6.1 Properties

Cell Context has the following properties:

In Cell Context, everything within the cell appears to be completely serialized. Under to hood, this may not be the case, and CPUs might be running concurrently. But when a CPU is accessed from a device, it is stopped until the device access is complete. For instance, a device will always see a stable cycle count when it repeatedly queries its associated clock during a register access.

2.7 Threaded Device Model

An object using one of the concurrency modes Sim_Concurrency_Mode_Serialized_Memory or Sim_Concurrency_Mode_Full is called a thread-aware model. The Threaded Device Model must be followed by such objects.

Thread-aware models run mostly in Threaded Context.

This section primarily discusses thread-aware models, but much of the contents also applies to code invoked directly from a "foreign" thread.

Note: A CPU is the typical example of a thread-aware model. Most devices should rather use the Standard Device Model.

2.7.1 Programming Model

Thread-aware models need to take the following into account:

Incoming Interface Calls
Interfaces implemented by thread-aware models can be invoked in Threaded Context rather than Cell Context, and the thread domain associated with the object cannot be assumed to be held on entry.

It is the responsibility of the model to ensure that its state is protected, usually by calling SIM_ACQUIRE_OBJECT from its interface methods, as in the following example:

      static void
      some_interface_method(conf_object *obj)
      {
          domain_lock_t *lock;
          SIM_ACQUIRE_OBJECT(obj, &lock);
          /* ... internal state is protected by the TD ... */
          SIM_RELEASE_OBJECT(obj, &lock);
      }
    

No extra protection is needed for interfaces which are only available in OEC. All thread domains are already held on entry.

Note: There are a few situations when the model is invoked with its thread domain already held:
  • The run method of the execute interface is invoked with the object's thread domain held. The model should not acquire the domain again, since this would block the signaling mechanism used to notify the model when another thread tries to acquire the domain.
  • The methods in the the direct_memory_update interface are always invoked with the thread domain held.
Outgoing Interface Calls
When a thread-aware model invokes an interface method on an object which is not known to reside in the same thread domain, then the call must be protected with SIM_ACQUIRE_TARGET, with the interface object provided as an argument. This ensures that Cell Context is entered, when necessary.

Example of an "outgoing" interface call:

      domain_lock_t *lock;
      /* incoming interface calls may occur here */
      SIM_ACQUIRE_TARGET(target_obj, &lock);
      some_interface->some_method(target_obj, ...);
      SIM_RELEASE_TARGET(target_obj, &lock);
    

Note: If the target object is thread-aware, then SIM_ACQUIRE_TARGET will actually be a no-op.
Note: If the cell TD is busy when SIM_ACQUIRE_TARGET is executed, then the model may see incoming interface calls while waiting for the domain, since all held domains are temporarily released while waiting.
API Calls
Cell Context must be entered before any API function can be called which requires this context. The context is entered with the SIM_ACQUIRE_CELL primitive, as in this example:
      domain_lock_t *lock;
      /* incoming interface calls may occur here */
      SIM_ACQUIRE_CELL(obj, &lock);
      /* this code runs in Cell Context */
      breakpoint_id = SIM_breakpoint(...);
      SIM_RELEASE_CELL(obj, &lock);
    

Some functions that need this protection:

  • HAP functions (SIM_hap_add_callback, ...)
  • SIM_breakpoint, SIM_delete_breakpoint
  • SIM_issue_transaction

There are, however, many functions that can be called directly in Threaded Context, e.g.

  • functions performing logging (SIM_log_info, ...)
  • functions returning constant object properties (SIM_object_name, SIM_get_interface, ...)
  • allocations (MM_MALLOC, SIM_alloc_attr_list, ...)
  • accessors (SIM_attr_integer, SIM_transaction_is_read, ...)
  • dbuffer API (but the dbuffer itself is not thread safe)
  • SIM_run_unrestricted, SIM_run_alone
Some API functions can be called directly, as long as the TD has been acquired for the object in question:
  • event related functions (SIM_event_post_cycle, ...)
  • time related functions (SIM_time, SIM_cycle_count, ...)
Callbacks
Callbacks triggered by the model are often expected to be dispatched in Cell Context. The model must enter Cell Context using SIM_ACQUIRE_CELL before dispatching such callbacks.

Note: Events registered with the Sim_Event_No_Serialize flag and callbacks used by the CPU instrumentation framework do not need to be protected. For these callbacks, it is the callee's responsibility to be aware that the context can be more limited than Cell Context. This is a performance optimization to allow fast callbacks with minimal overhead.
Attributes
Registered attribute setters and getters are automatically protected; an object's thread domain is always held when attribute setters and getters are invoked.

Note: Attributes should be used for configuration and to hold state. Attributes should never be used for communication between objects during simulation.

2.7.2 Domain Boundary Crossings

Whenever a thread-domain boundary is crossed, already held domains may temporarily be released to avoid deadlock situations. This allows unrelated, incoming, interface calls to occur at such points.

A thread-aware model must ensure that potential state changes caused by incoming interface calls are taken into account. This is one of the challenging points when writing a thread-aware model.

In Cell Context, boundary crossings are not an issue, since this context is prioritized exactly to avoid unexpected interface calls. Thread-aware models, running in Threaded Context, are not as fortunate and need to be aware of the possibility.

It is recommended that incoming interface calls are kept as simple as possible for thread-aware models. If possible, the interface action should be deferred and handled from an inner loop, especially for CPUs. For instance, a RESET interface should not perform the reset immediately, but instead set a flag that a reset should be performed before dispatching the next instruction.

2.7.3 Mixing Thread Domains and Mutexes

It is easy to run into problems when different locking schemes are combined. This is also the case when mixing mutexes and thread domains. The following examples illustrate some pitfalls:

Example 1
Acquiring a thread domain while holding a lock:
      Thread 1                  Thread 2
      Locks Mutex1              Acquires TD1
      Acquires TD1 (blocks)     Locks Mutex1 (blocks)
    

Thread 1 will never be able to acquire TD1 since this domain is held by thread 2 which blocks on Mutex1.

Note that the above example will also cause a deadlock if two mutexes are used rather than one mutex and one thread domain:

      Thread 1                  Thread 2
      Locks Mutex1              Locks Mutex2
      Locks Mutex2 (blocks)     Locks Mutex1 (blocks)
    

Whereas no deadlock occurs with two thread domains:

      Thread 1                  Thread 2
      Acquires TD2              Acquires TD1
      Acquires TD1*             Acquires TD2*
       *Not a deadlock - Simics detects and resolves this situation
    

Example 2
Waiting for a condition variable while holding a thread domain:
      Thread 1               Thread 2
      Acquires TD1           .
      Waits for COND1	     Acquires TD1 (blocks)
                             Releases TD1 (not reached)
	                     .
                             Signals COND1 (not reached)
    

Sleeping on a condition while holding a thread domain easily leads to deadlocks. Threads requiring the thread domain will get stuck and potentially prevent the condition from being signaled.

In practice, code can seldom make assumptions about which thread domains are held. For instance, an interface function can be invoked with an unknown set of thread domains already acquired. The domain retention mechanism also makes the picture more complex.

To avoid deadlocks, the following general principles are encouraged:

When needed, it is possible to drop all thread domains, which is illustrated in the following example:
  domain_lock_t *lock;
  SIM_DROP_THREAD_DOMAINS(obj, &lock);
  /* no thread domains are held here... */
  SIM_REACQUIRE_THREAD_DOMAINS(obj, &lock);

Note: Avoid empty drop/reacquire pairs. If the intention is allowing other objects to access held domains, then SIM_yield_thread_domains should be used instead. The yield function, besides being faster, guarantees that all waiting threads are given an opportunity to acquire the held domains.

2.7.4 Thread-Aware CPUs

Thread-aware CPUs have a few extra things to consider.

Execution
CPU models are driven from the run method of the execute interface. The method is invoked in Threaded Context, with the CPU thread domain already held.

The thread calling run is a simulation thread managed by the Simics scheduler. It is possible that this thread is used to simulate more than one model.

The model is not guaranteed that the run function is always invoked by the same thread.

Signaling
Whenever another CPU, or a device model, tries to acquire the CPU domain, the CPU is notified through the execute_control interface.

When a CPU is signaled in this way, it should as soon as possible call SIM_yield_thread_domains. The yield function ensures that pending direct memory update messages are delivered and allows other threads to invoke interfaces on the CPU object.

The signaling methods are invoked asynchronously, and the implementation must not acquire any thread domains or call API functions.

The signaling only occurs when the CPU's thread domain is the only domain held. Acquiring an additional domain, even the already held domain, temporarily blocks the signaling mechanism. Due to this, it is important that the CPU thread domain is not acquired in the run method, since it is already held on entry.

Note: To minimize the waiting time for other threads, it is important that the signaling is detected quickly.
Direct Memory
The methods of the direct_memory_update interface are invoked with the CPU thread domain already acquired. The model should service requests quickly and without acquiring additional thread domains.

2.7.5 Thread Domain Contention

Statistics about thread-domain acquisition can be collected with the enable-object-lock-stats command. This functionality is useful when a model is optimized to avoid unnecessary thread-domain crossings or to investigate thread-domain contention.

There is a definite overhead associated with collecting the statistics; it should not be turned on by default.

The collected statistics can be shown with the print-object-lock-stats command:

┌─────┬───────┬─┬────────────────────────────┬─────────────────────────────────┐
│Count│Avg(us)│ │          Function          │               File              │
├─────┼───────┼─┼────────────────────────────┼─────────────────────────────────┤
│  396│   1.94│ │get_cycles                  │core/clock/clock.c:172           │
│  369│   1.91│ │post                        │core/clock/clock.c:254           │
│   27│   2.00│C│handle_event                │core/clock/clock-src.c:211       │
│   12│   2.33│ │pb_lookup                   │core/common/image.c:3965         │
│    7│   2.86│C│cpu_access                  │cpu/cpu-common/memory.c:508      │
│    8│   2.38│C│perform_io                  │cpu/x86/x86-io.c:128             │
│    6│   1.83│ │dml_lookup                  │core/common/memory-page.c:431    │
│    3│   3.00│C│call_hap_functions_serialize│core/common/hap.c:1410           │
│    3│   2.33│ │cancel                      │core/clock/clock.c:280           │
└─────┴───────┴─┴────────────────────────────┴─────────────────────────────────┘

The command basically displays the location in the source where thread domains have been acquired, and how quickly the domains were acquired. The 'C' indicates that Cell Context was entered.

2.8 Foreign Threads

Threads created explicitly by models are called foreign threads. Such threads run in Threaded Context. There are also various API functions that registers callbacks that are called in FTC, like SIM_run_in_thread and SIM_notify_on_socket with the run_in_thread argument set to 1.

Many of the things stated in the preceding section is also relevant to foreign threads. One difference, however, is that foreign threads can be created by models using the Standard Device Model.

2.8.1 Device Interactions

The following outlines how a foreign thread can interact with the rest of the simulation:

Accessing a Device Object
A foreign thread can enter Cell Context using the SIM_ACQUIRE_CELL function. Once in Cell Context, the thread can interact with the object just like a normal device would do, and without needing any additional locking.
      /* foreign thread */
      SIM_ACQUIRE_CELL(obj, &lock);
      /* safe to access the device */
      SIM_RELEASE_CELL(obj, &lock);
    

Entering Global Context
A foreign thread can post callbacks that are run in Global Context, and hence allowed to access everything in the simulation. This is done using SIM_thread_safe_callback
      static void
      global_context_callback(void *data)
      {
          /* this code runs in Global Context */
      }

      {
          /* ... Threaded Context ... */
          SIM_thread_safe_callback(global_context_callback, data);
      }
    

It should be noted that the function posting the callback returns immediately, usually before the callback has started executing. Also, posting a Global Context callback is a relatively expensive operation since it involves stopping all running CPUs.

2.9 Simics Scheduler

The Simics scheduler is responsible for ensuring that models implementing the execute interface are scheduled. It is also responsible for mapping actual threads to the simulation workload and for keeping distinct CPUs synchronized in virtual time.

2.9.1 Basic Operation

The Simics Scheduler compiles a list of simulation tasks that can be run in parallel. Each task consists of a thread domain with one or more models implementing the execute interface.

The number of tasks that can be simulated in parallel depends on the thread domain partitioning, which in turn depends on the selected simulation mode. The simulation mode is configurable with the set-threading-mode command.

The available tasks are mapped to a set of execution threads managed by the scheduler. The number of threads used depends on the host hardware and any limit imposed by the user. The latter is settable with the set-thread-limit command.

A particular simulation task is usually simulated from a specific simulation thread in order to maximize cache locality. However, a task can be migrated to another thread when this is needed for load-balancing reasons. Thus, a model should not make any assumptions about the thread it is simulated from.

2.9.2 Virtual Time Synchronization

The scheduler ensures that all CPUs (and clocks) are kept synchronized in virtual time. More specifically, the virtual time for a pair of CPUs are not allowed to differ more than a fixed amount. A simulation task becomes blocked when it is about to break this invariant.

If a single thread domain contains more than one object implementing the execute interface, then the scheduler switches between them in a round-robin fashion. Each executor is simulated until the virtual time has advanced one time-quantum. The interval is settable with the set-time-quantum command.

The time difference for CPUs in the same cell, but in distinct thread domains, is not allowed to exceed the max-time-span limit. The limit is settable with the set-max-time-span command and is usually of the same order of magnitude as the time quantum.

The time difference between CPUs in distinct cells is kept below the min-latency limit. This limit is set with the set-min-latency command. The min-latency is often allowed to be a bit higher than the other limits.

3 Device API

The Simics Device API is a set of types and functions that provide access to Simics functionality from device models, usually written in DML or C/C++. The Device API is the same in all languages but the syntax of the types and functions declarations will of course differ.

3.1 Frontend Exceptions

Whenever an error occurs in a Simics API function, that function will raise an exception. An exception consists of an exception type and an error message.

The following exception types are defined in the Simics API:

typedef enum sim_exception {
        SimExc_No_Exception,
        SimExc_General,
        SimExc_Lookup,
        SimExc_Attribute,
        SimExc_IOError,
        SimExc_Index,
        SimExc_Memory,
        SimExc_InquiryOutsideMemory,
        SimExc_InquiryUnhandled,
        SimExc_Type,
        SimExc_Break,
        SimExc_PythonTranslation,
        SimExc_License,
        SimExc_IllegalValue,
        SimExc_InterfaceNotFound,
        SimExc_AttrNotFound,
        SimExc_AttrNotReadable,
        SimExc_AttrNotWritable
} sim_exception_t;

Note that API users writing in C must use SIM_clear_exception() and SIM_last_error() since C does not support exceptions. In Python, the Simics API exceptions will trigger actual Python exceptions, which you can capture using try ... except.

3.2 Device API Data Types

3.2.1 Generic Data Types

attr_value_t

NAME
attr_value_t
DESCRIPTION
The attr_value_t is the type used for all values in the configuration system. It is a tagged union.

The following table shows the different types of values, the type of their payload in C, and the corresponding Python types:

Kind C payload Python type
Invalid - raises exception
Stringconst char * str or unicode
Integer int64 or uint64 int or long
Boolean bool bool
Floatingdouble float
Object conf_object_t * simics.conf_object_t
List array of attr_value_t list
Dict array of pairs of attr_value_t dict
Data array of bytes tuple of small integers
Nil - None

The members inside attr_value_t should not be accessed directly. Instead, use the corresponding functions for each type:

Constructor SIM_make_attr_TYPE
DestructorSIM_attr_free
Type predicate SIM_attr_is_TYPE
AccessSIM_attr_TYPE

Values of type List and Dict can be modified using SIM_attr_TYPE_set_item and SIM_attr_TYPE_resize.

None of these functions are available or needed in Python. The attr_value_t values are translated to the ordinary Python values as shown in the table above.

Some values may have data in separate heap allocations. These are normally managed by the respective constructor and destructor methods, but careless copying of values may introduce aliasing errors. Use SIM_attr_copy to duplicate values. Again, this is of no concern in Python.

SEE ALSO
SIM_make_attr_int64, SIM_attr_is_integer, SIM_attr_integer, SIM_attr_free, SIM_attr_list_resize, SIM_attr_list_set_item, SIM_attr_dict_resize, SIM_attr_dict_set_item, SIM_attr_copy

buffer_t

NAME
buffer_t
SYNOPSIS
typedef struct {
        uint8 *data;
        size_t len;
} buffer_t;

DESCRIPTION
A reference to a (mutable) buffer. When used as a function parameter, the callee is permitted to write up to len bytes into the buffer pointed to by data.

Returning values of this type from interface methods should be avoided. If this is the case the scope of the returned object should be documented.

The corresponding Python type is called buffer_t, and behaves like a fixed-size mutable byte vector. The constructor takes as argument either a string, providing the initial value, or an integer, specifying the buffer size.

bytes_t

NAME
bytes_t
SYNOPSIS
typedef struct {
        const uint8 *data;
        size_t len;
} bytes_t;

DESCRIPTION
An immutable sequence of bytes. When used as a function parameter, the callee should treat the data as read-only.

When used as a return value, the data member must point to a heap-allocated memory block whose ownership is transferred to the caller. The caller is then responsible for freeing the block.

The corresponding Python type is Python's built-in class 'bytes'. Here are a few code examples that create 'bytes' objects in Python: b'abcd', b'\xf0\xf1\xf2\xf3', bytes([0xf0, 0xf1, 0xf2, 0xf3]), 0xf3f2f1f0.to_bytes(length=4, byteorder='little'), bytes.fromhex('f0f1f2f3').

cbdata_t, cbdata_call_t, cbdata_register_t, cbdata_type_t

NAME
cbdata_t, cbdata_call_t, cbdata_register_t, cbdata_type_t
SYNOPSIS
typedef struct {
        const char *name;
        void (*dealloc)(void *data);
} cbdata_type_t;

typedef struct cbdata cbdata_t;

typedef cbdata_t cbdata_register_t, cbdata_call_t;

DESCRIPTION
These data types are used by API functions and interface methods that provide callbacks with callback data. By using these data types instead of a simple void *, the callback data can be freed correctly when not needed anymore.

The types cbdata_register_t and cbdata_call_t are only aliases for cbdata_t, used to annotate whether the object is passed to a registration function or a callback function. This is used by the automatic Python wrapping to ensure that the callback data is freed correctly.

Objects of this type can be created by using either SIM_make_cbdata or SIM_make_simple_cbdata. The latter creates an untyped objects with no deallocation function, while the former takes a cbdata_type_t argument, specifying a type name and a deallocation function.

The following example shows how an API function could be defined using these data types:

   void for_all_ids(void (*callback)(const char *id,
                                     cbdata_call_t data),
                    cbdata_register_t data);
   

Note how the two flavors of cbdata_t are used. cbdata_register_t is used to pass some data to for_all_ids which passes the same data unmodified to callback. Here is an example of how this function could be called; from C:

   static void callback(const char *id, cbdata_call_t data)
   {
       const char *prefix = SIM_cbdata_data(&data);
       printf("%s %s\n", prefix, id);
   }
         :
       for_all_ids(callback, SIM_make_simple_cbdata("Testing"));
   

and from Python:

   def callback(id, prefix):
       print("%s %s" % (prefix, id))

   for_all_ids(callback, "Testing")
   

Note in particular that the Python code does not mention "cbdata" anywhere; it is all automatically handled by the Python wrapping code.

The C version of the previous example used SIM_make_simple_cbdata, as the constant string "Testing" does not need any deallocation function. For dynamically allocated data, you must use SIM_make_cbdata instead:

   static const cbdata_type_t malloced_int_type = {
       "integer",       // name
       free             // dealloc
   };

   static void callback(const char *id, cbdata_call_t data)
   {
       int *count = SIM_cbdata_data(&data);
       printf("%d %s\n", *count, id);
       ++*count;
   }
         :
       int *counter = malloc(sizeof *counter);
       *counter = 1;
       for_all_ids(callback, SIM_make_cbdata(malloced_int_type, counter));
   

In this example, for_all_ids is responsible for calling the deallocation function for the callback data after it has completed all calls to callback. It does this by calling SIM_free_cbdata, which in turn will call malloced_int_type.dealloc; i.e., free.

The same example in Python; we still do not have to call any cbdata function manually, but we do have to pass the counter in a one-element list since integers are immutable in Python:

   def callback(id, count):
       print("%s %s" % (prefix, count[0]))
       count[0] += 1

   for_all_ids(callback, [1])
   

While the use of cbdata_t over a simple void * in these examples seems redundant, they are needed if for_all_ids does not call callback before returning, but asynchronously at some later point in time. The use of cbdata_t also ensures that the data is freed correctly even when any of the involved functions is implemented in Python. This case often arises in conjunction with Simics interfaces.

See the Callback Functions in Interfaces section in the Simics Model Builder User's Guide for more information on how to use the cbdata_t types.

SEE ALSO
lang_void, SIM_make_cbdata, SIM_make_simple_cbdata, SIM_free_cbdata, SIM_cbdata_data, SIM_cbdata_type

class_data_t

NAME
class_data_t, class_kind_t
SYNOPSIS
typedef struct class_data {
        conf_object_t *(*alloc_object)(lang_void *data);
        lang_void *(*init_object)(conf_object_t *obj, lang_void *data);
        void (*finalize_instance)(conf_object_t *obj);

        void (*pre_delete_instance)(conf_object_t *obj);
        int (*delete_instance)(conf_object_t *obj);

        const char           *description;
        const char           *class_desc;
        class_kind_t          kind;
} class_data_t;

DESCRIPTION
The class_data_t type is used when a new class is registered. Uninitialized fields should be set to zero before the structure is passed to SIM_register_class.

When a new object is created, memory for the conf_object_t is allocated by Simics unless alloc_object has been provided by the class. Classes written in C may implement alloc_object to have a single allocation and must then place conf_object_t first in the object data structure. This has the advantage of allowing casts directly from a conf_object_t * to a pointer to the user structure instead of using SIM_object_data.

When the conf_object_t has been allocated, the init_object function is called. If the object instance needs additional storage, it may allocate its own memory and return a pointer to it from init_object. This pointer can later be obtained using SIM_object_data. The return value from init_object has to be non-null to signal a successful object initialization. If a null value is returned, no configuration object will be created and an error will be reported. For classes that implement their own alloc_object, there is no need to allocate additional storage in the init_object function and they can simply return the conf_object_t pointer from init_object.

alloc_object and init_object both receive a data parameter; they are currently not used, and should be ignored.

The optional finalize_instance function is called when all attributes have been initialized in the object, and in all other objects that are created at the same time.

The pre_delete_instance and delete_instance fields can be set to let the objects of this class support deletion:

  • pre_delete_instance will be called in the first phase of the object deletion, during which objects are expected to clean-up their external links to other objects (breakpoints, hap callbacks, file or network resources, ...). They may also trigger the deletion of other objects. pre_delete_instance is only called for objects that have reached at least finalize_instance during initialization.
  • delete_instance will be called in the second phase of the object deletion: objects are expected to deallocate the memory they use including the object data structure. They may not communicate with other objects as these may already have been destroyed. The return value from delete_instance is ignored for compatibility. delete_instance is always called unless alloc_object is not defined, or if it returned NULL.

The delete functions may be called by Simics before an object is fully configured. That is, without any call to finalize_instance and possibly before all the attribute set methods have been called. This may happen when the object is part of a configuration that fails to load. The SIM_object_is_configured function can be used to determine if finalize_instance has run or not.

The description string is used to describe the class in several sentences. It is used in the help commands and reference manuals. The class_desc string is a short class description beginning with lower case, without any trailing dot, and at most 50 characters long. It is used in help commands and for example in the GUI.

Note: The old class functions are legacy. New code should use class_info_t and SIM_create_class.
.

class_info_t

NAME
class_info_t, class_kind_t
SYNOPSIS
typedef enum {
        Sim_Class_Kind_Vanilla = 0, /* object is saved at checkpoints */
        Sim_Class_Kind_Session = 1, /* object is saved as part of a
                                     * session only */
        Sim_Class_Kind_Pseudo = 2,  /* object is never saved */

        Sim_Class_Kind_Extension = 3, /* extension class
                                         (see SIM_extend_class) */
} class_kind_t;

typedef struct class_info {
        conf_object_t *(*alloc)(conf_class_t *cls);
        lang_void *(*init)(conf_object_t *obj);
        void (*finalize)(conf_object_t *obj);
        void (*objects_finalized)(conf_object_t *obj);

        void (*deinit)(conf_object_t *obj);
        void (*dealloc)(conf_object_t *obj);

        const char           *description;
        const char           *short_desc;
        class_kind_t          kind;
} class_info_t;

DESCRIPTION
The class_info_t type is used when a new class is registered. Uninitialized fields should be set to zero before the structure is passed to SIM_create_class.

The alloc method is responsible for allocating memory for the object itself, i.e. the conf_object_t structure. If no alloc method is provided, Simics will use a default one, which uses MM_MALLOC. Classes written in C may implement alloc to have a single allocation and must then place conf_object_t first in the object data structure. This has the advantage of allowing casts directly from a conf_object_t * to a pointer to the user structure instead of using SIM_object_data. The alloc method can fail, e.g. if memory allocation fails, and signals this by returning NULL.

After alloc has run on all objects being created, the init function is called, if defined. This method should do any class specific initialization, such as initializing internal data structures. The init method may also use SIM_get_object to obtain pointers to other objects, and it can use SIM_set_attribute_default on its descendants, but it may not call interfaces on other objects, or post events. If the object instance needs additional storage, it may allocate its own memory and return a pointer to it from init. This pointer can later be obtained using SIM_object_data. However, for classes that implement their own alloc, there is no need for that, since it can be done by co-allocating the conf_object_t struct in a larger data structure, and simply return the conf_object_t pointer from init. The init method is allowed to fail, and it signals this by returning NULL.

The finalize method, if defined, is called when all attributes have been initialized in the object, and in all other objects that are created at the same time. This method is supposed to do any object initialization that require attribute values. Communication with other objects, e.g. via interfaces, should ideally be deferred until the objects_finalized method, but is permitted if SIM_require_object is first called.

The objects_finalized method, if defined, is called after finalize has been called on all objects, so in this method the configuration is ready, and communication with other objects is permitted without restrictions.

The deinit and dealloc methods are called during object destruction. The deinit method, if defined, is called first on all objects being deleted, and is supposed to do the inverse of the init method. The dealloc method is supposed to free the conf_object_t itself, i.e. it should be the inverse of alloc. It is not defined, a default dealloc method is used, which uses MM_FREE.

The delete functions may be called by Simics before an object is fully configured. That is, without any call to finalize and possibly before all the attribute set methods have been called. This may happen when the object is part of a configuration that fails to load. The SIM_object_is_configured function can be used to determine if finalize has run or not.

All functions are called in hierarchical order, starting from the root, so each object can assume that in each case, a function has already been called on all its ancestors. This can be used to e.g. set attribute default values on descendants in the init method.

If the initialization fails, i.e. if init fails, or if any attribute setter fails, then the configuration creation is rolled back. For those objects where init succeeded (or no init was defined), the deinit function will be called, and on all created objects (i.e. not ones where alloc failed) the dealloc method is called.

The description string is used to describe the class in several sentences. It is used in the help commands and reference manuals. The short_desc string is a short class description beginning with lower case, without any trailing dot, and at most 50 characters long. It is used in help commands and for example in the GUI.

conf_object_t

NAME
conf_object_t
DESCRIPTION
All objects in the Simics simulator have an associated conf_object_t struct. Pointers to conf_object_t are used in the Simics simulator API to refer to a specific object in the current Simics session. conf_object_t is an opaque data structure whose members should only be accessed using the Simics API.

data_or_instr_t

NAME
data_or_instr_t
SYNOPSIS
typedef enum {
        Sim_DI_Instruction      = 0,
        Sim_DI_Data             = 1
} data_or_instr_t;

DESCRIPTION
This type is used to differentiate between data and instruction, usually in a TBL or memory transaction context.

endianness_t

NAME
endianness_t
SYNOPSIS
typedef enum {
        Sim_Endian_Target,
        Sim_Endian_Host_From_BE,
        Sim_Endian_Host_From_LE
} endianness_t;

DESCRIPTION
Specifies the endianness to use for certain memory operations. When Sim_Endian_Target is used, the data from memory is copied without any endian conversion. Sim_Endian_Host_From_BE and Sim_Endian_Host_From_LE copies data between a big-endian, or little-endian, memory and a host buffer.

exception_type_t

NAME
exception_type_t
SYNOPSIS
typedef enum {
        SIM_PSEUDO_EXC(SIM_PSEUDO_EXC_ENUM)
} exception_type_t;

DESCRIPTION
Used to signal simulator exceptions for memory accesses. Errors usually correspond to hardware exceptions, but in some cases additional return values are needed, and then pseudo exceptions are used. The most common is Sim_PE_No_Exception, indicating that no error has occurred. Pseudo exceptions are used by devices, memory spaces, and Simics internally.
Sim_PE_No_Exception
No error.
Sim_PE_Deferred
Transaction completion is deferred via the call to SIM_defer_transaction.
Sim_PE_Async_Required
The endpoint tried to defer the transaction with SIM_defer_transaction but the transaction cannot be deferred.
Sim_PE_Cancelled
Special completion status passed to transaction_completion_t callbacks when asynchronous transactions are cancelled by Simics, for example, when simulation state is restored from a snapshot.
Sim_PE_IO_Not_Taken
Access to unmapped memory. In the PCI memory spaces interpreted as master abort.
Sim_PE_IO_Error
Accessed device returned error. In the PCI memory spaces interpreted as target abort.
Sim_PE_Inquiry_Outside_Memory
Same as Sim_PE_IO_Not_Taken, but for inquiry accesses.
Sim_PE_Execute_Outside_Memory
A processor tried to fetch instruction where no memory is defined.
Sim_PE_Inquiry_Unhandled
The accessed device does not support inquiry operations.
Sim_PE_Stall_Cpu
Timing model requested stall.
Sim_PE_Default_Semantics
Used by user decoders and user ASI handlers on SPARC to signal that the default semantics should be run.
Sim_PE_Ignore_Semantics
Used by user ASI handlers on SPARC to signal no update of destination registers.
Simics internal:
Sim_PE_Silent_Break, Sim_PE_Instruction_Finished, Sim_PE_Last.

generic_transaction_t

NAME
generic_transaction_t
DESCRIPTION
A generic_transaction_t represents a memory transaction. It should only be accessed via the accessor functions documented in Device API Functions, Core, Memory Transactions.

global_notifier_type_t

NAME
global_notifier_type_t
SYNOPSIS
typedef enum {
        Sim_Global_Notify_Object_Delete = 100,
        Sim_Global_Notify_Objects_Finalized,
        Sim_Global_Notify_Message,

        Sim_Global_Notify_Before_Snapshot_Restore = 150,
        Sim_Global_Notify_After_Snapshot_Restore,
} global_notifier_type_t;

DESCRIPTION
This enum is used to identify pre-defined global notifier. The Sim_Global_Notify_Object_Delete notifier is triggered by Simics when objects are being deleted. In the callback, objects are still fully available, but SIM_marked_for_deletion can be used to determine if an object is being deleted.

The Sim_Global_Notify_Objects_Finalized notifier is triggered by Simics when new objects have been finalized, after their objects_finalized methods have been called.

The Sim_Global_Notify_Message notifier is used by SIM_trigger_global_message.

The corresponding names used in e.g. list-notifiers are as follows:

  • "global-object-delete" (Sim_Global_Notify_Object_Delete)
  • "global-objects-finalized" (Sim_Global_Notify_Objects_Finalized)
  • "global-message" (Sim_Global_Notify_Message)

SEE ALSO
SIM_add_global_notifier, SIM_add_global_notifier_once, SIM_delete_global_notifier,

hap_type_t

NAME
hap_type_t
SYNOPSIS
typedef int hap_type_t;

DESCRIPTION
This data type is used to represent hap (occurrence) types. This is a runtime number that may change between different Simics invocations. Haps are normally identified by strings, but by calling SIM_hap_get_number(), a lookup from such a name to a hap_type_t can be made.
SEE ALSO
SIM_get_all_hap_types, SIM_hap_get_number, SIM_hap_add_type

init_arg_t

NAME
init_arg_t
SYNOPSIS
typedef struct {
        const char *name;
        bool boolean;
        union {
                const char *string;
                bool enabled;
        } u;
} init_arg_t;

DESCRIPTION
Data structure used to pass an initialization argument to the SIM_init_simulator2 function. The name field is mandatory and the associated data is either a boolean or a string (char *). A list of init_arg_t is passed to SIM_init_simulator2 where the last entry has the name field set to NULL.

int8, int16, int32, int64, uint8, uint16, uint32, uint64, intptr_t, uintptr_t

NAME
int8, int16, int32, int64, uint8, uint16, uint32, uint64, intptr_t, uintptr_t
SYNOPSIS
These data types have host-dependent definitions. Use the api-help Simics command line command to get their exact definition.
DESCRIPTION
These are basic integer data types defined by the Simics headers (unless defined by system header files).

The intn types are defined to be signed integers of exactly n bits. The uintn types are their unsigned counterparts.

intptr_t and uintptr_t are signed and unsigned integer types of a size that lets any pointer to void be cast to it and then cast back to a pointer to void, and the result will compare equal to the original pointer. This typically means that the two types are 64 bits wide.

lang_void

NAME
lang_void
SYNOPSIS
typedef void lang_void;

DESCRIPTION
In some places in the Simics API, arguments of type lang_void * are used. This data type is used to allow transparent passing of any data type in the current programming language as argument. In C, this works exactly like a void * and in Python, it is any Python object.

Typically, this is used by iterator functions in the API which take callback functions as arguments. The callback function is later called with the lang_void data and the object being iterated over.

SEE ALSO
SIM_hap_add_callback, SIM_register_typed_attribute

logical_address_t, physical_address_t, generic_address_t, linear_address_t

NAME
logical_address_t, physical_address_t, generic_address_t, linear_address_t
SYNOPSIS
These data types are target architecture independent, and always large enough to hold 64-bit addresses.
DESCRIPTION
These are integer data types defined to reflect the nature of the simulated architecture.

logical_address_t is an unsigned integer sufficiently large to contain logical (virtual) addresses on the target machine.

physical_address_t is an unsigned integer sufficiently large to contain physical addresses on the target machine.

generic_address_t is defined to be the largest of the logical_address_t and physical_address_t types.

linear_address_t is used for linear addresses used on x86 machines after segmentation but before paging.

Note that these data types are all defined to be 64-bit unsigned integers, and they can be printed by printf using the ll (ell-ell) size modifier.

map_info_t

NAME
map_info_t, swap_mode_t
SYNOPSIS
typedef enum swap_mode {
        Sim_Swap_None       = 0,
        Sim_Swap_Bus        = 1,
        Sim_Swap_Bus_Trans  = 2,
        Sim_Swap_Trans      = 3
} swap_mode_t;

typedef struct map_info {
        physical_address_t  base;
        physical_address_t  start;
        physical_address_t  length;
        int                 function;
        int16               priority;
        int                 align_size;
        swap_mode_t         reverse_endian;
} map_info_t;

DESCRIPTION
The map_info_t structure members have the following meaning:
  • base: The base address of the device mapping in the memory space.
  • start: The address inside the device memory space where the mapping starts.
  • length: The length of the mapped memory, in bytes.
  • function: Used to map the same object several times with different functionality. Corresponds to the function argument used when mapping devices into a memory space.
  • If the map target does not support large accesses, then align_size can be set to the maximum allowed size. Accesses spanning align boundaries will be split into several smaller transactions. The align size must be a power of two, or zero (which means "use the default value": 8 for devices and 8192 for memory).
  • Mappings with an align size of 2, 4, or 8 may set the reverse_endian field to a non zero value. This can be used to model bridges that perform byte swapping on a specific bus width.

If both base and length are 0 the map will become a default_target.

map_list_t

NAME
map_list_t, map_type_t
SYNOPSIS
typedef enum { 
        Sim_Map_Ram,
        Sim_Map_Rom,
        Sim_Map_IO,
        Sim_Map_Port,
        Sim_Map_Translate = 0x100, /* pseudo - do not use */
        Sim_Map_Translate_To_Space,
        Sim_Map_Translate_To_Ram,
        Sim_Map_Translate_To_Rom
} map_type_t;

typedef struct map_list {
        map_type_t       map_type;
        conf_object_t   *object;
        const char      *port;
#if !defined(PYWRAP)
        const void      *interface_ptr;
        const void      *target_interface;
        const void      *breakpoint_interface;
#if defined(SIMICS_6_API)
        const void      *breakpoint_query_interface;
#else
        const void      *breakpoint_query_v2_interface;
#endif
        const void      *bridge_interface;
#endif
        conf_object_t   *target_object;
        const char      *target_port;
        conf_object_t   *bridge;
        map_info_t       map_info;

        physical_address_t map_size; /* not constant, use with caution */

        int              deleted;  /* internal flag - should always be 0 ! */
} map_list_t;

DESCRIPTION
This data structure is used to pass information about the set of mappings a particular address in an address space contains.

map_target_t

NAME
map_target_t
SYNOPSIS
typedef struct map_target map_target_t;

DESCRIPTION
A map target can be viewed as an opaque representation of an object/interface pair which can function either as an endpoint for a memory transaction or as an address space where a memory transaction can be performed. To create a map_target_t object one should use the SIM_new_map_target function. The SIM_free_map_target function frees a map_target_t object. In order to get better performance, it is better to allocate a map target once and reuse it rather than to allocate and free it every time.

Examples of map targets include IO banks, RAM, ROM, memory spaces, port spaces, translators and bridges.

For certain targets, e.g. bridges or translators, the map target also holds information about a chained, or default, target.

PYTHON SPECIFICS
In Python, it is allowed to use arguments of the conf_object_t type with Simics API functions that have parameters of the map_target_t type. The arguments of the conf_object_t type will be converted to map_target_t values automatically, via the call to the SIM_new_map_target function. Here is an example where memory_space is a Simics object, i.e. has the conf_object_t type:
   t = transaction_t(...)
   SIM_issue_transaction(memory_space, t, addr)

In Python, the objects of the map_target_t type have read-only obj, port, and target attributes. These attributes correspond to the arguments given to SIM_new_map_target that created a map_target_t object.

SEE ALSO
SIM_new_map_target, SIM_free_map_target, SIM_map_target_object, SIM_map_target_port, SIM_map_target_target, translator_interface_t

mem_op_type_t

NAME
mem_op_type_t
SYNOPSIS
typedef enum {
        Sim_Trans_Load          = 0,
        Sim_Trans_Store         = Sim_Trn_Write,
        Sim_Trans_Instr_Fetch   = Sim_Trn_Instr,
        Sim_Trans_Prefetch      = Sim_Trn_Prefetch | Sim_Trn_Control,
        Sim_Trans_Cache         = Sim_Trn_Control
} mem_op_type_t;

DESCRIPTION
This enum is used to identify the type of a memory operation. The function SIM_get_mem_op_type() returns the type of a generic_transaction_t, and SIM_set_mem_op_type() is used to set it.
SEE ALSO
SIM_get_mem_op_type, SIM_set_mem_op_type, SIM_get_mem_op_type_name generic_transaction_t,

notifier_type_t

NAME
notifier_type_t
SYNOPSIS
/* Note that notifier types can be added either by modifying this enum or
   by using SIM_notifier_type. The latter is typically preferred since it does
   not change the Simics API. */
typedef enum {
        Sim_Notify_Queue_Change,
        Sim_Notify_Cell_Change,
        Sim_Notify_Frequency_Change,
        Sim_Notify_Concurrency_Change,
        Sim_Notify_Object_Delete,
        Sim_Notify_Map_Change,
        Sim_Notify_State_Change,
        Sim_Notify_Freerunning_Mode_Change,
        Sim_Notify_Bank_Register_Value_Change,
} notifier_type_t;

DESCRIPTION
Values of the notifier_type_t type identify notification events. A notifier_type_t value should be obtained from the SIM_notifier_type function and can then be used in other functions such as SIM_register_notifier, SIM_add_notifier, SIM_notify.

A few notification events have predefined (constant) values. They are listed below where a notifier type in the form of a string (as accepted by SIM_notifier_type) is followed by the constant of the notifier_type_t type corresponding to the notification event (as returned by SIM_notifier_type):

  • "queue-change" (Sim_Notify_Queue_Change)
  • "cell-change" (Sim_Notify_Cell_Change)
  • "frequency-change" (Sim_Notify_Frequency_Change)
  • "concurrency-change" (Sim_Notify_Concurrency_Change)
  • "object-delete" (Sim_Notify_Object_Delete)
  • "map-change" (Sim_Notify_Map_Change)
  • "state-change" (Sim_Notify_State_Change)
  • "freerunning-mode-change" (Sim_Notify_Freerunning_Mode_Change)
  • "bank-register-value-change" (Sim_Notify_Bank_Register_Value_Change)
SEE ALSO
SIM_notify, SIM_add_notifier, SIM_register_notifier, SIM_notifier_type, SIM_describe_notifier, SIM_notifier_description

processor_mode_t

NAME
processor_mode_t
SYNOPSIS
typedef enum {
        Sim_CPU_Mode_User       = 0,
        Sim_CPU_Mode_Supervisor = 1,
        Sim_CPU_Mode_Hypervisor
} processor_mode_t;

DESCRIPTION
The processor_mode_t data type is used to specify if a CPU is running in user mode or in a privileged mode (often called supervisor mode). For processor architectures with several privilege levels, the non-user levels are all identified as Sim_CPU_Mode_Supervisor.

read_or_write_t

NAME
read_or_write_t
SYNOPSIS
typedef enum {
        Sim_RW_Read  = 0,
        Sim_RW_Write = 1
} read_or_write_t;

DESCRIPTION
Whether a memory access is a read (from memory) or a write (to memory).

set_error_t

NAME
set_error_t
SYNOPSIS
typedef enum {
        Sim_Set_Ok,
        Sim_Set_Object_Not_Found,
        Sim_Set_Interface_Not_Found,
        Sim_Set_Illegal_Value,
        Sim_Set_Illegal_Type,
        Sim_Set_Illegal_Index,
        Sim_Set_Attribute_Not_Found,
        Sim_Set_Not_Writable,

        Sim_Set_Error_Types     /* number of error types */
} set_error_t;

DESCRIPTION
The SIM_set_attribute() family of functions and the set functions registered with the SIM_register_attribute() family of functions return a set_error_t value to report success or failure.

Sim_Set_Ok
The attribute was successfully set.

Sim_Set_Object_Not_Found
The string value does not match any object name. Deprecated, use attributes of object type instead of string attributes referring to object names.

Sim_Set_Interface_Not_Found
The object value does not implement an interface required by the attribute.

Sim_Set_Illegal_Value
The value is of a legal type for the attribute, but outside the legal range.

Sim_Set_Illegal_Type
The value is of an illegal type for the attribute.

Sim_Set_Attribute_Not_Found
The object has no attribute with the specified name. Should only be returned by SIM_set_attribute() family of functions, not by attribute set functions.

Sim_Set_Not_Writable
The attribute is read-only.

Sim_Set_Error_Types
This is the number of valid error values and should not be used as an error code.

simtime_t, cycles_t, pc_step_t, nano_secs_t

NAME
simtime_t, cycles_t, pc_step_t, nano_secs_t
SYNOPSIS
typedef int64 simtime_t;

typedef simtime_t cycles_t;

typedef simtime_t pc_step_t;

typedef int64 nano_secs_t;

DESCRIPTION
These are the types used for keeping track of time in Simics.

cycles_t is used when the time is specified in cycles, pc_step_t is used when the time is specified in steps, and simtime_t is used in places where it is unknown whether the time is in steps or cycles. See the Understanding Simics Timing application note for a discussion about the difference between steps and cycles.

nano_secs_t is used to express a number of nanoseconds (10−9 seconds).

translation_t

NAME
translation_t
DESCRIPTION
The translation_t type is used for the implementation of the translator and transaction_translator interfaces. It describes the range for which the translation is valid, its target as well as translation properties.

The range for which the translation is valid is specified by the fields base and size. As a special case, if size and base are both 0, then the translation is valid for the entire address space. To allow optimizations (e.g., caching of translations) translators should return as wide ranges as possible.

The target field specifies the object and interface port which is mapped into the address range in the form of a map target. Map targets can be created using the function SIM_new_map_target. Please note that the ownership over the returned map target is not transferred to the interface caller. This means that to avoid memory leaks the reference to the map target must be kept by the implementing object, and SIM_free_map_target function should be later used to deallocate the map target. Possible map targets include IO banks, RAM, ROM, memory spaces, port spaces, bridges, and translators. The base address in the source address space is mapped to the target address returned in the start field.

A null value returned in the target field signifies that the translation cannot be done. This can happen if there is nothing mapped in the range defined by base and size (transactions directed to this region will be terminated with the pseudo exception Sim_PE_IO_Not_Taken) or if a translation valid for all requested accesses cannot be performed. In the latter case, the requestor is expected to repeat the interface call with just a single bit set in the access mask, e.g. Sim_Access_Read.

If the returned translation is not static but instead depends on e.g. a device register, then the translator can set the flags field to Sim_Translation_Dynamic. This flag indicates that the translation must not be cached. If this flag is not used, then it is the responsibility of the translator to call either SIM_map_target_flush (preferably) or SIM_translation_changed function when a previously performed translation is no longer valid.

The Sim_Translation_Ambiguous flag should not generally be used by models. It is used by Simics objects of the memory-space class to indicate an error in the memory mapping when several destinations are specified for the address.

typedef enum {
        Sim_Translation_Dynamic = 1,
        Sim_Translation_Ambiguous = 2
} translation_flags_t;

typedef struct translation {
        const map_target_t *target;  /* target of translation */

        physical_address_t base;     /* base address of translated range */
        physical_address_t start;    /* start address in mapped object */
        physical_address_t size;     /* size of translated range */

        translation_flags_t flags;
} translation_t;

SEE ALSO
SIM_map_target_flush, SIM_translation_changed

3.2.2 Model Specific Data Types

arm_device_type_t

NAME
arm_device_type_t
SYNOPSIS
typedef enum {
        Arm_DeviceType_nGnRnE = 0x0,
        Arm_DeviceType_nGnRE  = 0x1,
        Arm_DeviceType_nGRE   = 0x2,
        Arm_DeviceType_GRE    = 0x3,
        Arm_DeviceType_Unknown
} arm_device_type_t;

DESCRIPTION
Arm device memory types. Corresponds to the DeviceType pseudo code enumeration in the Armv8 A-profile Architecture Reference Manual.

arm_mem_attr_t

NAME
arm_mem_attr_t
SYNOPSIS
typedef enum {
        Arm_MemAttr_NC = 0x0, // Non-cacheable
        Arm_MemAttr_WT = 0x2, // Write-through
        Arm_MemAttr_WB = 0x3, // Write-back
        Arm_MemAttr_Unknown
} arm_mem_attr_t;

DESCRIPTION
Memory cacheability. Corresponds to the MemAttr pseudo code constants in the Armv8 A-profile Architecture Reference Manual.

arm_mem_hint_t

NAME
arm_mem_hint_t
SYNOPSIS
typedef enum {
        Arm_MemHint_No  = 0x0, // No Read-Allocate, No Write-Allocate
        Arm_MemHint_WA  = 0x1, // No Read-Allocate, Write-Allocate
        Arm_MemHint_RA  = 0x2, // Read-Allocate, No Write-Allocate
        Arm_MemHint_RWA = 0x3, // Read-Allocate, Write-Allocate
        Arm_MemHint_Unknown
} arm_mem_hint_t;

DESCRIPTION
Cache allocation hint. Corresponds to the MemHint pseudo code constants in the Armv8 A-profile Architecture Reference Manual.

arm_mem_instr_origin_t

NAME
arm_mem_instr_origin_t
SYNOPSIS
typedef enum {
        /* Normal load or store instructions */
        Instr_Normal_Arm = 0,

        /* Unprivileged memory access instructions. */
        Instr_Unprivileged_Load,
        Instr_Unprivileged_Store,

        /* Other loads/stores or cache affecting instructions */
        Instr_ldrex,
        Instr_strex,
        Instr_ldxp,
        Instr_stxp,

        /* Address translation instruction */
        Instr_At,

        /* Atomic read-modify-write instructions */
        Instr_Atomic,

        /* Cache maintenance instructions */
        Instr_Cache_Maintenance,

        /* Number of different of enum values, not a value in itself. */
        Instr_Count
} arm_mem_instr_origin_t;

DESCRIPTION
List of special memory operations that can be send by a ARM processor.

arm_mem_transient_t

NAME
arm_mem_transient_t
SYNOPSIS
typedef enum {
        Arm_Transient_True,
        Arm_Transient_False,
        Arm_Transient_Unknown
} arm_mem_transient_t;

DESCRIPTION
Transcience hint. Corresponds to the boolean used for transience by the pseudo code in the Armv8 A-profile Architecture Reference Manual.

arm_mem_type_t

NAME
arm_mem_type_t
SYNOPSIS
typedef enum {
        Arm_MemType_Normal,
        Arm_MemType_Device
} arm_mem_type_t;

DESCRIPTION
Arm memory types. Corresponds to the MemType pseudo code enumeration in the Armv8 A-profile Architecture Reference Manual.

arm_memory_attributes_encoding_t

NAME
arm_memory_attributes_encoding_t
SYNOPSIS
typedef union {
        struct {
                uint64 memory_type:2;            // arm_mem_type_t
                uint64 device_type:3;            // arm_device_type_t
                uint64 inner_cacheability:3;     // arm_mem_attr_t
                uint64 inner_allocation_hint:3;  // arm_mem_hint_t
                uint64 inner_transcience_hint:2; // arm_mem_transient_t
                uint64 outer_cacheability:3;     // arm_mem_attr_t
                uint64 outer_allocation_hint:3;  // arm_mem_hint_t
                uint64 outer_transcience_hint:2; // arm_mem_transient_t
                uint64 shareable:1;              // bool
                uint64 outer_shareable:1;        // bool
        } u;
        uint64 u64;
} arm_memory_attributes_encoding_t;

DESCRIPTION
This type should be used to encode or decode the uint64 value contained in an arm_memory_attributes atom. The comment beside each field is the type that should be used to interpret the field value.

arm_memory_transaction_t

NAME
arm_memory_transaction_t
SYNOPSIS
typedef struct arm_memory_transaction {
        generic_transaction_t s;

        processor_mode_t mode;
        int rotate;
        arm_mem_instr_origin_t instr_origin;
} arm_memory_transaction_t;

DESCRIPTION
This is the ARM specific memory transaction data structure. The generic data is stored in the s field.

The mode field specifies the processor mode the MMU should assume when processing the transaction. This is the same as the current mode of the processor except for unprivileged load and store instructions when it is always Sim_CPU_Mode_User.

The rotate field is non-zero if this transaction is from one of the AArch32 instructions for which an unaligned address is interpreted as an aligned load with the value rotated so that the addressed byte becomes the least significant byte if neither SCTLR.U nor SCTLR.A is set.

The instr_origin field specifies the type of instruction that initiated this memory transaction.

arm_smmu_attributes_t

NAME
arm_smmu_attributes_t
SYNOPSIS
typedef union {
        struct {
                uint64 sid:32;    // IMPLEMENTATION DEFINED size, between 0 and 32 bits
                uint64 ssid:20;   // IMPLEMENTATION DEFINED size, between 0 and 20 bits
                uint64 secsid:1;  // bool
                uint64 ssidv:1;   // bool
                uint64 atst:1;    // bool
        } u;
       uint64 u64;
} arm_smmu_attributes_t;

DESCRIPTION
This type should be used to encode or decode the uint64 value contained in an arm_smmu_attributes atom. The comment beside each field is the type that should be used to interpret the field value.

arm_translation_regime_t

NAME
arm_translation_regime_t
SYNOPSIS
typedef enum {
        Arm_TR_EL3,  /* EL3         */
        Arm_TR_EL2,  /* EL2   PL2   */
        Arm_TR_EL20, /* EL2&0       */
        Arm_TR_EL10, /* EL1&0 PL1&0 */
} arm_translation_regime_t;

,

DESCRIPTION
Arm MMU translation regimes. Named after the AArch64 translation regimes, but also used for the AArch32 ones.

i2c_status_t

NAME
i2c_status_t
SYNOPSIS
typedef enum {
        /* The ACK bit related to the operation was 0. This typically
           means that the operation was successful */
        I2C_status_success = 0,
        /* The ACK bit related to the operation was 1. This typically
           means that the operation was unsuccessful */
        I2C_status_noack = 1,
        /* The operation could not be carried out, because the link is
           currently in use by another master */
        I2C_status_bus_busy
} i2c_status_t;

DESCRIPTION
The i2c_status_t type is used to communicate the results of various operations on the I2C link. The type is an enum, with the values I2C_status_success, I2C_status_noack and I2C_status_bus_busy.

The i2c_status_t type typically represents an ACK bit; in this case I2C_status_success corresponds to 0, and I2C_status_noack corresponds to 1. In the start_response function of the i2c_master interface, the i2c_status_t parameter is additionally allowed to take the value I2C_status_bus_busy, meaning that the start failed since some other master is active using the i2c link. The value I2C_status_bus_busy is disallowed in all other function parameters in the i2c_link, i2c_slave and i2c_master interfaces.

SEE ALSO
i2c_link_interface_t, i2c_master_interface_t, i2c_slave_interface_t

interrupt_source_t

NAME
interrupt_source_t
SYNOPSIS
typedef enum {
        Interrupt_Source_Icr_Ipr,
        Interrupt_Source_Msi,
        Interrupt_Source_Virtual_Wire,
        Interrupt_Source_Nmi_Pin,
        Interrupt_Source_Lvt,
        Interrupt_Source_Iommu,
        Interrupt_Source_Int2,
        Interrupt_Source_Vmcs_Injection,
        Interrupt_Source_Legacy_Apic_Vector,
        Interrupt_Source_Self_Ipi,
        Interrupt_Source_Unknown,
} interrupt_source_t;

DESCRIPTION
Sources of interrupts.
  • Interrupt_Source_Icr_Ipr means that the source is the Interrupt Control Register - Inter Processor Interrupt.
  • Interrupt_Source_Msi means that the source is an MSI.
  • Interrupt_Source_Virtual_Wire means that the source is the Virtual Wire.
  • Interrupt_Source_Nmi_Pin means that the source is the external NMI pin.
  • Interrupt_Source_Lvt means that the source is the local vector table (LVT).
  • Interrupt_Source_Iommu means that the source is the IOMMU.
  • Interrupt_Source_Int2 means that the source is the INT2 instruction.
  • Interrupt_Source_Vmcs_Injection means that the source is an interrupt injected through the VMCS.
  • Interrupt_Source_Legacy_Apic_Vector means that the source is the legacy APIC interrupt vector.
  • Interrupt_Source_Self_Ipi means that the source is the SELF IPI Register.
  • Interrupt_Source_Unknown means that the source is unknown.
SEE ALSO
interrupt_subscriber_interface_t

mips_memory_transaction_t

NAME
mips_memory_transaction_t
SYNOPSIS
typedef struct mips_memory_transaction {

        /* generic transaction */
        generic_transaction_t s;

        /* Cache coherency, values as the C field in EntryLo0 and EntryLo1. */
        unsigned int cache_coherency:3;
} mips_memory_transaction_t;

DESCRIPTION
This is the MIPS specific memory transaction data structure. The generic data is stored in the s field.

The cache_coherency field specifies the cache coherency attribute of the memory transaction, as defined by the C field of the EntryLo0 and EntryLo1 coprocessor 0 registers.

nios_memory_transaction_t

NAME
nios_memory_transaction_t
SYNOPSIS
typedef struct nios_memory_transaction {
        /* generic transaction */
        generic_transaction_t s;
} nios_memory_transaction_t;

DESCRIPTION
The s field contains generic information about memory operations (see generic_transaction_t).

pci_memory_transaction_t

NAME
pci_memory_transaction_t
SYNOPSIS
typedef struct pci_memory_transaction {
        generic_transaction_t INTERNAL_FIELD(s);
        uint32 INTERNAL_FIELD(original_size);

        int INTERNAL_FIELD(bus_address);

        int INTERNAL_FIELD(bus_number);
        int INTERNAL_FIELD(device_number);
        int INTERNAL_FIELD(function_number);

        uint32 INTERNAL_FIELD(tlp_prefix);
} pci_memory_transaction_t;

DESCRIPTION
The pci_memory_transaction_t is used for memory accesses initiated by PCI devices.

Note: All struct fields are internal and should never be used directly.
A generic_transaction_t can be converted to a pci_memory_transaction_t via the SIM_pci_mem_trans_from_generic() function. Never explicitly cast one struct to the other, always use the Simics API functions.
SEE ALSO
SIM_pci_mem_trans_from_generic, generic_transaction_t

ppc_mem_instr_origin_t

NAME
ppc_mem_instr_origin_t
SYNOPSIS
typedef enum {
        /* Normal load or store instructions */
        Normal_Load_Store = 0,

        /* No data touched by the load/store will be placed in cache */
	Caching_Inhibited,

        Instr_Multiple,         /* load/store multiple */
        Instr_String,           /* load/store string */

        Instr_Altivec_Element,  /* Altivec load/store element */

        /* Data cache manipulations */
        Instr_dcbt,             /* data cache block touch */
        Instr_dcbst,            /* data cache block store */
        Instr_dcbtst,           /* data cache block touch for store */
        Instr_dcbi,             /* data cache block invalidate */
        Instr_dcbf,             /* data cache block flush */
        Instr_dcbfl,            /* data cache block flush local */
        Instr_dcba,             /* data cache block allocate */
        Instr_dcbz,             /* data cache block to zero */
        
        /* Instruction cache manipulations */
        Instr_icbi,             /* instruction cache block invalidate */
        
        /* Data stream (Altivec) manipulations */
        Instr_dst,              /* data stream touch */
        Instr_dstt,             /* data stream touch transient */
        Instr_dstst,            /* data stream touch for store */
        Instr_dststt,           /* data stream touch for store transient */

        /* e500 cache lock apu instructions */
        Instr_dcblc_l1,         /* data cache block lock clear (L1) */
        Instr_dcblc_l2,         /* data cache block lock clear (L2) */
        Instr_dcbtls_l1,        /* data cache block touch and lock set (L1)*/
        Instr_dcbtls_l2,        /* data cache block touch and lock set (L1)*/
        Instr_dcbtstls_l1,      /* data cache block touch for store and lock
                                   set (L1)*/
        Instr_dcbtstls_l2,      /* data cache block touch for store and lock
                                   set (L1)*/
        Instr_icblc_l1,         /* instruction cache block clear (L1) */
        Instr_icblc_l2,         /* instruction cache block clear (L2) */
        Instr_icbtls_l1,        /* instruction cache block touch and lock
                                   set (L1) */
        Instr_icbtls_l2,        /* instruction cache block touch and lock
                                   set (L1) */

        /* Other loads/stores or cache affecting instructions */
        Instr_lwarx,
        Instr_stwcx,
        Instr_ldarx,
        Instr_stdcx,
        Instr_lq,
        Instr_stq,

        /* Other cache affecting instructions */
        Instr_sync,
        Instr_eieio,
        Instr_ecowx,
        Instr_eciwx,
        Instr_tlbie,
        Instr_tlbsync,
        Instr_isync,

        Instr_lfdp,             /* Load Floating point Double Pair */
        Instr_stfdp,            /* Store Floating point Double Pair */

        Instr_spe,

        Instr_dcbal,            /* Obsolete - use Instr_dcba. */

        /* e500 cache lock apu instructions, platform cache versions */
        Instr_dcblc_pc,         /* data cache block lock clear */
        Instr_dcbtls_pc,        /* data cache block touch and lock set*/
        Instr_dcbtstls_pc,      /* data cache block touch for store and lock
                                   set */
        Instr_icblc_pc,         /* instruction cache block clear */
        Instr_icbtls_pc,        /* instruction cache block touch and lock
                                   set */
        Instr_Fpu               /* Load/store from FPU unit */
} ppc_mem_instr_origin_t;

DESCRIPTION
List of special memory operations that can be send by a PPC processor.

ppc_memory_transaction_t

NAME
ppc_memory_transaction_t
SYNOPSIS
typedef struct ppc_memory_transaction {

        /* generic transaction */
        generic_transaction_t s;

        processor_mode_t mode;
        ppc_mem_instr_origin_t instr_origin;
        logical_address_t ea_origin;
	uint8 wimg;
        uint8 alignment;

        /* cache operations may flag this to cause prefetches to be no-ops */
        uint8 inhibit_exception;

        /* External PID */
        uint8 external_pid;

        /* Decorated storage */
        ppc_decoration_t decoration;
} ppc_memory_transaction_t;

DESCRIPTION
This is the PPC specific memory transaction data structure. The generic data is stored in the s field.

The current processor mode when generating this transaction is stored in the mode field.

The type of instruction generating the memory transactions is provided by the instr_origin field. Note that it is mainly provided for special memory accesses like cache block operations..

The wimg field is filled in by the MMU with the corresponding WIMG bits during the translation.

The alignment field contains the size on which the transaction is required to be aligned.

The inhibit_exception field is set for operations that should be ignored if triggering an exception.

The external_pid field is only used internally for some Book-E cores. It is undefined for cores which do not have this feature.

decoration contains decoration data.

typedef struct {
        ppc_decoration_type_t type;
        uint64 data;
} ppc_decoration_t;

The type field specifies whether the transaction is decorated or not, and if it is, the decoration type. It will be one of:

typedef enum {
        Decoration_None,
        Decoration_Notify,
        Decoration_Load,
        Decoration_Store
} ppc_decoration_type_t;

The data field holds the decoration data supplied by the instruction. It is only valid if type is not Decoration_None.

Note that not all processors implement decorated storage.

riscv_cpu_mode_t

NAME
riscv_cpu_mode_t
SYNOPSIS
typedef enum {
        Riscv_Mode_User            = 0x0,
        Riscv_Mode_Supervisor      = 0x1,
        Riscv_Mode_Reserved        = 0x2,
        Riscv_Mode_Machine         = 0x3,

        Riscv_Mode_Guest_User       = 0x10,
        Riscv_Mode_Guest_Supervisor = 0x11
} riscv_cpu_mode_t;

DESCRIPTION
List of privilege levels of the RISC-V core.

serial_peripheral_interface_flags_t

NAME
serial_peripheral_interface_flags_t
SYNOPSIS
typedef enum serial_peripheral_interface_flags {
        SPI_Flags_CPHA = 0x1,
        SPI_Flags_CPOL = 0x2
} serial_peripheral_interface_flags_t;

DESCRIPTION
The serial_peripheral_interface_flags_t type is used to describe some properties of an SPI connection. The type is a bitfield, currently defining two values, CPOL and CPHA. If a master device connects to a slave using a CPOL/CPHA combination incompatible with the slave device, then the results of any SPI transfer are undefined.

The SPI_Flags_CPOL bit defines the polarity of the clock pin (SCK): A value of zero means that the pin is low when the bus is idle, while a value of one means that the pin is high when the bus is idle.

The SPI_Flags_CPHA bit defines the phase of the clock pin. If the CPHA and CPOL bits are equal, data bits are read on the falling edge of the SCK pin and changed on the rising edge of the pin; if the bits are not equal, data bits are read on the rising edge and changed on the falling edge of the SCK pin.

SEE ALSO
serial_peripheral_interface_slave_interface_t

usb_transfer_t

NAME
usb_transfer_t
SYNOPSIS
typedef enum {
        USB_Transfer_Completed,
        USB_Transfer_Not_Ready
} usb_transfer_completion_t;

typedef enum {
        USB_Direction_None,
        USB_Direction_In,
        USB_Direction_Out
} usb_direction_t;

typedef enum {
        USB_Status_Undef,
        USB_Status_Ack,
        USB_Status_Nak,
        USB_Status_Stall
} usb_status_t;

typedef enum {
        USB_Type_Control,
        USB_Type_Interrupt,
        USB_Type_Isochronous,
        USB_Type_Bulk
} usb_type_t;

typedef enum {
        USB_Speed_Low,
        USB_Speed_Full,
        USB_Speed_High
} usb_speed_t;

typedef struct {
        uint8  bmRequestType;
        uint8  bRequest;
        uint16 wValue;
        uint16 wIndex;
        uint16 wLength;
} usb_device_request_t;

typedef struct {
        /* Endpoint/function specific information */
        uint8                 function_address;
        uint8                 endpoint_number;
        /* Type specific information */
        usb_type_t            type;
#ifndef PYWRAP
        union {
                usb_device_request_t   control_request;
                nano_secs_t            periodic_time;
        } u;
#endif /* PYWRAP */
        /* Data specific */
        usb_direction_t       direction;
        int                   size;
        dbuffer_t             *buf;
        /* Status */
        usb_status_t          status;
} usb_transfer_t;

DESCRIPTION
All USB related data types are Simics internal, and should not be used by user-defined classes. The data types may change in future versions of Simics.

The usb_transfer_t type is independent of USB host and USB device implementations and is used for sending data over USB.

There are two fields to identify the pipe: function_address is the function/device address for the target USB device; endpoint_number specifies the endpoint number.

The type of transfer is defined using the type field. The type is either control, bulk, interrupt, or isochronous. The u.control_request field is only valid for control transfers. It contains the information that would be in the setup packet of a control transfer. The u.periodic_time field is only valid for periodic transfers, i.e., interrupt and isochronous transfers. It specifies the minimum response time for a transfer expected by the USB host. A USB device do not need to fulfill the expectation. It is merely a way to tell the USB device how to keep the timing specified in the periodic list scheduling.

The usb_direction field specifies the direction of the data in the USB transfer. Only the actual data packet is used to specify the direction, even if a real transfer consists of a mix of SETUP/OUT/IN/STATUS packets. USB_Direction_None means that the transfer does not contain any data, for example, in Set_Address control transfers. size is the number of bytes the USB host can receive for IN transfers and the number of bytes sent for OUT transfers. buf contains the IN or OUT data. Note that buf can contain data for several data packets concatenated together. The endpoint descriptors in USB host and USB device define the maximum packet size for the pipe, but there is no limitation in Simics.

The status field contains the status for the transfer. The status is typically only set by the USB device. The USB host does not set the status field when it has completed an IN transfer.

x86_execution_mode_t

NAME
x86_execution_mode_t
SYNOPSIS
typedef struct x86_execution_mode {
        uint64 ac:1,
               seam:1,
               sgx:1,
               smm:1,
               vmx_root:1,
               vmx_non_root:1;
} x86_execution_mode_t;

DESCRIPTION
Processor execution mode for x86. Used by x86_execution_mode_interface_t interface.

x86_memory_transaction_t

NAME
x86_memory_transaction_t
SYNOPSIS
typedef struct x86_memory_transaction {
        generic_transaction_t s;                /* Superclass */
        linear_address_t      linear_address;   
        physical_address_t    guest_physical_address;
        uint16                segnum;           /* segment number */
        uint16                access_linear:1;  /* Linear access */
        uint16                io:1;             /* I/O (port) access */
        uint16                fault_as_if_write:1;
        uint16                guest_phys_valid:1;
        processor_mode_t      mode;
        x86_access_type_t     access_type;
        x86_memory_type_t     pat_type;
        x86_memory_type_t     mtrr_type;
        x86_memory_type_t     effective_type;
        int                   sequence_number; /* used for -stall */
} x86_memory_transaction_t;

DESCRIPTION
The s field contains generic information about memory operations (see generic_transaction_t).

The mode is the current mode (user or supervisor) of the cpu.

The linear_address contains the address for transactions with linear addresses.

The access_linear flag is set for all transactions with linear addresses.

The io flag is set on port accesses (from IN and OUT instructions). It is cleared for regular memory accesses, and also for memory mapped I/O.

The fault_as_if_write flag indicates that an access should set the page fault access bits as a write even if the access is a read.

The access_type field contains the type of the transaction. See online help for expanded output of this type: api-help x86_access_type_t

typedef enum x86_access_type {
        FOR_X86_ACCESS_TYPES(X86_ACCESS_TYPE_ENUM)
} x86_access_type_t;

The effective memory type for the access is contained in effective_type. The MMU calculates the effective memory type and uses the pat_type and mtrr_type members as temporary storage and input to that calculation. The pat_type and mtrr_type members should not be used by code outside of the MMU.

typedef enum {
        X86_None,
        X86_Strong_Uncacheable,    /* UC */
        X86_Uncacheable,           /* UC- */
        X86_Write_Combining,       /* WC */
        X86_Write_Through,         /* WT */
        X86_Write_Back,            /* WB */
        X86_Write_Protected        /* WP */
} x86_memory_type_t;

x86_sync_instruction_type_t

NAME
x86_sync_instruction_type_t
SYNOPSIS
typedef enum {
        X86_SFence = 1,
        X86_LFence = 2,
        X86_MFence = 3
} x86_sync_instruction_type_t;

DESCRIPTION
Type of synchronisation instruction for x86. Used in the Core_Sync_Instruction hap.

xtensa_memory_transaction_t

NAME
xtensa_memory_transaction_t
SYNOPSIS
typedef struct xtensa_memory_transaction {
        /* generic transaction */
        generic_transaction_t s;
} xtensa_memory_transaction_t;

DESCRIPTION
The s field contains generic information about memory operations (see generic_transaction_t).

3.2.3 Internal Data Types

Collection of Internal Data Types

NAME
addr_type_t, byte_string_t, struct ether_addr, event_queue_type_t, icode_mode_t, image_spage_t, instruction_trace_callback_t, intervals_func_t, interval_set_t, interval_set_iter_t, os_time_t, struct os_tm, page_info_t, prof_data_t, prof_data_address_t, prof_data_counter_t, prof_data_iter_t, rand_state_t, range_node_t, sim_ic_type_t, simics_internal_counters_t, socket_t, state_save_kind_t, strbuf_t, struct simcontext, vtmem_inform_opcode_t
DESCRIPTION
These data types are exported for Simics internal use.

3.3 Device API Functions

Attribute Values

SIM_alloc_attr_dict()

NAME
SIM_alloc_attr_dict — create empty attribute dictionary
SYNOPSIS
attr_value_t
SIM_alloc_attr_dict(unsigned length);

DESCRIPTION
Returns an attr_value_t of type dict with size len. The dictionary elements are initialized to invalid values.
EXECUTION CONTEXT
All contexts (including Threaded Context)
SEE ALSO
SIM_attr_dict_set_item, SIM_alloc_attr_list

SIM_alloc_attr_list()

NAME
SIM_alloc_attr_list — create uninitialized attribute list
SYNOPSIS
attr_value_t
SIM_alloc_attr_list(unsigned length);

DESCRIPTION
Returns an attr_value_t of type list with size length. The list elements are initialized to invalid values.
EXECUTION CONTEXT
All contexts (including Threaded Context)
SEE ALSO
SIM_make_attr_list, SIM_attr_list_set_item

SIM_attr_copy()

NAME
SIM_attr_copy — copy attribute value
SYNOPSIS
attr_value_t
SIM_attr_copy(attr_value_t val);

DESCRIPTION
Return a deep copy of val. The caller obtains ownership of the copy and needs to free it after use; the argument is not modified.

This function is not available from Python.

EXECUTION CONTEXT
All contexts (including Threaded Context)
SEE ALSO
SIM_attr_free

SIM_attr_dict_resize()

NAME
SIM_attr_dict_resize — resize dict attribute value
SYNOPSIS
void
SIM_attr_dict_resize(attr_value_t *NOTNULL attr, unsigned newsize);

DESCRIPTION
Resize attr, which must be of dict type, to newsize elements. New elements are marked invalid. Dropped elements are freed.
EXECUTION CONTEXT
Cell Context

SIM_attr_dict_set_item()

NAME
SIM_attr_dict_set_item — set dict attribute element
SYNOPSIS
void
SIM_attr_dict_set_item(attr_value_t *NOTNULL attr, unsigned index,
                       attr_value_t key, attr_value_t value);

DESCRIPTION
Set the element numbered index of the dict attr to key and value. The previous key and value at that position are freed. The ownership for key and value is transferred from the caller to attr. The key must be of integer, string or object type.
EXECUTION CONTEXT
Cell Context

SIM_attr_free()

NAME
SIM_attr_free, SIM_free_attribute — free attribute
SYNOPSIS
void
SIM_attr_free(attr_value_t *NOTNULL value);

void
SIM_free_attribute(attr_value_t value);

DESCRIPTION
Free the memory allocation used by the value pointed to by value. For values of list or dict type, this recursively frees all contents; for string or data values, the allocation containing the payload is freed. It is an error to use the value or any sub-part of it after it has been freed.

SIM_attr_free is the preferred call because it changes the type of the argument variable to Invalid, preventing accidental use after freeing. SIM_free_attribute only differs in how the argument is passed, but cannot change the argument variable as it is passed by value.

Note: These functions are not available in Python; memory allocation is managed automatically there.
EXECUTION CONTEXT
All contexts (including Threaded Context)

SIM_attr_integer()

NAME
SIM_attr_integer, SIM_attr_boolean, SIM_attr_string, SIM_attr_string_detach, SIM_attr_floating, SIM_attr_object, SIM_attr_object_or_nil, SIM_attr_data_size, SIM_attr_data, SIM_attr_list_size, SIM_attr_list_item, SIM_attr_list, SIM_attr_dict_size, SIM_attr_dict_key, SIM_attr_dict_value — extract values stored in attr_value_t values
SYNOPSIS
FORCE_INLINE int64
SIM_attr_integer(attr_value_t attr);

FORCE_INLINE bool
SIM_attr_boolean(attr_value_t attr);

FORCE_INLINE const char *
SIM_attr_string(attr_value_t attr);

FORCE_INLINE char *
SIM_attr_string_detach(attr_value_t *attr);

FORCE_INLINE double
SIM_attr_floating(attr_value_t attr);

FORCE_INLINE conf_object_t *
SIM_attr_object(attr_value_t attr);

FORCE_INLINE conf_object_t *
SIM_attr_object_or_nil(attr_value_t attr);

FORCE_INLINE unsigned
SIM_attr_data_size(attr_value_t attr);

FORCE_INLINE const uint8 *
SIM_attr_data(attr_value_t attr);

FORCE_INLINE unsigned
SIM_attr_list_size(attr_value_t attr);

FORCE_INLINE attr_value_t
SIM_attr_list_item(attr_value_t attr, unsigned index);

FORCE_INLINE attr_value_t *
SIM_attr_list(attr_value_t attr);

FORCE_INLINE unsigned
SIM_attr_dict_size(attr_value_t attr);

FORCE_INLINE attr_value_t
SIM_attr_dict_key(attr_value_t attr, unsigned index);

FORCE_INLINE attr_value_t
SIM_attr_dict_value(attr_value_t attr, unsigned index);

DESCRIPTION
Extract a value encapsulated in attr. It is an error to call an accessor function with an attr of the wrong type.

SIM_attr_integer returns the integer attribute value modulo-reduced to the interval [−263,263−1]. (Converting the return value to uint64 gives the integer attribute value modulo-reduced to [0,264−1].)

SIM_attr_string, SIM_attr_data and SIM_attr_list return values owned by attr. Ownership is not transferred to the caller.

SIM_attr_string_detach returns the string in attr and changes the value pointed to by attr into a nil attribute. Ownership of the string is transferred to the caller.

SIM_attr_object_or_nil accepts an attr parameter of either object or nil type. In case of a nil attribute, the function returns NULL.

SIM_attr_list_size and SIM_attr_dict_size return the number of items in the list and key-value pairs in the dict respectively. SIM_attr_data_size returns the number of bytes in the data value.

SIM_attr_list_item returns the item at index. The index must be less than the number of items in the list. The item returned is still owned by attr. Ownership is not transferred to the caller.

SIM_attr_list returns a pointer directly into the internal array of the attribute value; it is mainly present as an optimisation. Use SIM_attr_list_item and SIM_attr_list_set_item for type-safety instead.

SIM_attr_dict_key and SIM_attr_dict_value return the key and value at index. The index must be less than the number of items in the dict. The value returned is still owned by attr. Ownership is not transferred to the caller.

EXECUTION CONTEXT
All contexts (including Threaded Context)

SIM_attr_is_integer()

NAME
SIM_attr_is_integer, SIM_attr_is_boolean, SIM_attr_is_string, SIM_attr_is_floating, SIM_attr_is_object, SIM_attr_is_invalid, SIM_attr_is_data, SIM_attr_is_list, SIM_attr_is_dict, SIM_attr_is_nil, SIM_attr_is_int64, SIM_attr_is_uint64attr_value_t type predicates
SYNOPSIS
FORCE_INLINE bool
SIM_attr_is_integer(attr_value_t attr);

FORCE_INLINE bool
SIM_attr_is_boolean(attr_value_t attr);

FORCE_INLINE bool
SIM_attr_is_string(attr_value_t attr);

FORCE_INLINE bool
SIM_attr_is_floating(attr_value_t attr);

FORCE_INLINE bool
SIM_attr_is_object(attr_value_t attr);

FORCE_INLINE bool
SIM_attr_is_invalid(attr_value_t attr);

FORCE_INLINE bool
SIM_attr_is_data(attr_value_t attr);

FORCE_INLINE bool
SIM_attr_is_list(attr_value_t attr);

FORCE_INLINE bool
SIM_attr_is_dict(attr_value_t attr);

FORCE_INLINE bool
SIM_attr_is_nil(attr_value_t attr);

FORCE_INLINE bool
SIM_attr_is_int64(attr_value_t attr);

FORCE_INLINE bool
SIM_attr_is_uint64(attr_value_t attr);

DESCRIPTION
Indicates whether the value stored in attr is of the specified type. SIM_attr_is_int64 and SIM_attr_is_uint64 additionally test whether the integer value would fit in the given C type.
EXECUTION CONTEXT
Cell Context

SIM_attr_list_resize()

NAME
SIM_attr_list_resize — resize list attribute value
SYNOPSIS
void
SIM_attr_list_resize(attr_value_t *NOTNULL attr, unsigned newsize);

DESCRIPTION
Resize attr, which must be of list type, to newsize elements. New elements are set to invalid value. Dropped elements are freed.
EXECUTION CONTEXT
Cell Context

SIM_attr_list_set_item()

NAME
SIM_attr_list_set_item — set list attribute element
SYNOPSIS
void
SIM_attr_list_set_item(attr_value_t *NOTNULL attr, unsigned index,
                       attr_value_t elem);

DESCRIPTION
Set the element numbered index of the list attr to elem. The previous value at that position is freed. The ownership for elem is transferred from the caller to attr.
EXECUTION CONTEXT
Cell Context

SIM_attr_scanf()

NAME
SIM_attr_scanf, SIM_ascanf — parse list attribute values
SYNOPSIS
bool
SIM_attr_scanf(attr_value_t *NOTNULL list, const char *NOTNULL fmt, ...);

bool
SIM_ascanf(attr_value_t *NOTNULL list,
           const char *NOTNULL fmt, ...) __attribute__((alias("SIM_attr_scanf")));

DESCRIPTION
Reads and converts entries in list according to the format string fmt. Returns true if all elements were successfully converted, false otherwise.

The characters in the format string mean:

format char argument type element must be
i int64 * integer
b int * boolean
f double * floating
s const char ** string
S const char ** string or nil
o conf_object_t ** object
O conf_object_t ** object or nil
l attr_value_t ** list
d attr_value_t ** data
a attr_value_t ** any except invalid

The fmt string may also include a period (.) at the end, taken to mean that more elements may follow. If the period is not present, the length of the list must equal the number of specified elements.

Converted values of type attr_value_t * and const char * are still owned by list.

SIM_ascanf is an alias of SIM_attr_scanf and will be deprecated.

EXECUTION CONTEXT
All contexts (including Threaded Context)

SIM_make_attr_boolean()

NAME
SIM_make_attr_boolean — make boolean attribute
SYNOPSIS
FORCE_INLINE attr_value_t
SIM_make_attr_boolean(bool b);

DESCRIPTION
Returns an attr_value_t of boolean type.
EXECUTION CONTEXT
Cell Context

SIM_make_attr_data()

NAME
SIM_make_attr_data, SIM_make_attr_data_adopt — create raw data attribute
SYNOPSIS
attr_value_t
SIM_make_attr_data(size_t size, const void *data);

FORCE_INLINE attr_value_t
SIM_make_attr_data_adopt(size_t size, void *data);

DESCRIPTION
Returns an attr_value_t of type data using size and data for the binary data. The maximum size of the binary data is 2**32-1 bytes, i.e. size should fit into a 32-bit unsigned integer.

SIM_make_attr_data will make a copy of the argument data.

SIM_make_attr_data_adopt is mainly provided for compatibility; it will assume ownership of the argument data, which must have been allocated using one of the MM_MALLOC functions.

EXECUTION CONTEXT
All contexts (including Threaded Context)

SIM_make_attr_floating()

NAME
SIM_make_attr_floating — make floating point attribute
SYNOPSIS
FORCE_INLINE attr_value_t 
SIM_make_attr_floating(double d);

DESCRIPTION
Returns an attr_value_t of floating type with value d.
EXECUTION CONTEXT
Cell Context

SIM_make_attr_int64()

NAME
SIM_make_attr_int64, SIM_make_attr_uint64 — make integer attribute
SYNOPSIS
FORCE_INLINE attr_value_t
SIM_make_attr_int64(int64 i);

FORCE_INLINE attr_value_t
SIM_make_attr_uint64(uint64 i);

DESCRIPTION
Returns an attr_value_t of integer type with value i.
EXECUTION CONTEXT
Cell Context

SIM_make_attr_invalid()

NAME
SIM_make_attr_invalid — make invalid attribute
SYNOPSIS
FORCE_INLINE attr_value_t
SIM_make_attr_invalid(void);

DESCRIPTION
Returns an attr_value_t of invalid type.
EXECUTION CONTEXT
Cell Context

SIM_make_attr_list()

NAME
SIM_make_attr_list, SIM_make_attr_list_vararg — make list attribute
SYNOPSIS
attr_value_t
SIM_make_attr_list(unsigned length, ...);

attr_value_t
SIM_make_attr_list_vararg(unsigned length, va_list va);

DESCRIPTION
Returns an attr_value_t of type list with size length. The list is filled with data from the arguments following, which should be of type attr_value_t.

This function must be called with exactly length+1 arguments. The attribute parameters should all be valid attributes; e.g., attributes of invalid type are not allowed. The length argument must be a constant expression.

The newly created list assumes ownership of the passed parameters, which therefore should not be freed.

EXECUTION CONTEXT
All contexts (including Threaded Context)
SEE ALSO
SIM_alloc_attr_list

SIM_make_attr_nil()

NAME
SIM_make_attr_nil — make nil attribute
SYNOPSIS
FORCE_INLINE attr_value_t
SIM_make_attr_nil(void);

DESCRIPTION
Returns an attr_value_t of type nil.
EXECUTION CONTEXT
Cell Context

SIM_make_attr_object()

NAME
SIM_make_attr_object — make object attribute
SYNOPSIS
FORCE_INLINE attr_value_t
SIM_make_attr_object(conf_object_t *obj);

DESCRIPTION
Returns an attr_value_t of object type with value obj. Returns a nil value if obj is NULL.
EXECUTION CONTEXT
Cell Context

SIM_make_attr_string()

NAME
SIM_make_attr_string, SIM_make_attr_string_adopt — make string attribute
SYNOPSIS
attr_value_t
SIM_make_attr_string(const char *str);

FORCE_INLINE attr_value_t
SIM_make_attr_string_adopt(char *str);

DESCRIPTION
Returns an attr_value_t of type string with value str. Returns Nil if str is NULL.

SIM_make_attr_string will make a copy of the argument string.

SIM_make_attr_string_adopt is mainly provided for compatibility; it will assume ownership of the argument string, which must have been allocated using one the MM_MALLOC functions.

EXECUTION CONTEXT
All contexts (including Threaded Context)

Configuration

SIM_attribute_error()

NAME
SIM_attribute_error, SIM_c_attribute_error — specify reason for attribute error
SYNOPSIS
void
SIM_attribute_error(const char *NOTNULL msg);

void
SIM_c_attribute_error(const char *NOTNULL msg, ...);

DESCRIPTION
When used inside an attribute set_attr/get_attr method, indicates why it failed to set or retrieve the attribute. This function only serves to give an informative message to the user. The object or attribute names need not be mentioned in the msg argument; Simics will supply this automatically. SIM_c_attribute_error is similar but the msg argument and those following it are used for string formatting in the same way as in the standard sprintf function. This function is not available from Python.

The error message supplied will be attached to any frontend exception generated by the attribute access.

EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_register_attribute, SIM_get_attribute, SIM_set_attribute

SIM_class_port()

NAME
SIM_class_port — check if class has specified port object
SYNOPSIS
conf_class_t *
SIM_class_port(const conf_class_t *NOTNULL cls, const char *NOTNULL name);

DESCRIPTION
Returns the class of objects on the port named name, or NULL if no such port is registered.
SEE ALSO
SIM_register_port, SIM_register_simple_port
EXECUTION CONTEXT
Cell Context

SIM_copy_class()

NAME
SIM_copy_class — create a copy of an existing class
SYNOPSIS
conf_class_t *
SIM_copy_class(const char *NOTNULL name, const conf_class_t *NOTNULL src_cls,
               const char *desc);

DESCRIPTION
This function creates a copy of the class src_class named name.

Additional attributes and interfaces can be registered on the newly created class.

The new class is described by desc unless this parameter is NULL which means that the original class description should be used.

RETURN VALUE
The newly created class is returned.
SEE ALSO
SIM_extend_class, SIM_create_class
EXECUTION CONTEXT
Global Context

SIM_create_class()

NAME
SIM_create_class — create class
SYNOPSIS
conf_class_t *
SIM_create_class(const char *NOTNULL name,
                 const class_info_t *NOTNULL class_info);

DESCRIPTION
This function creates a new class that can be instantiated by calling the SIM_create_object function. It is a replacement for SIM_register_class and should be used in all new code.

The name can contain upper and lower case ASCII letters, hyphens, underscores, and digits. It must not begin with a digit or a hyphen and must not end with a hyphen.

class_info may be freed when the function has returned.

typedef enum {
        Sim_Class_Kind_Vanilla = 0, /* object is saved at checkpoints */
        Sim_Class_Kind_Session = 1, /* object is saved as part of a
                                     * session only */
        Sim_Class_Kind_Pseudo = 2,  /* object is never saved */

        Sim_Class_Kind_Extension = 3, /* extension class
                                         (see SIM_extend_class) */
} class_kind_t;

typedef struct class_info {
        conf_object_t *(*alloc)(conf_class_t *cls);
        lang_void *(*init)(conf_object_t *obj);
        void (*finalize)(conf_object_t *obj);
        void (*objects_finalized)(conf_object_t *obj);

        void (*deinit)(conf_object_t *obj);
        void (*dealloc)(conf_object_t *obj);

        const char           *description;
        const char           *short_desc;
        class_kind_t          kind;
} class_info_t;

RETURN VALUE
Class structure, or NULL on error.
EXECUTION CONTEXT
Global Context
SEE ALSO
SIM_register_class_alias, class_info_t

SIM_ensure_partial_attr_order()

NAME
SIM_ensure_partial_attr_order — ensure attribute order
SYNOPSIS
void
SIM_ensure_partial_attr_order(conf_class_t *NOTNULL cls,
                              const char *NOTNULL before,
                              const char *NOTNULL after);

DESCRIPTION
Attribute initialization order is guaranteed to be identical to the order in which the attributes were registered. In some cases a particular order is required in order for a model to work correctly.

This function checks the registration order of the attributes before and after in the class cls. If before is not registered before after, or if at least one of the two are not registered at all, an ASSERT is triggered.

Use this function to ensure that e.g. code refactoring does not break a required attribute order.

EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_register_attribute

SIM_extend_class()

NAME
SIM_extend_class — extend class with contents from an extension class
SYNOPSIS
void
SIM_extend_class(conf_class_t *NOTNULL cls, conf_class_t *NOTNULL ext);

DESCRIPTION
The function extends the class cls with attributes, interfaces, port objects and port interfaces defined by the extension class ext.

The extension class must be of the type Sim_Class_Kind_Extension and must not define any attributes or interfaces which have already been defined by the class being augmented.

Besides normal object initialization, the init_object method for the extension class, will be called when cls is instantiated. The pointer returned by init_object can be retrieved using SIM_extension_data. The init_object method may return NULL if no private data pointer is needed; this does not signify an error condition for extension classes.

The finalize_instance method defined by the extension class will be called before the finalize_instance method is called for the class being extended.

The SIM_extension_class function is intended to be used to extend a class with generic functionality, common to multiple classes.

SEE ALSO
SIM_create_class, SIM_register_class, SIM_extension_data
EXECUTION CONTEXT
Global Context

SIM_extension_data()

NAME
SIM_extension_data — get class extension data
SYNOPSIS
void *
SIM_extension_data(conf_object_t *obj, conf_class_t *ext_cls);

DESCRIPTION
Returns the private data pointer of an object associated with the extension class ext_cls. The returned pointer is the value returned by the init_object method called for the extension class ext_cls.

The object obj must be an instance of a class which has been extended with the extension class ext_cls using the SIM_extend_class function.

SEE ALSO
SIM_object_data, SIM_register_class, SIM_extend_class
EXECUTION CONTEXT
Cell Context

SIM_get_class()

NAME
SIM_get_class — get class
SYNOPSIS
conf_class_t *
SIM_get_class(const char *NOTNULL name);

DESCRIPTION
Returns the configuration class called name.

If it finds no class called name, SIM_get_class will load a module implementing that class, if any can be found, and return the newly created class.

Note that loading a module can not be done during the simulation execution: in that case, SIM_get_class will trigger an error instead. If you encounter this problem, a simple work-around is to make sure that all necessary modules are loaded before starting the execution.

RETURN VALUE
Opaque pointer referencing the class, or NULL if not found.
EXCEPTIONS
SimExc_General Thrown if the class has not been registered.

EXECUTION CONTEXT
Cell Context, except when loading a module.
SEE ALSO
SIM_get_class_name

SIM_get_class_data()

NAME
SIM_get_class_data — get class data
SYNOPSIS
lang_void *
SIM_get_class_data(conf_class_t *cls);

DESCRIPTION
Obtain the class data that was set using SIM_set_class_data. This can be called at any time during the object initialisation process.
SEE ALSO
SIM_set_class_data
EXECUTION CONTEXT
Cell Context

SIM_get_class_name()

NAME
SIM_get_class_name — get class name
SYNOPSIS
const char *
SIM_get_class_name(const conf_class_t *NOTNULL class_data);

DESCRIPTION
Returns the name of the class. Simics retains ownership of the returned string; it must not be modified or freed by the caller.

In Python, the name of an object's class is available via the classname attribute:

obj.classname

.

EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_get_class

SIM_get_interface()

NAME
SIM_get_interface, SIM_c_get_interface, SIM_get_class_interface, SIM_c_get_class_interface, SIM_get_port_interface, SIM_c_get_port_interface, SIM_get_class_port_interface, SIM_c_get_class_port_interface — get interface
SYNOPSIS
const void *
SIM_get_interface(const conf_object_t *NOTNULL obj, const char *NOTNULL name);

const void *
SIM_c_get_interface(const conf_object_t *NOTNULL obj, const char *NOTNULL name);

const void *
SIM_get_class_interface(const conf_class_t *NOTNULL cls, 
                        const char *NOTNULL name);

const void *
SIM_c_get_class_interface(const conf_class_t *NOTNULL cls, 
                          const char *NOTNULL name);

const void *
SIM_get_port_interface(const conf_object_t *NOTNULL obj, 
                       const char *NOTNULL name, const char *portname);

const void *
SIM_c_get_port_interface(const conf_object_t *NOTNULL obj, 
                         const char *NOTNULL name, 
                         const char *portname);

const void *
SIM_get_class_port_interface(const conf_class_t *NOTNULL cls,
                             const char *NOTNULL name, 
                             const char *portname);

const void *
SIM_c_get_class_port_interface(const conf_class_t *NOTNULL cls,
                               const char *NOTNULL name, 
                               const char *portname);

DESCRIPTION
Get the interface with name name from object obj. Returns NULL, and raises an exception if obj does not implement the interface.

SIM_get_port_interface returns a port interface instance as registered with SIM_register_port_interface. The portname selects a particular implementation of the interface by obj's class. If no port name is supplied, the function behaves as SIM_get_interface.

SIM_get_class_interface and SIM_get_class_port_interface are similar but return the interface for a class instead of an object.

SIM_c_get_interface, SIM_c_get_port_interface, SIM_c_get_class_interface and SIM_c_get_class_port_interface are similar to their respective counterparts but never raise an exception, nor do they accept dashes inside name or portname instead of underscores.

The SIM_C_GET_INTERFACE macro is a useful type-safe replacement for SIM_c_get_interface. The macro takes an object and the name of the interface without quotes. Compare the three forms:

SIM_c_get_interface(obj, PCI_DEVICE_INTERFACE);
SIM_c_get_interface(obj, "pci_device");
SIM_C_GET_INTERFACE(obj, pci_device);
   

The data the result points to is owned by Simics. The caller must not deallocate or modify it.

In Python, there is usually no need to use these functions since Simics objects' interfaces are available via the iface attribute. Here is sample Python code calling the signal_raise method of the object's signal interface:

obj.iface.signal.signal_raise()

In a similar way one can call interfaces of an object's port objects. Here is a respective example where an object obj with a port object obj.port.reset has a signal interface:

obj.port.reset.iface.signal.signal_raise()

Port interfaces - interfaces that are registered with SIM_register_port_interface and are considered legacy - are also directly accessible in Python. Here is sample code calling the signal_raise method of the signal interface from the object's RESET port:

obj.ports.RESET.signal.signal_raise()

In order to check if a Simics object implements an interface the following Python code can be used:

if hasattr(obj.iface, "signal"):  # check whether obj has signal interface
    ...

RETURN VALUE
Pointer to interface, or NULL if not found.
EXCEPTIONS
SimExc_Lookup Thrown if the interface is not implemented by obj's class.

SimExc_General Thrown if the interface name is illegal.

EXECUTION CONTEXT
All contexts (including Threaded Context)
SEE ALSO
SIM_register_interface

SIM_is_restoring_state()

NAME
SIM_is_restoring_state — check if state restoring phase
SYNOPSIS
bool
SIM_is_restoring_state(conf_object_t *obj);

DESCRIPTION
Returns true if the configuration system is currently restoring the saved state for the object obj when reading a checkpoint, applying a persistent state or restoring a snapshot.

SIM_is_restoring_state is typically used to prevent side effects in attribute set methods that only should run when the attribute is set manually, for example when hot plugging.

SIM_object_is_configured SIM_is_restoring_state
Creating object false false
Loading checkpoint false true
Loading persistent state true true
Loading snapshot truetrue
Manual attribute access (hot plug) true false

LIMITATION: This function currently returns true for all objects in Simics while some state is being restored and not only for the affected objects.

SEE ALSO
SIM_object_is_configured
EXECUTION CONTEXT
Cell Context

SIM_marked_for_deletion()

NAME
SIM_marked_for_deletion — is object being deleted
SYNOPSIS
bool
SIM_marked_for_deletion(const conf_object_t *NOTNULL obj);

DESCRIPTION
Indicates if the given object is being deleted. This information can be useful by other objects that want to clean up their references.
RETURN VALUE
true if the object is being deleted.
EXECUTION CONTEXT
Global Context
SEE ALSO
SIM_delete_objects

SIM_object_clock()

NAME
SIM_object_clock — get object clock
SYNOPSIS
conf_object_t *
SIM_object_clock(const conf_object_t *NOTNULL obj);

DESCRIPTION
Retrieve the default clock used by an object. This is either set by the queue attribute, or inherited from the default clock of the object's parent. The default clock is used as time reference for the object.
EXECUTION CONTEXT
All contexts (including Threaded Context)

SIM_object_data()

NAME
SIM_object_data — get object-specific data pointer
SYNOPSIS
lang_void *
SIM_object_data(conf_object_t *NOTNULL obj);

DESCRIPTION
Returns the private data pointer of an object. This pointer is available to the class for storing instance-specific state.

It is initialised to the return value of the init (from class_info_t) method that is called during object creation. For classes created using the legacy SIM_register_class, the same functionality is provided by the init_object method .

For classes implemented in Python, the data (which is then a Python value) can also be accessed as obj.object_data.

For classes written in C, the preferred way to store instance-specific state is by co-allocation with the object's conf_object_t structure instead of using SIM_object_data. Such classes should define the alloc method in the class_info_t passed to SIM_create_class for allocating its instance data. For classes using the legacy SIM_register_class class registration function, they should define the alloc_object method in the class_data_t data structure.

SEE ALSO
SIM_create_class, SIM_register_class
EXECUTION CONTEXT
All contexts (including Threaded Context)

SIM_object_id()

NAME
SIM_object_id — get object identifier
SYNOPSIS
const char *
SIM_object_id(const conf_object_t *NOTNULL obj);

DESCRIPTION
Returns the unique identifier for an object. The identifier is a string that is guaranteed to be unique and will never change, even if the object moves to another hierarchical location.

The return value is a static string that should not be modified or freed by the caller.

EXECUTION CONTEXT
All contexts (including Threaded Context)
SEE ALSO
SIM_object_name

SIM_object_is_configured()

NAME
SIM_object_is_configured, SIM_set_object_configured — get/set configured status
SYNOPSIS
bool
SIM_object_is_configured(const conf_object_t *NOTNULL obj);

void
SIM_set_object_configured(conf_object_t *NOTNULL obj);

DESCRIPTION
SIM_object_is_configured indicates whether obj is configured. SIM_set_object_configured sets the object as configured.

An object is configured once its finalize_instance method (post_init in DML) has completed, or SIM_set_object_configured has been called for it. Being configured indicates that the object is in a consistent state and is ready to be used by other objects.

SIM_set_object_configured is used to avoid circular dependencies between objects. It may only be called from the object's own finalize_instance method, when the object is known to be in a consistent state.

EXECUTION CONTEXT
SIM_object_is_configured: all contexts (including Threaded Context); SIM_set_object_configured: Global Context
SEE ALSO
SIM_require_object, SIM_register_class, SIM_is_restoring_state

SIM_object_name()

NAME
SIM_object_name — get object name
SYNOPSIS
const char *
SIM_object_name(const conf_object_t *NOTNULL obj);

DESCRIPTION
Returns the name of an object. This name identifies the object uniquely, but may change if the object is moved to another hierarchical location.

The return value is a string, owned by obj, that should not be modified or freed by the caller.

In Python, an object's name is available via the name attribute:

obj.name

.

EXECUTION CONTEXT
All contexts (including Threaded Context)
SEE ALSO
SIM_object_id

SIM_picosecond_clock()

NAME
SIM_picosecond_clock — get object picosecond clock
SYNOPSIS
conf_object_t *
SIM_picosecond_clock(conf_object_t *NOTNULL obj);

DESCRIPTION
Return the picosecond clock used by an object obj.

The returned clock uses a cycle period of exactly 1 ps. It has full picosecond resolution even if the processor (or clock) driving the simulation uses a lower resolution. An event posted at a particular picosecond triggers always at that precise time, without any rounding issues.

The returned object is the vtime.ps port object of the default clock for the object, and it implements the cycle_event interface.

The API functions SIM_event_post_cycle, SIM_event_post_time, SIM_event_find_next_cycle, SIM_event_cancel_time, and SIM_cycle_count can be used directly on the picosecond clock.

Note: The function SIM_time is currently not supported for the picosecond clock; it will return same value as if the function is invoked on the default clock.
Note: The picosecond clock will wrap around after roughly 200 days of virtual time (2^64 ps).
SEE ALSO
SIM_object_clock
EXECUTION CONTEXT
All contexts (including Threaded Context)

SIM_register_attribute()

NAME
SIM_register_attribute, SIM_register_class_attribute, SIM_register_attribute_with_user_data, SIM_register_class_attribute_with_user_data — register attribute
SYNOPSIS
void
SIM_register_attribute(
        conf_class_t *NOTNULL cls, const char *NOTNULL name,
        attr_value_t (*get_attr)(conf_object_t *),
        set_error_t (*set_attr)(conf_object_t *, attr_value_t *),
        attr_attr_t attr, const char *type, const char *desc);

void
SIM_register_class_attribute(
        conf_class_t *NOTNULL cls, const char *NOTNULL name,
        attr_value_t (*get_attr)(conf_class_t *),
        set_error_t (*set_attr)(conf_class_t *, attr_value_t *),
        attr_attr_t attr, const char *type, const char *desc);

void
SIM_register_attribute_with_user_data(
        conf_class_t *NOTNULL cls, const char *NOTNULL name,
        attr_value_t (*get_attr)(conf_object_t *, lang_void *),
        lang_void *user_data_get,
        set_error_t (*set_attr)(conf_object_t *, attr_value_t *, lang_void *),
        lang_void *user_data_set,
        attr_attr_t attr, const char *type, const char *desc);

void
SIM_register_class_attribute_with_user_data(
        conf_class_t *NOTNULL cls, const char *NOTNULL name,
        attr_value_t (*get_attr)(conf_class_t *, lang_void *),
        lang_void *user_data_get,
        set_error_t (*set_attr)(conf_class_t *, attr_value_t *, lang_void *),
        lang_void *user_data_set,
        attr_attr_t attr, const char *type, const char *desc);

DESCRIPTION
Add the attribute name to the set of attributes of the class cls.

For SIM_register_attribute and SIM_register_class_attribute, the function get_attr is called with the object as argument, and returns the current value of the attribute. For SIM_register_attribute_with_user_data and SIM_register_class_attribute_with_user_data, the function get_attr takes an additional user data argument, which takes the value passed as user_data_get.

On error, get_attr should call SIM_attribute_error. The return value is then ignored; typically, SIM_make_attr_invalid is used to generate an explicitly invalid value.

If get_attr is a null pointer, the attribute will be write-only.

For SIM_register_attribute and SIM_register_class_attribute, the function set_attr is called with the object as argument. For SIM_register_attribute_with_user_data and SIM_register_class_attribute_with_user_data, the function set_attr takes an additional user data argument, which takes the value passed as user_data_set. The set_attr function is called when the attribute is initialised or changed. The argument value is owned by the caller, so any data from it must be copied.

The set_attr method should return Sim_Set_Ok if the new value could be set. On error, it should return an appropriate error code (usually Sim_Set_Illegal_Value), and optionally call SIM_attribute_error with an explanatory message.

If set_attr is a null pointer, the attribute will be read-only.

The attr parameter is one of Sim_Attr_Required, Sim_Attr_Optional or Sim_Attr_Pseudo.

Attributes marked Sim_Attr_Required or Sim_Attr_Optional are saved in checkpoints. Both set_attr and get_attr must be non-null for such attributes.

All attributes that are marked Sim_Attr_Required must be present in all configurations.

The set of permitted values is encoded in the string type.

The type strings are composed as follows:

  • Most types are represented by a single letter:
    i integer
    f floating-point
    s string
    b boolean
    o object
    d data
    n nil
    a any type (not valid when the attribute is marked with Sim_Attr_Required)
  • The | (vertical bar) operator specifies the union of two types; eg, s|o is the type of a string or an object.
  • Lists are defined inside square brackets: []. There are two kinds of list declarations:

    • A heterogeneous list of fixed length is defined by the types of its elements. For example, [ios] specifies a 3-element list consisting of an integer, an object and a string, in that order.
    • A homogeneous list of varying length is defined by a single type followed by a length modifier:

      {N:M} between N and M elements, inclusive
      {N} exactly N elements
      * zero or more elements
      + one or more elements

      For example, [i{3,5}] specifies a list of 3, 4 or 5 integers.

    Inside heterogeneous lists, | (union) has higher precedence than juxtaposition; ie, [i|so|n] defines a list of two elements, the first being an integer or a string and the second an object or NIL.

SIM_register_class_attribute and SIM_register_class_attribute_with_user_data will register a class attribute. Class attributes are the same for all instances of the class.

EXECUTION CONTEXT
Global Context

SIM_register_class()

NAME
SIM_register_class — register class
SYNOPSIS
conf_class_t *
SIM_register_class(const char *NOTNULL name,
                   const class_data_t *NOTNULL class_data);

DESCRIPTION
This function is considered legacy. New code should use the SIM_create_class function to create new classes in the Simics simulator.

The function registers a new class that can be instantiated by calling the SIM_create_object function.

The name can contain upper and lower case ASCII letters, hyphens, underscores, and digits. It must not begin with a digit or a hyphen and must not end with a hyphen.

class_data may be freed when the function has returned.

typedef struct class_data {
        conf_object_t *(*alloc_object)(lang_void *data);
        lang_void *(*init_object)(conf_object_t *obj, lang_void *data);
        void (*finalize_instance)(conf_object_t *obj);

        void (*pre_delete_instance)(conf_object_t *obj);
        int (*delete_instance)(conf_object_t *obj);

        const char           *description;
        const char           *class_desc;
        class_kind_t          kind;
} class_data_t;

RETURN VALUE
Class structure, or NULL on error.
EXECUTION CONTEXT
Global Context
SEE ALSO
SIM_create_class, SIM_register_class_alias, class_data_t

SIM_register_class_alias()

NAME
SIM_register_class_alias — register class alias
SYNOPSIS
void
SIM_register_class_alias(const char *NOTNULL alias, const char *NOTNULL name);

DESCRIPTION
Register an alias alias for the existing class class_name. Using aliases allows the read-configuration command to read configuration files that define objects of type alias, while the write-configuration command always uses class_name.

Aliases are used to support compatibility with old class names if a class is renamed. They can also be used to allow different modules, which define different specific implementations of the same generic base class, to read the same configuration files.

SEE ALSO
SIM_create_class, SIM_register_class
EXECUTION CONTEXT
Global Context

SIM_register_clock()

NAME
SIM_register_clock — register mandatory interface and attributes for clock objects
SYNOPSIS
int
SIM_register_clock(conf_class_t *NOTNULL cls,
                   const cycle_interface_t *NOTNULL iface);

DESCRIPTION
Register the cls class as a class for schedulable clock objects. This includes registering the cycle interface (iface), in addition to which SIM_register_clock registers the cell attribute required for scheduling the clock and some other Simics specific attributes. Simics will be able to schedule objects instantiated from the class cls.

The return value is 0 if everything works, and non-zero if something fails. Depending on the stage that failed, SIM_register_clock() will return the error value provided by SIM_register_interface().

RETURN VALUE
Returns non-zero on failure, 0 otherwise.
EXCEPTIONS
SimExc_General Thrown if the cycle interface has already been registered for this class.

EXECUTION CONTEXT
Global Context
SEE ALSO
SIM_register_interface, SIM_register_attribute

SIM_register_compatible_interfaces()

NAME
SIM_register_compatible_interfaces — register earlier versions of interface
SYNOPSIS
void
SIM_register_compatible_interfaces(conf_class_t *NOTNULL cls,
                                   const char *NOTNULL name);

DESCRIPTION
Register any earlier versions of the interface name for class cls. The interface name must already be registered for the class.

When supported, this function lets a module implement a single version of an interface while still exporting earlier versions.

The following interfaces are currently accepted by this function, with the additional interfaces that are exported given in parenthesis: BREAKPOINT_QUERY_V2, PROCESSOR_INFO_V2 (PROCESSOR_INFO).

EXCEPTIONS
SimExc_General Thrown if no interface is registered with the given name, if compatible versions of the interface have already been registered, or if the interface does not have any earlier versions that this function knows about.

EXECUTION CONTEXT
Global Context

SIM_register_interface()

NAME
SIM_register_interface, SIM_register_port_interface — register interface
SYNOPSIS
int
SIM_register_interface(conf_class_t *NOTNULL cls, const char *NOTNULL name,
                       const void *NOTNULL iface);

int
SIM_register_port_interface(conf_class_t *NOTNULL cls,
                            const char *NOTNULL name,
                            const void *NOTNULL iface,
                            const char *NOTNULL portname,
                            const char *desc);

DESCRIPTION
Register that cls implements the name interface. The interface itself should be supplied in the iface argument.

SIM_register_port_interface registers a port instance of an interface that must be looked up using SIM_get_port_interface. The portname parameter is the name of the port. The port name may not be the same as any attribute name used by the class. A short description of the port is provided with the desc parameter and should be identical for all interfaces for a port. These two functions are considered legacy. New code should use SIM_register_port and SIM_register_interface instead.

The data iface points to must not be deallocated or overwritten by the caller. Simics will use that data to store the interface structure. It will never be freed or written to by Simics.

RETURN VALUE
Returns non-zero on failure, 0 otherwise.
EXCEPTIONS
SimExc_General Thrown if the interface name is illegal, or if this interface has already been registered for this class.

EXECUTION CONTEXT
Global Context
SEE ALSO
SIM_get_interface

SIM_register_port()

NAME
SIM_register_port — register port class
SYNOPSIS
void
SIM_register_port(conf_class_t *NOTNULL cls, const char *NOTNULL name,
                  conf_class_t *NOTNULL port_cls, const char *desc);

DESCRIPTION
Add a port named name of class port_cls to the set of ports defined by the class cls.

The result of this is that whenever an object of class cls is created, Simics will automatically create a port object of class port_cls. The name of the port object is created by appending . followed by the name string to the parent object's name.

If the port name contains dots or brackets, then intermediate port objects are registered as well. For instance, the port name x.array[2] will implicitly register ports x of class namespace, and x.array of class index-map.

Each port name may be registered at most once in a class. One exception is namespace classes: If the port is registered once as class namespace and once as some other class, then the namespace registration is dropped. Also, if a port is registered twice as class index-map, or twice as class namespace, then the second registration is dropped.

SEE ALSO
SIM_register_simple_port
EXECUTION CONTEXT
Global Context

SIM_register_simple_port()

NAME
SIM_register_simple_port — register port
SYNOPSIS
conf_class_t *
SIM_register_simple_port(conf_class_t *NOTNULL cls, const char *NOTNULL name,
                         const char *desc);

DESCRIPTION
Add a port named name to the set of ports defined by the class cls. The port will be an instance of a class named "parent_class_name.portname" where portname is the specified name of the port with leading namespaces omitted and any array indices removed. The port class is created if it does not exist already.
RETURN VALUE
The port class is returned.
SEE ALSO
SIM_register_port
EXECUTION CONTEXT
Global Context

SIM_register_typed_attribute()

NAME
SIM_register_typed_attribute, SIM_register_typed_class_attribute — register attribute
SYNOPSIS
int
SIM_register_typed_attribute(
        conf_class_t *NOTNULL cls, const char *NOTNULL name,
        attr_value_t (*get_attr)(lang_void *user_data,
                                 conf_object_t *obj,
                                 attr_value_t *idx),
        lang_void *user_data_get,
        set_error_t (*set_attr)(lang_void *user_data,
                                conf_object_t *obj,
                                attr_value_t *val, attr_value_t *idx),
        lang_void *user_data_set,
        attr_attr_t attr, const char *type, const char *idx_type,
        const char *desc);

int
SIM_register_typed_class_attribute(
        conf_class_t *NOTNULL cls, const char *NOTNULL name,
        attr_value_t (*get_attr)(lang_void *ptr,
                                 conf_class_t *c,
                                 attr_value_t *idx),
        lang_void *user_data_get,
        set_error_t (*set_attr)(lang_void *ptr,
                                conf_class_t *c,
                                attr_value_t *val,
                                attr_value_t *idx),
        lang_void *user_data_set,
        attr_attr_t attr, const char *type, const char *idx_type,
        const char *desc);

DESCRIPTION
Note: The functions SIM_register_typed_attribute and SIM_register_typed_class_attribute are legacy. New code should use SIM_register_attribute or SIM_register_class_attribute.
Add the attribute name to the set of attributes of the class cls.

The function get_attr is called with the object and the value from user_data_get as arguments, and returns the current value of the attribute.

On error, get_attr should call SIM_attribute_error. The return value is then ignored; typically, SIM_make_attr_invalid is used to generate an explicitly invalid value.

If get_attr is a null pointer, the attribute will be write-only.

The function set_attr is called with the object and the value from user_data_set as arguments when the attribute is initialised or changed. The argument value is owned by the caller, so any data from it must be copied.

The set_attr method should return Sim_Set_Ok if the new value could be set. On error, it should return an appropriate error code (usually Sim_Set_Illegal_Value), and optionally call SIM_attribute_error with an explanatory message.

If set_attr is a null pointer, the attribute will be read-only.

The attr parameter is one of Sim_Attr_Required, Sim_Attr_Optional or Sim_Attr_Pseudo.

Attributes marked Sim_Attr_Required or Sim_Attr_Optional are saved in checkpoints. Both set_attr and get_attr must be non-null for such attributes.

All attributes that are marked Sim_Attr_Required must be present in all configurations.

The set of permitted values is encoded in the string type, and in idx_type for values during indexed access. A NULL value for either type string means that values of any type are permitted.

The type strings are composed as follows:

  • Most types are represented by a single letter:
    i integer
    f floating-point
    s string
    b boolean
    o object
    d data
    n nil
    D dictionary
    a any type
  • The | (vertical bar) operator specifies the union of two types; eg, s|o is the type of a string or an object.
  • Lists are defined inside square brackets: []. There are two kinds of list declarations:

    • A heterogeneous list of fixed length is defined by the types of its elements. For example, [ios] specifies a 3-element list consisting of an integer, an object and a string, in that order.
    • A homogeneous list of varying length is defined by a single type followed by a length modifier:

      {N:M} between N and M elements, inclusive
      {N} exactly N elements
      * zero or more elements
      + one or more elements

      For example, [i{3,5}] specifies a list of 3, 4 or 5 integers.

    Inside heterogeneous lists, | (union) has higher precedence than juxtaposition; ie, [i|so|n] defines a list of two elements, the first being an integer or a string and the second an object or NIL.

SIM_register_typed_class_attribute will register a class attribute. Class attributes are the same for all instances of the class.

RETURN VALUE
Returns zero if successful, and non-zero otherwise.
EXCEPTIONS
SimExc_General Thrown if the attribute name is invalid, and if the attribute is not a required, optional, session or pseudo attribute.

SimExc_AttrNotReadable Thrown if a checkpointed attribute is not readable.

SimExc_AttrNotWritable Thrown if a checkpointed attribute is not writable.

EXECUTION CONTEXT
Global Context

SIM_require_object()

NAME
SIM_require_object — make sure an object is fully configured
SYNOPSIS
void
SIM_require_object(conf_object_t *NOTNULL obj);

DESCRIPTION
If obj has not yet been set as configured, then that object's finalize method (post_init in DML) is run; otherwise, nothing happens. After completion of that method, obj will be set as configured.

Each object will have its finalize method called automatically, usually in hierarchical order, during object creation. Since it is only permitted to call methods on objects that have been configured, SIM_require_object is a way to allow such calls during finalisation by ensuring that those objects are correctly set up. A better way to call methods on other objects during finalization is to defer such calls to the objects_finalized method.

SIM_require_object may only be called from the finalize method of another object.

Finalisation cycles can occur if two or more objects call SIM_require_object on each other. Such cycles are treated as errors. To avoid them, call SIM_set_object_configured as soon as the object has reached a consistent state.

EXECUTION CONTEXT
Global Context
SEE ALSO
SIM_object_is_configured, SIM_create_class, SIM_is_restoring_state

SIM_set_attribute_default()

NAME
SIM_set_attribute_default — set default value for an attribute in a child object
SYNOPSIS
set_error_t
SIM_set_attribute_default(conf_object_t *NOTNULL obj, const char *NOTNULL name,
                          attr_value_t val);

DESCRIPTION
SIM_set_attribute_default sets the default value for attribute name of object obj. The default value is used if no explicit value has been provided when the object is instantiated.

After the call val is still owned by the caller.

The function may only called while obj is being under construction and before its attributes have been set. More precisely, it is only legal to use this function from init_object callbacks or from an attribute setters belonging to a hierarchical ancestor of the object.

The main purpose of this function is setting suitable default attribute values for port objects.

RETURN VALUE
Returns Sim_Set_Ok if successful.
EXECUTION CONTEXT
Global Context
SEE ALSO
SIM_register_port, SIM_register_class

SIM_set_class_data()

NAME
SIM_set_class_data — set class data
SYNOPSIS
void
SIM_set_class_data(conf_class_t *cls, lang_void *data);

DESCRIPTION
Set extra data for the specified class. This is particularly useful if the same class methods are used for multiple distinct classes, for instance for generated classes.

The class data can be fetched at any time during the object initialisation, using SIM_get_class_data.

SEE ALSO
SIM_get_class_data
EXECUTION CONTEXT
Global Context

Callbacks

SIM_cbdata_data()

NAME
SIM_cbdata_data — get cbdata data pointer
SYNOPSIS
FORCE_INLINE void *
SIM_cbdata_data(const cbdata_t *cbd);

DESCRIPTION
Return the data pointer of the callback data cbd.
SEE ALSO
cbdata_t

SIM_cbdata_type()

NAME
SIM_cbdata_type — get cbdata type pointer
SYNOPSIS
FORCE_INLINE const cbdata_type_t *
SIM_cbdata_type(const cbdata_t *cbd);

DESCRIPTION
Return a pointer to the type information of the callback data cbd.
SEE ALSO
cbdata_t

SIM_free_cbdata()

NAME
SIM_free_cbdata — free cbdata
SYNOPSIS
FORCE_INLINE void
SIM_free_cbdata(cbdata_t *cbd);

DESCRIPTION
Free the callback data cbd by calling its dealloc function.
SEE ALSO
cbdata_t

SIM_make_cbdata()

NAME
SIM_make_cbdata — create cbdata
SYNOPSIS
FORCE_INLINE cbdata_t
SIM_make_cbdata(const cbdata_type_t *type, void *data);

DESCRIPTION
Create new callback data of type type and value data.
SEE ALSO
cbdata_t

SIM_make_simple_cbdata()

NAME
SIM_make_simple_cbdata — create untyped cbdata
SYNOPSIS
FORCE_INLINE cbdata_t
SIM_make_simple_cbdata(void *obj);

DESCRIPTION
Create new untyped callback data of value data. An untyped callback data has no dealloc function.
SEE ALSO
cbdata_t

Errors and Exceptions

SIM_clear_exception()

NAME
SIM_clear_exception — clear pending exception
SYNOPSIS
sim_exception_t
SIM_clear_exception();

DESCRIPTION
Clears the currently pending frontend exception and returns the value of it.
RETURN VALUE
Returns the exception that was pending before the call, or SimExc_No_Exception.
EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_get_pending_exception, SIM_last_error

SIM_describe_pseudo_exception()

NAME
SIM_describe_pseudo_exception — return pseudo exception description
SYNOPSIS
const char *
SIM_describe_pseudo_exception(exception_type_t ex);

DESCRIPTION
This function returns a descriptive string for the specified exception_type_t.
RETURN VALUE
Exception description, or an error message if input is not a known pseudo-exception.
EXECUTION CONTEXT
Global Context
SEE ALSO
exception_type_t

SIM_get_pending_exception()

NAME
SIM_get_pending_exception — get current pending exception
SYNOPSIS
sim_exception_t
SIM_get_pending_exception();

DESCRIPTION
This function returns the exception type of the current pending exception, or SimExc_No_Exception if none available.
EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_clear_exception, SIM_last_error

SIM_last_error()

NAME
SIM_last_error — get error message from last frontend exception
SYNOPSIS
const char *
SIM_last_error();

DESCRIPTION
Returns the error message associated with the most recently raised frontend exception, even if that exception has been cleared.

The returned string is only valid until the next use of the Simics API in the same thread.

EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_clear_exception, SIM_get_pending_exception

Notifiers

SIM_add_notifier()

NAME
SIM_add_notifier — add a notifier callback
SYNOPSIS
notifier_handle_t *
SIM_add_notifier(
        conf_object_t *NOTNULL obj,
        notifier_type_t type,
        conf_object_t *subscriber,
        void (*callback)(conf_object_t *subscriber,
                         conf_object_t *NOTNULL notifier,
                         lang_void *data),
        lang_void *data);

DESCRIPTION
SIM_add_notifier installs a notifier of type type on the object obj.

The subscriber argument should be the object listening for the notification; this object is passed as the first argument to the callback function. The installed callback is automatically removed if the subscriber object is deleted. It is legal to pass NULL in the subscriber argument if there is no object associated with the callback.

The data argument is passed as the last argument to the callback function.

The function returns a handle to the installed notifier or NULL if the notifier type is not supported by the object.

Adding a notifier callback from another notifier callback of the same notifier type and object does not trigger an immediate callback invocation (from the same call to SIM_notify).

EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_delete_notifier
SEE ALSO
SIM_delete_notifier, SIM_register_notifier

SIM_class_has_notifier()

NAME
SIM_class_has_notifier — query class for notifier
SYNOPSIS
bool
SIM_class_has_notifier(conf_class_t *NOTNULL cls, notifier_type_t type);

DESCRIPTION
Sim_class_has_notifier returns true if the class cls supports the notifier specified by type.
EXECUTION CONTEXT
Cell Context

SIM_delete_notifier()

NAME
SIM_delete_notifier — delete notifier callback
SYNOPSIS
void
SIM_delete_notifier(conf_object_t *NOTNULL obj, notifier_handle_t *handle);

DESCRIPTION
SIM_delete_notifier deletes the notifier callback specified by the handle handle.

Notifiers callbacks are deleted automatically when the subscribing object is deleted.

Deleting a notifier callback from another notifier callback of the same notifier type and object may or may not inhibit the last invocation of the deleted callback; this is undefined.

EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_add_notifier

SIM_describe_notifier()

NAME
SIM_describe_notifier, SIM_notifier_description — set short description
SYNOPSIS
void
SIM_describe_notifier(notifier_type_t type, const char *NOTNULL generic_desc);

const char *
SIM_notifier_description(notifier_type_t type);

DESCRIPTION
SIM_describe_notifier sets generic_desc as a generic description of the notification specified by the type argument. If the function is called multiple times then the description supplied during the last invocation of the function will be used. The generic description is shown when no description has been provided to the SIM_register_notifier or SIM_register_tracked_notifier functions.

SIM_notifier_description returns a generic description that was set with the SIM_describe_notifier for the notification specified by the type argument, or the empty string if no description has been set.

EXECUTION CONTEXT
Global Context

SIM_has_notifier()

NAME
SIM_has_notifier — query object for notifier
SYNOPSIS
bool
SIM_has_notifier(conf_object_t *NOTNULL obj, notifier_type_t type);

DESCRIPTION
SIM_has_notifier returns true if the object obj supports the notifier specified by type.
EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_register_notifier

SIM_notifier_type()

NAME
SIM_notifier_type — get notifier type
SYNOPSIS
notifier_type_t
SIM_notifier_type(const char *NOTNULL type);

DESCRIPTION
Given a notifier type type specified in the form of a string, return a notifier_type_t identifier which uniquely corresponds to this type.

This function always returns a valid notifier type; if a particular type string has not been seen before, then a new notifier type is created and associated with this string.

The string must consist of printable 7-bit ASCII characters, and by convention it should be expressed as a noun with words separated by dashes.

EXECUTION CONTEXT
Cell Context

SIM_notify()

NAME
SIM_notify — trigger notification callbacks
SYNOPSIS
void
SIM_notify(conf_object_t *NOTNULL obj, notifier_type_t type);

DESCRIPTION
The SIM_notify function triggers all callbacks associated with the notifier notifier which have been installed on the object obj.

The order in which notifier callbacks are invoked is undefined, but the same order every time.

EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_register_notifier, SIM_add_notifier

SIM_register_notifier()

NAME
SIM_register_notifier, SIM_register_tracked_notifier — register notifier
SYNOPSIS
void
SIM_register_notifier(conf_class_t *NOTNULL cls, notifier_type_t type,
                      const char *desc);

void
SIM_register_tracked_notifier(conf_class_t *NOTNULL cls, notifier_type_t type,
                              const char *desc,
                              void (*subscribed_changed)(conf_object_t *obj,
                                                         notifier_type_t type,
                                                         bool has_subscribers));

DESCRIPTION
These functions add the notifier type (returned by the SIM_notifier_type function) to the set of notifiers supported by the class cls. The desc argument can be used to provide any relevant documentation, e.g., information about when the notifier is triggered and how it should be used by the objects that subscribe to it. For uniformity, we suggest formatting the description similar to this one of the "frequency-change" notifier: "Notifier that is triggered when frequency changes. New frequency can be read via the frequency interface of the object."

SIM_register_notifier is the base registration function. It should be used in most cases.

SIM_register_tracked_notifier accepts an additional argument - the subscribed_changed callback. This callback can be used to track whether any respective notification subscribers are installed. The callback is invoked in following cases:

  • a. there are no objects subscribed to type's notifications from obj of cls class, and a new object subscribes to such notifications, i.e., calls SIM_add_notifier. In this case the callback is invoked with the has_subscribers argument equal to true.
  • b. the only object that was subscribed to type's notifications from obj of cls class unsubscribes from such notifications, either explicitly by a call to SIM_delete_notifier, or implicitly when the subscriber object is deleted. In this case the callback is invoked with the has_subscribers argument equal to false.

If the subscribed_changed argument is equal to NULL then it is just ignored.

The subscribed_changed callback is not invoked while the notifier object is being deleted. Thus, if the callback relies on data structures owned by the notifier object, then it is still safe for the object's destructor to deinitialize these data structures needed by the callback.

It is legal to call SIM_register_notifier multiple times for the same class and the same notifier type. All subsequent invocations done after the notifier was registered are ignored. Calling SIM_register_tracked_notifier multiple times registers multiple subscribed_changed callbacks. All of them will be invoked as it is specified above.

EXECUTION CONTEXT
Global Context
SEE ALSO
SIM_notifier_type, SIM_notify, SIM_add_notifier

Global Notifiers

SIM_add_global_notifier()

NAME
SIM_add_global_notifier — add a global notifier callback
SYNOPSIS
global_notifier_callback_t *
SIM_add_global_notifier(
        global_notifier_type_t type,
        conf_object_t *subscriber,
        void (*callback)(conf_object_t *subscriber, lang_void *data),
        lang_void *data);

DESCRIPTION
SIM_add_global_notifier installs a callback on the global notifier of type type. The callback will be executed in Global Context. The callback can uninstall itself, using SIM_delete_global_notifier, but must not uninstall any other global notifiers.

The subscriber argument should be the object listening on the notifier; this object is passed as the first argument to the callback. The installed callback is automatically removed if the subscriber object is deleted. It is legal to pass NULL in the subscriber argument if there is no object associated with the callback.

The function returns a handle to the installed callback or NULL if the notifier type is unknown.

Adding a notifier callback from another notifier callback of the same notifier type does not trigger an immediate callback invocation.

EXECUTION CONTEXT
Global Context

SIM_add_global_notifier_once()

NAME
SIM_add_global_notifier_once — add a global notifier callback
SYNOPSIS
global_notifier_callback_t *
SIM_add_global_notifier_once(
        global_notifier_type_t type,
        conf_object_t *subscriber,
        void (*callback)(conf_object_t *subscriber, lang_void *data),
        lang_void *data);

DESCRIPTION
The SIM_add_global_notifier_once is similar to SIM_add_global_notifier, except that the notifier will be removed automatically after the callback has been called once.
EXECUTION CONTEXT
Global Context

SIM_delete_global_notifier()

NAME
SIM_delete_global_notifier — delete global notifier callback
SYNOPSIS
void
SIM_delete_global_notifier(global_notifier_callback_t *handle);

DESCRIPTION
SIM_delete_global_notifier deletes the global notifier callback specified by the handle handle.

Global notifier callbacks are deleted automatically when the subscribing object is deleted.

Deleting a notifier callback from another notifier callback of the same notifier type may or may not inhibit the last invocation of the deleted callback; this is undefined.

EXECUTION CONTEXT
Global Context

Haps

SIM_hap_add_type()

NAME
SIM_hap_add_type — register a new hap type
SYNOPSIS
hap_type_t
SIM_hap_add_type(const char *NOTNULL hap,
                 const char *NOTNULL params,
                 const char *param_desc,
                 const char *index,
                 const char *desc,
                 int unused);

DESCRIPTION
Creates a run-time defined hap type.

The params parameter specifies the argument that callbacks for this hap is called with; e.g., "s" or "II". The first two arguments are always lang_void * and conf_object_t * respectively, and should not be included in that string. The table below shows which characters may be used, and what their meaning is:

ian int
Ian int64 (64 bit integer)
ean exception_type_t
oa script specific object; i.e., void * in C and any Python object in Python
sa string
ma memory transaction (generic_transaction_t * in C)
ca configuration object (conf_object_t * in C)

param_desc should be a string of space-separated parameter names, or NULL if params is the empty string. There should be one word in param_desc for each character in params.

index is a string describing the index value for this hap, or NULL if there is no index value.

desc is a description string for the hap.

EXCEPTIONS
SimExc_General Thrown if hap is already defined. However, consequent calls with the same parameters will be successful, and return the same hap type number each time.
RETURN VALUE
The hap type number or -1 on error.

EXECUTION CONTEXT
Global Context

SIM_hap_get_name()

NAME
SIM_hap_get_name — get hap name by number
SYNOPSIS
const char *
SIM_hap_get_name(hap_type_t hap);

DESCRIPTION
Returns the name of hap, or NULL for no such hap. The returned value is a static string that should not be modified or freed by the caller.
EXECUTION CONTEXT
Cell Context

SIM_hap_get_number()

NAME
SIM_hap_get_number — get hap number by name
SYNOPSIS
hap_type_t
SIM_hap_get_number(const char *NOTNULL hap);

DESCRIPTION
Return the runtime number associated with a hap identifier. All haps are listed in the Haps chapter in each reference manual.
EXCEPTIONS
SimExc_Lookup Thrown if no hap is associated with name hap.

RETURN VALUE
The hap type number, or 0 on failure.
EXECUTION CONTEXT
Global Context

SIM_hap_is_active()

NAME
SIM_hap_is_active, SIM_hap_is_active_obj, SIM_hap_is_active_obj_idx — check if hap has callbacks
SYNOPSIS
bool
SIM_hap_is_active(hap_type_t hap);

bool
SIM_hap_is_active_obj(hap_type_t hap, conf_object_t *NOTNULL obj);

bool
SIM_hap_is_active_obj_idx(hap_type_t hap, conf_object_t *NOTNULL obj,
                          int64 index);

DESCRIPTION
Indicate whether the hap has any callback functions to be called when the hap is triggered with the given arguments (object and index). The return value is approximate: if false, no functions would be called; if true, there may be functions to call.

The SIM_hap_is_active function should be avoided; it may be slower and less precise than the other variants.

EXECUTION CONTEXT
Cell Context

SIM_hap_occurred_always()

NAME
SIM_hap_occurred_always, SIM_c_hap_occurred_always_vararg, SIM_c_hap_occurred_always, SIM_hap_occurred, SIM_c_hap_occurred_vararg, SIM_c_hap_occurred — trigger a hap occurrence
SYNOPSIS
int
SIM_hap_occurred_always(hap_type_t hap, conf_object_t *obj,
                        int64 value, attr_value_t *NOTNULL list);

int
SIM_c_hap_occurred_always_vararg(hap_type_t hap, conf_object_t *obj,
                                 int64 value, va_list ap);

int
SIM_c_hap_occurred_always(hap_type_t hap, conf_object_t *obj,
                          int64 value, ...);

int
SIM_hap_occurred(hap_type_t hap, conf_object_t *obj,
                 int64 value, attr_value_t *NOTNULL list);

int
SIM_c_hap_occurred_vararg(hap_type_t hap, conf_object_t *obj,
                          int64 value, va_list ap);

int
SIM_c_hap_occurred(hap_type_t hap, conf_object_t *obj,
                   int64 value, ...);

DESCRIPTION
These functions are used to trigger a hap of type hap. When a hap triggers, all callback functions installed on the hap are called.

The obj argument is the object that the hap triggering is associated with. It may be NULL for haps that are not associated with an object.

The value argument is used for filtering out callback functions to call based on the index or range that they are installed for. What the index or range corresponds to is hap specific, but could for example be the exception number for the Core_Exception hap.

SIM_hap_occurred() will only call the callbacks once every simulated cycle; if this hap is triggered several times during one cycle, the callbacks will still only be called once. The SIM_hap_occurred_always() function will always call the hap callback functions every time. It is recommended that SIM_hap_occurred_always() is used.

These hap triggering functions return whether or not there were any matching callback function registered on the hap. This can be useful information when one wants a default behavior to be triggered (for example, stopping the simulation) if nobody is listening to the hap.

The hap-specific parameters to the callback function can be passed in various ways: The SIM_c_hap_occurred... functions are only available in C/C++ and are variadic or take a va_list as argument. SIM_hap_occurred and SIM_hap_occurred_always are mainly intended to be used from Python, taking the parameters from an attribute value of list type, or an empty list ([]) if no parameters are passed. In all cases, the number and types of passed parameters must agree with the hap type definition.

RETURN VALUE
The return value is 0 if no callbacks are registered on the hap and non-zero if there are callbacks registered.
EXCEPTIONS
SimExc_General Thrown if hap is not a valid hap type or if the values in the list argument are of the wrong type.

EXECUTION CONTEXT
Cell Context

SIM_hap_remove_type()

NAME
SIM_hap_remove_type — remove a hap type
SYNOPSIS
void
SIM_hap_remove_type(const char *NOTNULL hap);

DESCRIPTION
Remove a run-time defined hap type.
EXECUTION CONTEXT
Global Context

Logging

SIM_log_info()

NAME
SIM_log_info, SIM_log_spec_violation, SIM_log_unimplemented, SIM_log_error, SIM_log_critical, SIM_log_message, SIM_log_message_vararg — output log message
SYNOPSIS
void
SIM_log_info(int level, conf_object_t *NOTNULL dev, int grp,
             const char *NOTNULL fmt, ...);

void
SIM_log_spec_violation(int level, conf_object_t *NOTNULL dev, int grp,
                       const char *NOTNULL fmt, ...);

void
SIM_log_unimplemented(int level, conf_object_t *NOTNULL dev, int grp,
                      const char *NOTNULL fmt, ...);

void
SIM_log_error(conf_object_t *NOTNULL dev, int grp,
              const char *NOTNULL fmt, ...);

void
SIM_log_critical(conf_object_t *NOTNULL dev, int grp,
                 const char *NOTNULL fmt, ...);

void
SIM_log_message(conf_object_t *obj, int level, uint64 group_ids,
                log_type_t log_type, const char *message);

void
SIM_log_message_vararg(conf_object_t *NOTNULL obj, int level, uint64 grp,
                       log_type_t log_type, const char *NOTNULL fmt, ...);

DESCRIPTION
SIM_log_warning(dev, grp, msg)  #  Python-only

Logging functions and macros are used to emit information and error messages.

The functions above should only be used in Python. In C they are deprecated and the following preprocessor macros can be used instead.

#define SIM_LOG_INFO(level, dev, grp, ...)
#define SIM_LOG_SPEC_VIOLATION(level, dev, grp, ...)
#define SIM_LOG_UNIMPLEMENTED(level, dev, grp, ...)
#define SIM_LOG_ERROR(dev, grp, ...)
#define SIM_LOG_WARNING(dev, grp, ...)
#define SIM_LOG_CRITICAL(dev, grp, ...)
#define SIM_LOG_INFO_ONCE(level1, level2, dev, grp, ...)
#define SIM_LOG_SPEC_VIOLATION_ONCE(level1, level2, dev, grp, ...)
#define SIM_LOG_UNIMPLEMENTED_ONCE(level1, level2, dev, grp, ...)
#define SIM_LOG_WARNING_ONCE(dev, grp, ...)

The logging macros are among the few API features that may be called while a frontend exception is pending.

The level parameter indicates the importance; a lower value means a more important message.

level should be between 1 and 4:

  1. important messages that are always printed
  2. "high-level" informative messages
  3. standard debug messages
  4. detailed information, such as register accesses

SIM_LOG_ERROR has no level parameter and will always emit messages.

The grp parameter should have a bit set for each log group that the message corresponds to, as defined by the SIM_log_register_groups function, while a value of 0 equals any group.

The level and grp parameters allow the user to selectively display more or fewer messages using the log-level, log-group and log-type commands.

The fmt argument and those following it are used for string formatting in the same way as in the standard sprintf function.

The use of the different functions and macros is discussed in Simics Model Builder User's Guide, section "Logging":

  • info: Normal informational message
  • warning: Unexpected problem in the model, but simulation can continue.
  • error: Unexpected error in the model (indicates a bug in the model)
  • critical: Critical error that will interrupt the simulation (indicates a bug that the model may not recover from)
  • spec_violation: Target program violates the specification
  • unimplemented: Attempt to use not yet implemented functionality
If the sim->stop_on_error attribute is set to true, for example if Simics was started with the --stop-on-error command line flag, then Simics will exit with an error code when a log message of the error type is generated.

If the sim->warnings_as_errors attribute is set to true, for example if Simics was started with the --warnings-as-errors command line flag, then a log warning has the same effect as a log error.

EXECUTION CONTEXT
All contexts (including Threaded Context)
SEE ALSO
SIM_log_register_groups, SIM_attribute_error

SIM_log_level()

NAME
SIM_log_level, SIM_set_log_level — set and get log level
SYNOPSIS
unsigned
SIM_log_level(const conf_object_t *NOTNULL obj);

void
SIM_set_log_level(conf_object_t *NOTNULL obj, unsigned level);

DESCRIPTION
Retrieve or set the log level of an object. The level must be in the range 0..4 inclusive. Higher values mean more detailed logging.
EXECUTION CONTEXT
Cell Context

SIM_log_register_groups()

NAME
SIM_log_register_groups — register names of log groups
SYNOPSIS
void
SIM_log_register_groups(conf_class_t *NOTNULL cls,
                        const char *const *NOTNULL names);

DESCRIPTION
Register a list of log groups that an object can use to separate messages. The order of the groups in the list defines the group ids that should be used in calls to SIM_log_info and similar functions. The group_ids argument to those functions should have a bit set corresponding to the group; i.e., a value of 1 for the first group, 2 for the second, 4 for the third, etc. names should be a NULL-terminated array.

A class may have up to 63 user-defined log groups.

The Default_Log_Group group is present on all classes. It is used for log entries where no group is specified.

EXCEPTIONS
SimExc_General Thrown in case of an error, e.g. if log groups are already registered.

EXECUTION CONTEXT
Global Context
SEE ALSO
SIM_log_info

Transaction Types

atom_id_t

NAME
atom_id_t
DESCRIPTION
Each atom type is associated with a unique id, the atom_id_t. Most atoms types are pre-defined by Simics Core and have static ids, but there are also dynamically assigned ids which are used for custom atom types.

Atom ids are internal to Simics Core and should never be used explicitly by a Simics models. Instead, there are API functions like e.g. ATOM_size or ATOM_initiator which should be used instead.

atom_t

NAME
atom_t
DESCRIPTION
The atom_t type is a container type for tagged data associated with a transaction. The kind of data stored in the atom is determined by the id field, and a pointer to the data or the data itself is stored in the ptr field.

Atoms should always be initialized using provided constructor functions like ATOM_flags or ATOM_size. Usage of the constructors ensures that the data payload is of the correct type and that the id is set to the correct value.

Atom lists must be terminated with the special ATOM_LIST_END marker.

transaction_completion_t

NAME
transaction_completion_t
SYNOPSIS
typedef exception_type_t (*transaction_completion_t)(
        conf_object_t *obj, transaction_t *t, exception_type_t ex);

DESCRIPTION
Callback invoked when an asynchronous transaction is completed. The callback is stored in a completion atom belonging to the transaction t. Similarly, obj is an object stored in either an owner atom or an initiator atom. The former takes precedence if both are present.

Completion callbacks are only invoked for transactions monitored with either SIM_monitor_transaction or SIM_monitor_chained_transaction, or for transactions deferred with SIM_defer_owned_transaction.

The completion status for the operation is given in the ex argument, and is usually equal to Sim_PE_No_Exception.

The return value of the callback is the completion status for the transaction t. This status is used to complete the parent transaction if the transaction is being monitored with SIM_monitor_chained_transaction. The return value is also returned by SIM_monitor_transaction or SIM_monitor_chained_transaction when a transaction is completed synchronously.

If the callback returns Sim_PE_Deferred, then the transaction t is left uncompleted. It must then be completed later on by an explicit call to SIM_complete_transaction.

transaction_flags_t

NAME
transaction_flags_t
SYNOPSIS
typedef enum {
        Sim_Transaction_Fetch         = 1 << 0,
        Sim_Transaction_Write         = 1 << 1,
        Sim_Transaction_Control       = 1 << 2,

        Sim_Transaction_Inquiry       = 1 << 8,
        Sim_Transaction_Incoherent    = 1 << 9,
        Sim_Transaction_Atomic        = 1 << 10,
} transaction_flags_t;

DESCRIPTION
The transaction_flags_t type is bitmask used to specify the transaction type. It is a combination of the following bits:

Sim_Transaction_Fetch indicates that the transaction is an instruction fetch.

Sim_Transaction_Write is set if the transaction is a write.

Sim_Transaction_Control is set if the transaction does not actually transfer any data. One example of such transactions is cache control operations.

The Sim_Transaction_Inquiry bit signifies that side effects normally triggered by the transaction should be suppressed. Examples of side effects include triggering breakpoints and clearing "read-to-clear" device registers.

When neither Sim_Transaction_Fetch nor Sim_Transaction_Write is set the transaction is a read transaction.

transaction_t

NAME
transaction_t
DESCRIPTION
A transaction_t represents a memory transaction. The properties of the transaction is stored in the form of an atom list, where each atom describes a particular aspect of the transaction, like the size of the transaction.

The field atoms points to the atoms list, which must be terminated with the constant ATOM_LIST_END.

The prev field points to an optional parent transaction. If a particular atom is not found in the atoms list, then the parent's list of atoms is consulted instead. The prev pointer is also used when a chained transaction is monitored with SIM_monitor_chained_transaction.

Besides the fields above, the transaction contains some internal fields that should be initialized to 0. The internal fields should not be referenced explicitly since they are likely to change in future Simics releases.

For details, please refer to "Transactions" chapter in the Model Builder's User Guide.

Transactions

ATOM_flags()

NAME
ATOM_flags, ATOM_data, ATOM_size, ATOM_initiator, ATOM_completion, ATOM_list_end — transaction atom's constructor
SYNOPSIS
static inline atom_t ATOM_flags(transaction_flags_t val);

static inline atom_t ATOM_data(uint8 *val);

static inline atom_t ATOM_size(uint32 val);

static inline atom_t ATOM_initiator(conf_object_t *val);

static inline atom_t ATOM_completion(transaction_completion_t val);

static inline atom_t ATOM_list_end(int val);

DESCRIPTION
The functions construct transaction atoms.

ATOM_flags returns a transaction atom specifying transaction flags (see description of transaction_flags_t for information about available transaction flags).

ATOM_data returns a transaction atom that holds the pointer to a buffer that is used to get the data from (for write transactions) to store the data to (for read and instruction fetch transactions).

ATOM_size returns a transaction atom that holds the size of a transaction.

ATOM_initiator returns a transaction atom that holds the initiator of a transaction.

ATOM_completion creates a completion atom - a special atom that holds a callback that is invoked when a transaction is completed asynchronously.

ATOM_list_end returns a special atom that should end the list of transaction atoms. One can use the ATOM_LIST_END macro instead.

RETURN VALUE
An atom value
EXECUTION CONTEXT
All contexts (including Threaded Context)
EXAMPLE
Sample C code to create a 1-byte read transaction:
     uint8 val;
     atom_t atoms[] = {
         // the flags atom value specifies the transaction type:
         // - 0 defines a read transaction
         // - Sim_Transaction_Write - a write transaction
         // - Sim_Transaction_Fetch - an instruction fetch transaction
         ATOM_flags(0),

         ATOM_data(&val),
         ATOM_size(sizeof val),
         ATOM_initiator(obj),
         ATOM_LIST_END
     };
     transaction_t t = { atoms };
   

SEE ALSO
transaction_t, transaction_flags_t, transaction_completion_t

SIM_complete_transaction()

NAME
SIM_complete_transaction — complete a deferred transaction
SYNOPSIS
void
SIM_complete_transaction(transaction_t *t, exception_type_t status);

DESCRIPTION
The SIM_complete_transaction completes a previously deferred transaction t using the exception status status. The transaction t must be the return value of a previous call to SIM_defer_transaction or a transaction passed to SIM_defer_owned_transaction.

If the transaction t has not been monitored, then the completion code is stored in an internal transaction field until the transaction is monitored with SIM_monitor_transaction or SIM_monitor_chained_transaction, at which time the completion callback is invoked using the stored completion code.

Note that SIM_complete_transaction is normally only used to complete asynchronous transactions. Synchronous transactions are completed by returning the appropriate return code directly from the issue method.

SEE ALSO
SIM_defer_transaction, SIM_monitor_transaction, SIM_monitor_chained_transaction, SIM_poll_transaction
EXECUTION CONTEXT
Cell Context

SIM_defer_owned_transaction()

NAME
SIM_defer_owned_transaction — defer transaction completion using an existing transaction
SYNOPSIS
transaction_t *
SIM_defer_owned_transaction(transaction_t *t);

DESCRIPTION
When a transaction cannot be completed immediately in the issue method of the transaction interface, then the completion can be deferred to a later time by calling SIM_defer_transaction which allocates a new transaction. One alternative is calling SIM_defer_owned_transaction which allows the caller to allocate the deferred transaction explicitly, in which case provides a heap-allocated transaction t which is linked to the transaction which should be deferred through its prev field. The provided transaction should have an owner and a completion atoms, which are used when the deferred transaction is completed.

When a transaction is deferred, the status code Sim_PE_Deferred must be returned from the issue method of the transaction interface.

RETURN VALUE
The transaction t, or NULL if the transaction was issued synchronously and cannot be deferred. When a transaction cannot be deferred, the issue method may choose to return the error status Sim_PE_Async_Required.
EXECUTION CONTEXT
Cell Context

SIM_defer_transaction()

NAME
SIM_defer_transaction — defer transaction completion
SYNOPSIS
transaction_t *
SIM_defer_transaction(conf_object_t *obj, transaction_t *t);

DESCRIPTION
When a transaction cannot be completed immediately in the issue method of the transaction interface, then the completion can be deferred to a later time by calling SIM_defer_transaction with the transaction as a parameter.

The SIM_defer_transaction function returns a new transaction pointer which is guaranteed to be available until it is completed with a call to SIM_complete_transaction. When a transaction is deferred, the status code Sim_PE_Deferred must be returned from the issue method of the transaction interface.

RETURN VALUE
Deferred transaction, or NULL if the transaction was issued synchronously and cannot be deferred. When a transaction cannot be deferred, the issue method may choose to return the error status Sim_PE_Async_Required.
EXECUTION CONTEXT
Cell Context

SIM_get_transaction_bytes()

NAME
SIM_get_transaction_bytes, SIM_get_transaction_bytes_offs, SIM_get_transaction_value_le, SIM_get_transaction_value_be — get transaction data payload
SYNOPSIS
void
SIM_get_transaction_bytes(const transaction_t *t, buffer_t buf);

void
SIM_get_transaction_bytes_offs(const transaction_t *t, unsigned offs,
                               buffer_t buf, bool zerofill_holes);

uint64
SIM_get_transaction_value_le(const transaction_t *t);

uint64
SIM_get_transaction_value_be(const transaction_t *t);

DESCRIPTION
Copy the data payload from a transaction to the provided buffer buf. The size of the buffer must match the size of the transaction.

SIM_get_transaction_bytes_offs retrieves the bytes of the transaction which starts at offset offs. The sum of the offset and the buffer size must not exceed the transaction size.

SIM_get_transaction_value_le returns the value obtained when the transaction buffer is interpreted as an encoded little endian integer. The size of the transaction must not exceed 8 for this function to be used.

SIM_get_transaction_value_be returns the value obtained when the transaction buffer is interpreted as an encoded big endian integer.

EXECUTION CONTEXT
All contexts (including Threaded Context)

SIM_get_transaction_id()

NAME
SIM_get_transaction_id — obtain checkpoint ID for a deferred a transaction
SYNOPSIS
int64
SIM_get_transaction_id(transaction_t *t);

DESCRIPTION
The SIM_get_transaction_id function is used by objects that checkpoint the transaction state. The returned ID uniquely identifies the transaction and should be stored in a checkpoint together with the relevant state that the object keeps for the transaction. The same ID should then be given to SIM_reconnect_transaction during checkpoint load.

This function must only be called on a deferred transaction.

SEE ALSO
SIM_reconnect_transaction
EXECUTION CONTEXT
Global Context

SIM_inspect_address_routing()

NAME
SIM_inspect_address_routing — track the route of a transaction through memory hierarchy
SYNOPSIS
bool
SIM_inspect_address_routing(const map_target_t *NOTNULL mt,
                            transaction_t *NOTNULL t,
                            uint64 addr,
                            bool (*NOTNULL callback)(
                                    const map_target_t *mt,
                                    const transaction_t *t,
                                    uint64 addr,
                                    uint64 base,
                                    uint64 start,
                                    uint64 size,
                                    access_t access,
                                    translation_flags_t flags,
                                    lang_void *data),
                            lang_void *data);

DESCRIPTION
This function allows to track the route of a transaction through memory hierarchy. The route is traced as if the transaction t was issued at the address addr to the destination represented by the map target mt. Note that when this function is used the endpoint of the transaction will not be accessed.

The transaction t can be of any type: a read, a write, or an instruction fetch. Please note that the type of the transaction may affect its path through memory hierarchy. The size of the transaction t is ignored: when accesses are done larger transactions may be split depending on how the memory mapping are set up; no such splitting is occurred while the transaction route is traced with SIM_inspect_address_routing. It is allowed to use transactions with zero size.

The callback callback will be called for every device (memory spaces and translator objects) encountered on the transaction’s route to the destination as well as for the destination device (this is usually a device implementing the transaction interface or the io_memory interface). The first invocation of callback is done with the mt argument itself.

The arguments passed to the callback are:

- mt is a map target representing an intermediate device or the endpoint. If nothing is mapped then NULL (or None in Python) value is passed. The map target value should not be cached but it can be inspected

- t is usually the original transaction, but it can be also a new transaction in the case when additional atoms were appended to the original transaction via the transaction chaining (see, e.g., the documentation for the transaction_translator interface)

- addr is address inside the intermediate device or the endpoint where the transaction is sent

- base, start, size, access, and flags arguments describe the mapping which led to the mt map target. These arguments (except for access) are the same as the fields of the translation_t structure. Please refer to the translation_t's documentation for their description. The access argument is a bitmask specifying access types. The bit corresponding to the type of the t transaction is always set. Other access bits may also be set optionally. But the latter is not guaranteed even if read/write/execute accesses are routed similarly

- data is the data argument passed to SIM_inspect_address_routing

The callback callback may return false to stop inspection. I.e. if the false value is returned callback will not be invoked any more.

RETURN VALUE
The function returns false if callback returned false in order to stop the inspection. Otherwise, true is returned.
EXAMPLE
 
# The following example shows how one can determine
# the destination of a read transaction sent from a CPU object:

import conf, simics

def get_destination(memory_space, address):
    '''Example function returning destination object for the access
    sent to address in the memory space memory_space.'''
    mt = simics.SIM_new_map_target(memory_space, None, None)
    t = simics.transaction_t()  # read transaction of zero size
    l = [None]  # data for the callback

    def callback(mt, t, addr, base, start, size, access, flags, l):
        l[0] = (simics.SIM_map_target_object(mt)
                if mt is not None
                else None)
        return True

    simics.SIM_inspect_address_routing(mt, t, address, callback, l)

    # We free mt here but it can be saved and reused if needed.
    # Transaction t can also be reused.
    simics.SIM_free_map_target(mt)
    return l[0]

# Please specify here CPU object and address you are interested in:
cpu = simics.SIM_get_processor(0)
address_of_access = 0x1000

dest = get_destination(
    cpu.iface.processor_info_v2.get_physical_memory(),
    address_of_access)

print("Destination: ",
      dest.name if dest is not None else "'nothing is mapped'")

EXECUTION CONTEXT
Cell Context

SIM_inspect_breakpoints()

NAME
SIM_inspect_breakpoints — find out breakpoints that a transaction would trigger
SYNOPSIS
bool
SIM_inspect_breakpoints(
        const map_target_t *NOTNULL mt,
        transaction_t *NOTNULL t,
        uint64 start,
        uint64 end,
        bool (*NOTNULL callback)(
                conf_object_t *trigger_object,
                breakpoint_set_t bp_set,
                const transaction_t *t,
                uint64 start,
                uint64 end,
                lang_void *data),
        lang_void *data);

DESCRIPTION
The function allows to find out the breakpoints that would be triggered if a transaction t would be sent to the address range inside the map target mt. The address range is specified by the start and end arguments and includes both start and end of the range. Only breakpoints matching the transaction t's type (i.e., a read, a write, or an instruction fetch) are reported. The size of the transaction t is ignored and can be zero.

For all matching breakpoints Simics invokes callback. The callback function may be called multiple times: with different trigger_object objects. The callback function gets the following two arguments that describe the breakpoints:

- trigger_object is the object implementing the breakpoint_trigger interface. The interface is used during simulation to signal that an access triggers a breakpoint

- bp_set is a set of breakpoints. The breakpoints match the transaction t's type and intersect the [start, end] range within the mt map target. Bp_set should only be used inside callback. Data ownership is preserved by the caller (i.e., Simics)

Auxiliary information is provided to callback via the following arguments:

- t is usually the original transaction, but it can be also a new transaction in the case when additional atoms were appended to the original transaction via the transaction chaining (see, e.g., the documentation for the transaction_translator interface)

- callback's start and end arguments specify an address range inside the trigger_object Simics object where the accesses to the requested address range inside the mt map target would go. The size of the range reported to callback may be smaller than the size of the requested range. This may occur, e.g., when different parts of the original address range are translated to different destinations based the memory mappings of the simulated machine

- callback's data is the data argument passed to SIM_inspect_breakpoints

The callback function may return false to stop searching for breakpoints. I.e. if the false value is returned callback will not be invoked any more even if more breakpoints are present.

The SIM_inspect_breakpoints function is an inspection function: the endpoint of the transaction is never accessed when the function is used.

RETURN VALUE
The function returns false if callback returned false in order to stop the inspection. Otherwise, true is returned.
EXECUTION CONTEXT
Cell Context

SIM_issue_read_transaction()

NAME
SIM_issue_read_transaction, SIM_issue_write_transaction — functions for issuing transaction_t transactions
SYNOPSIS
FORCE_INLINE exception_type_t
SIM_issue_read_transaction(
        map_target_t *NOTNULL mt, uint64 addr, buffer_t buf,
        bool inquiry, conf_object_t *initiator);

FORCE_INLINE exception_type_t
SIM_issue_write_transaction(
        map_target_t *NOTNULL mt, uint64 addr, bytes_t bytes,
        bool inquiry, conf_object_t *initiator);

DESCRIPTION
These functions provide a simple way to issue read and write transaction_t transactions in C code. In Python, please use the SIM_issue_transaction function.

The functions have the following parameters:

- mt specifies the destination to send a transaction to.

- addr is the address used to issue a transaction.

- the SIM_issue_read_transaction's buf parameter has buffer_t type and specifies a writable buffer for storing the read data. The data.data field points to the host memory where the results should be stored. The data.len field specifies the number of bytes to read.

- The SIM_issue_write_transaction's bytes parameter is of bytes_t type and provides the data that should be written. The data.data field points to the buffer holding the data that should be written. The data.len field specifies the number of bytes to write.

- inquiry specifies whether the transaction should have the Sim_Transaction_Inquiry flag set. The flag signifies that side effects normally triggered by the transaction should be suppressed. Examples of side effects include triggering breakpoints and clearing "read-to-clear" device registers.

- initiator specifies the object issuing a transaction. It may be NULL. The value is used for setting the initiator atom of the transaction.

These functions don't support the case when a model needs to provide custom atoms in transaction_t transactions. For such cases as well as when using Python the SIM_issue_transaction function should be used.

RETURN VALUE
Status of the issued transaction, usually Sim_PE_No_Exception or Sim_PE_IO_Not_Taken. See the exception_type's documentation for more information.
EXECUTION CONTEXT
Cell Context
EXAMPLE
    /* Sample C code that reads an 8-byte little-endian value. If in the
       simulated hardware the endpoint stores values in big-endian format then
       macros from <simics/util/swabber.h> can be used for conversion. */
    uint64 value = -1;  // variable to read data into
    exception_type_t ex = SIM_issue_read_transaction(
        mt,
        addr,
        (buffer_t) {
            .data = (uint8 *)&value,
            .len = sizeof value,
        },
        false,  /* inquiry flag */
        obj     /* initiator */
        );
    if (ex == Sim_PE_No_Exception) {
        /* Read was successful: 'value' contains valid data. */
        SIM_LOG_INFO(4, obj, 0, "Read '%#llx' at %#llx", value, addr);
    } else {
        /* Read operation was not successful. There is no valid data
           in 'value'. Put any error handling code here. */
        SIM_LOG_ERROR(obj, 0, "Read at %#llx failed", addr);
    }

    /* Sample C code that writes an 8-byte little-endian value. If in the
       simulated hardware the endpoint stores values in big-endian format then
       macros from <simics/util/swabber.h> can be used for conversion. */
    uint64 write_value = 1;  // Data to write. '1' is written in this example.
    SIM_LOG_INFO(4, obj, 0, "Writing '%#llx' at %#llx", write_value, addr);
    exception_type_t ex = SIM_issue_write_transaction(
        mt,
        addr,
        (bytes_t) {
            .data = (uint8 *)&write_value,
            .len = sizeof write_value,
        },
        false,  /* inquiry flag */
        obj     /* initiator */
        );
    if (ex == Sim_PE_No_Exception) {
        /* Write was successful. */
    } else {
        /* Write operation was not successful.
           Put any error handling code here. */
        SIM_LOG_ERROR(obj, 0, "Write at %#llx failed", addr);
    }
    

SEE ALSO
exception_type_t, map_target_t, SIM_issue_transaction, transaction_t

SIM_issue_transaction()

NAME
SIM_issue_transaction — issue transaction
SYNOPSIS
exception_type_t
SIM_issue_transaction(const map_target_t *NOTNULL mt,
                      transaction_t *NOTNULL t, uint64 addr);

DESCRIPTION
SIM_issue_transaction issues the transaction t with the address addr to the destination represented by the map target mt. In Python, the mt argument can also be a conf_object_t.
RETURN VALUE
The function returns Sim_PE_Deferred if the transaction was deferred for completion at a some later time. The corresponding pseudo exception is returned if the transaction completed directly (normally Sim_PE_No_Exception or Sim_PE_IO_Not_Taken).
SEE ALSO
exception_type_t, transaction_t, SIM_new_map_target, SIM_free_map_target, SIM_issue_read_transaction, SIM_issue_write_transaction, SIM_defer_transaction, SIM_complete_transaction, SIM_monitor_transaction, SIM_transaction_wait
EXECUTION CONTEXT
Cell Context

SIM_monitor_transaction()

NAME
SIM_monitor_transaction, SIM_monitor_chained_transaction — monitor a transaction for deferred completion
SYNOPSIS
exception_type_t
SIM_monitor_transaction(transaction_t *t, exception_type_t ex);

exception_type_t
SIM_monitor_chained_transaction(transaction_t *t, exception_type_t ex);

DESCRIPTION
The SIM_monitor_transaction function monitors an asynchronously issued transaction for completion. A transaction is asynchronously issued if it has a completion atom with a callback which is not NULL. The function should be called after the transaction has been issued, and the ex status code should be the return value from function used to issue the transaction, for example the issue method of the transaction interface.

If ex equals Sim_PE_Deferred, then SIM_monitor_transaction will check if the transaction has in fact been completed already, and in that case, immediately invoke the completion callback. If the transaction is still uncompleted, then it will be marked as monitored and a subsequent call to SIM_complete_transaction will immediately complete the transaction by invoking the completion callback.

If ex is not equal to Sim_PE_Deferred, then the transaction has been completed synchronously, and the completion callback is called using ex as the completion status.

Note that it is illegal to call SIM_monitor_transaction for transactions that do not have a valid completion callback.

SIM_monitor_chained_transaction is similar to SIM_monitor_transaction except that when a deferred transaction is completed, its parent transaction will be completed too.

RETURN VALUE
Exception code returned by the completion function, or Sim_PE_Deferred if the transaction is monitored for completion at a later time.
SEE ALSO
SIM_defer_transaction, SIM_complete_transaction
EXECUTION CONTEXT
Cell Context

SIM_poll_transaction()

NAME
SIM_poll_transaction — check if a transaction has completed
SYNOPSIS
exception_type_t
SIM_poll_transaction(transaction_t *t);

DESCRIPTION
The SIM_poll_transaction function checks if the transaction t is marked as completed, in which case the associated status code is returned and the completion status for the transaction is cleared. If the transaction is uncompleted, then Sim_PE_Deferred is returned.

It is illegal to call SIM_poll_transaction on a transaction which is monitored for completion using e.g. the SIM_monitor_transaction function.

SEE ALSO
SIM_complete_transaction
EXECUTION CONTEXT
Cell Context

SIM_reconnect_transaction()

NAME
SIM_reconnect_transaction — register that a deferred transaction has been restored
SYNOPSIS
void
SIM_reconnect_transaction(transaction_t *t, int64 id);

DESCRIPTION
The SIM_reconnect_transaction function is used by objects that checkpoint the transaction state. It should be called when the relevant state has been read from a checkpoint.
SEE ALSO
SIM_get_transaction_id
EXECUTION CONTEXT
Global Context

SIM_register_python_atom_type()

NAME
SIM_register_python_atom_type — register an atom type which takes plain Python objects
SYNOPSIS
void
SIM_register_python_atom_type(const char *NOTNULL name);

DESCRIPTION
Register an atom type named name. The atom type can be used from Python and can hold any Python object.
EXECUTION CONTEXT
Global Context

SIM_replace_transaction()

NAME
SIM_replace_transaction — replace transaction
SYNOPSIS
void
SIM_replace_transaction(transaction_t *t_old, transaction_t *t_new);

DESCRIPTION
Replace a transaction t_old with a new transaction t_new.

A transaction which has been issued and is deferred by some downstream device can be replaced with a different transaction by initiator. This is mostly useful when a transaction is allocated on the stack and it turns out that the transaction is not completed synchronously, in which case SIM_replace_transaction can be used to move the transaction to e.g. the heap.

This function ensures that the deferred transaction is properly linked with the t_new transaction. It is the caller's responsibility to fill in the contents of the new transaction, including the prev pointer.

It is illegal to replace a transaction which has been monitored.

EXECUTION CONTEXT
Cell Context

SIM_set_transaction_bytes()

NAME
SIM_set_transaction_bytes, SIM_set_transaction_bytes_offs, SIM_set_transaction_value_le, SIM_set_transaction_value_be, SIM_set_transaction_bytes_constant — set transaction data payload
SYNOPSIS
void
SIM_set_transaction_bytes(const transaction_t *t, bytes_t bytes);

void
SIM_set_transaction_bytes_offs(const transaction_t *t, unsigned offs,
                               bytes_t bytes);

void
SIM_set_transaction_value_le(const transaction_t *t, uint64 value);

void
SIM_set_transaction_value_be(const transaction_t *t, uint64 value);

void
SIM_set_transaction_bytes_constant(const transaction_t *t, uint8 value);

DESCRIPTION
Set the data payload of a transaction to the contents provided by bytes. The number of provided bytes must match the transaction size exactly.

The SIM_set_transaction_bytes_offs function sets some bytes of the transaction starting at offset offs. The sum of the offset and the number of provided bytes must not exceed the transaction size.

The SIM_set_transaction_value_le function sets the transaction bytes to the little endian representation of value. The size of the transaction must not exceed 8 for this function to be used. Similarly, SIM_set_transaction_value_be sets the transaction bytes to the big endian representation of the provided value. If the transaction is smaller than 8 bytes the functions will truncate the representation of the value.

The SIM_set_transaction_bytes_constant function can be used when an endpoint wants to set all transaction bytes to value.

EXECUTION CONTEXT
Cell Context

SIM_transaction_flags()

NAME
SIM_transaction_flags, SIM_transaction_is_fetch, SIM_transaction_is_write, SIM_transaction_is_read, SIM_transaction_is_inquiry — return transaction type
SYNOPSIS
transaction_flags_t
SIM_transaction_flags(const transaction_t *NOTNULL t);

bool
SIM_transaction_is_fetch(const transaction_t *NOTNULL t);

bool
SIM_transaction_is_write(const transaction_t *NOTNULL t);

bool
SIM_transaction_is_read(const transaction_t *NOTNULL t);

bool
SIM_transaction_is_inquiry(const transaction_t *NOTNULL t);

DESCRIPTION
SIM_transaction_flags returns a transaction_flags_t bitmap describing transaction type. Most of the flags can be queried using specific accessors.

The SIM_transaction_is_fetch function returns true if the transaction is an instruction fetch.

The SIM_transaction_is_read function returns true if the transaction is a read operation.

The SIM_transaction_is_write function returns true if the transaction is a write operation.

The SIM_transaction_is_inquiry function returns true if the transaction is an inquiry operation.

EXECUTION CONTEXT
All contexts (including Threaded Context)

SIM_transaction_initiator()

NAME
SIM_transaction_initiator — return transaction initiator
SYNOPSIS
conf_object_t *
SIM_transaction_initiator(const transaction_t *t);

DESCRIPTION
Return the initiator of the transaction.
EXECUTION CONTEXT
All contexts (including Threaded Context)

SIM_transaction_is_deferrable()

NAME
SIM_transaction_is_deferrable — check if a transaction can be deferred for later completion
SYNOPSIS
bool
SIM_transaction_is_deferrable(const transaction_t *NOTNULL t);

DESCRIPTION
The function allows to check whether a transaction can be deferred (with the SIM_defer_transaction or SIM_defer_owned_transaction function) for later completion which is done with a call to SIM_complete_transaction.

Usually, this function is not needed since SIM_defer_transaction and SIM_defer_owned_transaction return NULL for transactions that cannot be deferred.

RETURN VALUE
false if the transaction was issued synchronously and cannot be deferred. Otherwise, true. When a transaction cannot be deferred, endpoint's issue method of the transaction interface may choose to return the error status Sim_PE_Async_Required.
EXECUTION CONTEXT
Cell Context

SIM_transaction_size()

NAME
SIM_transaction_size — return transaction size
SYNOPSIS
unsigned
SIM_transaction_size(const transaction_t *NOTNULL t);

DESCRIPTION
Return the size of the transaction, in bytes.
EXECUTION CONTEXT
All contexts (including Threaded Context)

SIM_transaction_wait()

NAME
SIM_transaction_wait — wait for transaction completion
SYNOPSIS
exception_type_t
SIM_transaction_wait(transaction_t *t, exception_type_t ex);

DESCRIPTION
SIM_transaction_wait waits until an issued transaction has completed.

The function may only be invoked for transactions which have a completion atom containing a NULL pointer. The NULL pointer means that the initiator will wait for transaction completion using this function. Moreover, SIM_transaction_wait must always be called after a transaction has been issued with a NULL completion callback.

The ex argument should be the return value of the function or method used to issue the transaction.

SIM_transaction_wait will not return until the transaction has completed. While waiting, a different user-level thread will be activated, which allows simulated time to advance.

Note that the simulator cannot create a checkpoint while a call to the SIM_transaction_wait is in progress. See help transaction-wait-all-completed for more information related to checkpointing and SIM_transaction_wait.

Transaction wait is not supported from all contexts. When unsupported, the transaction will appear to be issued synchronously.

RETURN VALUE
Completion status of the transaction
EXECUTION CONTEXT
Cell Context

Memory Transactions

SIM_arm_mem_trans_from_generic()

NAME
SIM_arm_mem_trans_from_generic, SIM_mips_mem_trans_from_generic, SIM_ppc_mem_trans_from_generic, SIM_x86_mem_trans_from_generic, SIM_pci_mem_trans_from_generic — convert generic transaction to CPU specific
SYNOPSIS
struct arm_memory_transaction *
SIM_arm_mem_trans_from_generic(generic_transaction_t *NOTNULL mop);

struct mips_memory_transaction *
SIM_mips_mem_trans_from_generic(generic_transaction_t *NOTNULL mop);

struct ppc_memory_transaction *
SIM_ppc_mem_trans_from_generic(generic_transaction_t *NOTNULL mop);

struct x86_memory_transaction *
SIM_x86_mem_trans_from_generic(generic_transaction_t *NOTNULL mop);

struct pci_memory_transaction *
SIM_pci_mem_trans_from_generic(generic_transaction_t *NOTNULL mop);

DESCRIPTION
Converts a pointer to a generic memory transaction into a pointer to a CPU specific memory transaction. The generic memory transaction must be part of a CPU specific one for this function to succeed. The pointer returned will be the same the input pointer if conversion is allowed, and NULL on failure.
EXCEPTIONS
SimExc_Type Thrown if the generic transaction is not part of a CPU specific transaction.

RETURN VALUE
New memory transaction pointer, or NULL on error.

EXECUTION CONTEXT
Cell Context

SIM_c_get_mem_op_value_buf()

NAME
SIM_c_get_mem_op_value_buf, SIM_get_mem_op_value_buf, SIM_get_mem_op_value_cpu, SIM_get_mem_op_value_le, SIM_get_mem_op_value_be — get value for a memory operation
SYNOPSIS
void
SIM_c_get_mem_op_value_buf(const generic_transaction_t *NOTNULL mop,
                           uint8 *NOTNULL dst);

attr_value_t
SIM_get_mem_op_value_buf(const generic_transaction_t *NOTNULL mop);

uint64
SIM_get_mem_op_value_cpu(const generic_transaction_t *NOTNULL mop);

uint64
SIM_get_mem_op_value_le(const generic_transaction_t *NOTNULL mop);

uint64
SIM_get_mem_op_value_be(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
Returns load or store value for a memory transaction. If the data size is 8 bytes or less the SIM_get_mem_op_value_be and SIM_get_mem_op_value_le functions can be used. For reads/writes larger than 8 bytes, the functions SIM_c_get_mem_op_value_buf or SIM_get_mem_op_value_buf should be used to get the data.

If your model is compiled with one of the DEVICE_IS_LITTLE_ENDIAN, DEVICE_IS_BIG_ENDIAN pre-processor defines, then the SIM_get_mem_op_value function can be used as an alias to the SIM_get_mem_op_value_le and SIM_get_mem_op_value_be versions.

The SIM_c_get_mem_op_value_buf function is only available from C/C++. It places the data into the buffer pointed to by dst. No endian conversion is performed, i.e. data is returned in target endianness. There is no alignment requirement on the dst parameter.

WARNING
When called from a memory-hierarchy (timing-model) only store values can be retrieved, since the load has not yet performed. To get the load value, a snoop-device should be used.
RETURN VALUE
SIM_c_get_mem_op_value_buf returns nothing. The out parameter dst is filled with the data buffer of the memory transaction. SIM_get_mem_op_value_buf returns an attr_value_t (type data) containing the data buffer of the memory transaction. SIM_get_mem_op_value_be returns the zero-extended value in host endian order (interpreted as big endian) for the memory transaction. SIM_get_mem_op_value_le returns the zero-extended value in host endian order (interpreted as little endian). SIM_get_mem_op_value_cpu interprets the data in the default endian order for the initiating processor. This function can only be used for processor initiated memory operations. It is recommended that one of the other functions are used instead.

EXCEPTIONS
SimExc_Memory Thrown if the size of the operation is illegal.

EXECUTION CONTEXT
Cell Context

SIM_c_set_mem_op_value_buf()

NAME
SIM_c_set_mem_op_value_buf, SIM_set_mem_op_value_buf, SIM_set_mem_op_value_cpu, SIM_set_mem_op_value_le, SIM_set_mem_op_value_be — set value for a memory operation
SYNOPSIS
void
SIM_c_set_mem_op_value_buf(generic_transaction_t *NOTNULL mop,
                           const uint8 *NOTNULL src);

void
SIM_set_mem_op_value_buf(generic_transaction_t *NOTNULL mop,
                         attr_value_t value);

void
SIM_set_mem_op_value_cpu(generic_transaction_t *NOTNULL mop, uint64 value);

void
SIM_set_mem_op_value_le(generic_transaction_t *NOTNULL mop, uint64 value);

void
SIM_set_mem_op_value_be(generic_transaction_t *NOTNULL mop, uint64 value);

DESCRIPTION
Set the value returned to the requester of a memory operation. If the data size is 8 bytes or less the SIM_set_mem_op_value_be and SIM_set_mem_op_value_le functions can be used. For sizes larger than 8 bytes, the functions SIM_c_set_mem_op_value_buf or SIM_set_mem_op_value_buf should be used to set the data as an attr_value_t of data type.

If your model is compiled with one of the DEVICE_IS_LITTLE_ENDIAN, DEVICE_IS_BIG_ENDIAN pre-processor defines, then the SIM_set_mem_op_value function can be used as an alias to the SIM_set_mem_op_value_le and SIM_set_mem_op_value_be versions.

SIM_c_set_mem_op_value_buf is only available from C/C++, it operates on data in target endian order. There is no alignment requirement on the buf parameter.

SIM_set_mem_op_value_be takes data in host endian order and sets it in big-endian.

SIM_set_mem_op_value_le takes data in host endian order and sets it in little-endian.

SIM_set_mem_op_value_cpu takes data in host endian order and sets it in the default endian order for the initiating processor. This function can only be used for processor initiated memory operations. It is recommended that one of the other functions are used instead.

The functions that set the memory operation based on a value will truncate the representation of that value if the memory operation is smaller than 8 bytes.

WARNING
These functions cannot be called from a timing-model since the real operation will overwrite the value set. They should instead be used from a snoop-device.
EXCEPTIONS
SimExc_Memory Thrown if the size of the operation is illegal.

EXECUTION CONTEXT
Cell Context

SIM_get_mem_op_page_cross()

NAME
SIM_get_mem_op_page_cross — detect transaction split
SYNOPSIS
FORCE_INLINE unsigned
SIM_get_mem_op_page_cross(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
If a memory transaction was split because it straddled an MMU page, return 1 if it is the first part and 2 for the second. If the transaction was not split, return zero.
EXECUTION CONTEXT
Cell Context

SIM_get_mem_op_size()

NAME
SIM_get_mem_op_size — get transaction size
SYNOPSIS
FORCE_INLINE unsigned
SIM_get_mem_op_size(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
Retrieve the size, in bytes, of a memory transaction.
EXECUTION CONTEXT
Cell Context

SIM_get_mem_op_type()

NAME
SIM_get_mem_op_type — get type of transaction
SYNOPSIS
FORCE_INLINE mem_op_type_t
SIM_get_mem_op_type(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
This function returns the type of the memory transaction.
SEE ALSO
generic_transaction_t, SIM_set_mem_op_type
EXECUTION CONTEXT
Cell Context

SIM_get_mem_op_type_name()

NAME
SIM_get_mem_op_type_name — get name of memory operation type
SYNOPSIS
const char *
SIM_get_mem_op_type_name(mem_op_type_t type);

DESCRIPTION
Returns a string describing type or NULL if unknown.
EXECUTION CONTEXT
Cell Context

SIM_make_mem_op_write()

NAME
SIM_make_mem_op_write, SIM_make_mem_op_read — create a memory transaction
SYNOPSIS
generic_transaction_t
SIM_make_mem_op_write(physical_address_t addr, bytes_t data,
                      bool inquiry, conf_object_t *initiator);

generic_transaction_t
SIM_make_mem_op_read(physical_address_t addr, buffer_t buffer,
                     bool inquiry, conf_object_t *initiator);

DESCRIPTION
Create and return a memory transaction for writing data to addr, or reading from addr into buffer. The number of bytes to transfer is specified by data and buffer respectively. The initiator is the object issuing the transaction; it may be NULL.

These functions do not actually perform any memory operation; they just construct the generic_transaction_t that can be used in other calls.

The buffer argument must refer to an allocated buffer, and data must contain valid data. They must remain valid and allocated during the life-time of the returned value.

EXECUTION CONTEXT
All contexts (including Threaded Context)

SIM_mem_op_ensure_future_visibility()

NAME
SIM_mem_op_ensure_future_visibility — request transaction visibility
SYNOPSIS
FORCE_INLINE void
SIM_mem_op_ensure_future_visibility(generic_transaction_t *NOTNULL mop);

DESCRIPTION
Request that future accesses from the same virtual address (using a granularity given by the min_cacheline_size processor attribute) will be seen by the memory hierarchy. Otherwise, the simulator may cache accesses to this address for performance so that they are not seen by the memory model.
EXECUTION CONTEXT
Cell Context

SIM_mem_op_is_atomic()

NAME
SIM_mem_op_is_atomic — detect transaction atomicity
SYNOPSIS
FORCE_INLINE bool
SIM_mem_op_is_atomic(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
Return true if the transaction was part of an atomic instruction (usually a read followed by a write), false otherwise.
EXECUTION CONTEXT
Cell Context

SIM_mem_op_is_control()

NAME
SIM_mem_op_is_control — transaction control predicates
SYNOPSIS
FORCE_INLINE bool
SIM_mem_op_is_control(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
Checks whether mem_op is a control transaction (one that does not actually transfer any data, such as cache control operations).
EXECUTION CONTEXT
Cell Context

SIM_mem_op_is_data()

NAME
SIM_mem_op_is_data, SIM_mem_op_is_instruction — transaction data/instruction predicates
SYNOPSIS
FORCE_INLINE bool
SIM_mem_op_is_data(const generic_transaction_t *NOTNULL mop);

FORCE_INLINE bool
SIM_mem_op_is_instruction(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
These functions check whether mem_op is a data or an instruction transaction. Currently, the only transactions that are instruction transactions are instruction fetches.
EXECUTION CONTEXT
Cell Context

SIM_mem_op_is_from_cache()

NAME
SIM_mem_op_is_from_cache — Cache initiated transaction
SYNOPSIS
FORCE_INLINE bool
SIM_mem_op_is_from_cache(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
Checks whether mem_op is sent from a cache timing model.
EXECUTION CONTEXT
Cell Context

SIM_mem_op_is_from_cpu()

NAME
SIM_mem_op_is_from_cpu — CPU initiated transaction
SYNOPSIS
FORCE_INLINE bool
SIM_mem_op_is_from_cpu(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
Checks whether mem_op is sent from a processor.
EXECUTION CONTEXT
Cell Context

SIM_mem_op_is_from_cpu_arch()

NAME
SIM_mem_op_is_from_cpu_arch — CPU initiated transaction
SYNOPSIS
FORCE_INLINE bool
SIM_mem_op_is_from_cpu_arch(const generic_transaction_t *NOTNULL mop,
                            ini_type_t arch);

DESCRIPTION
Checks whether mem_op is sent from a processor of a specific architecture.
EXECUTION CONTEXT
Cell Context

SIM_mem_op_is_from_device()

NAME
SIM_mem_op_is_from_device — Device initiated transaction
SYNOPSIS
FORCE_INLINE bool
SIM_mem_op_is_from_device(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
Checks whether mem_op is sent from a device.
EXECUTION CONTEXT
Cell Context

SIM_mem_op_is_prefetch()

NAME
SIM_mem_op_is_prefetch — transaction control predicates
SYNOPSIS
FORCE_INLINE bool
SIM_mem_op_is_prefetch(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
Checks whether mem_op is prefetch transaction.
EXECUTION CONTEXT
Cell Context

SIM_mem_op_is_read()

NAME
SIM_mem_op_is_read, SIM_mem_op_is_write — transaction read/write predicates
SYNOPSIS
FORCE_INLINE bool
SIM_mem_op_is_read(const generic_transaction_t *NOTNULL mop);

FORCE_INLINE bool
SIM_mem_op_is_write(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
These functions check whether mem_op is a read or a write transaction.
EXECUTION CONTEXT
Cell Context

SIM_mem_op_may_stall()

NAME
SIM_mem_op_may_stall — detect transaction stall possibility
SYNOPSIS
FORCE_INLINE bool
SIM_mem_op_may_stall(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
If true, the simulator will allow the transaction to stall execution. When false, a memory hierarchy must not attempt any stalling.
EXECUTION CONTEXT
Cell Context

SIM_set_mem_op_exception()

NAME
SIM_set_mem_op_exception, SIM_get_mem_op_exception — get/set transaction exception
SYNOPSIS
FORCE_INLINE void
SIM_set_mem_op_exception(generic_transaction_t *NOTNULL mop,
                         exception_type_t exc);

FORCE_INLINE exception_type_t
SIM_get_mem_op_exception(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
Retrieve or change the transaction exception. If set to a value other than Sim_PE_No_Exception, the transaction will be interrupted and an exception will be taken.
EXECUTION CONTEXT
Cell Context

SIM_set_mem_op_initiator()

NAME
SIM_set_mem_op_initiator, SIM_get_mem_op_initiator, SIM_get_mem_op_ini_type — get/set transaction initiator
SYNOPSIS
FORCE_INLINE void
SIM_set_mem_op_initiator(generic_transaction_t *NOTNULL mop,
                         ini_type_t type, conf_object_t *obj);

FORCE_INLINE conf_object_t *
SIM_get_mem_op_initiator(const generic_transaction_t *NOTNULL mop);

FORCE_INLINE ini_type_t
SIM_get_mem_op_ini_type(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
Retrieve or change the transaction initiator type and object. These two parameters must agree.
EXECUTION CONTEXT
Cell Context

SIM_set_mem_op_inquiry()

NAME
SIM_set_mem_op_inquiry, SIM_get_mem_op_inquiry — get/set transaction inquiry flag
SYNOPSIS
FORCE_INLINE void
SIM_set_mem_op_inquiry(generic_transaction_t *NOTNULL mop, bool inquiry);

FORCE_INLINE bool
SIM_get_mem_op_inquiry(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
Retrieve or change the transaction inquiry flag. An inquiry read has no side-effects. An inquiry write has no other side-effect than changing the bytes at the specified address and size.
EXECUTION CONTEXT
Cell Context

SIM_set_mem_op_physical_address()

NAME
SIM_set_mem_op_physical_address, SIM_get_mem_op_physical_address, SIM_set_mem_op_virtual_address, SIM_get_mem_op_virtual_address — get or set transaction address
SYNOPSIS
FORCE_INLINE void
SIM_set_mem_op_physical_address(generic_transaction_t *NOTNULL mop,
                                physical_address_t pa);

FORCE_INLINE physical_address_t
SIM_get_mem_op_physical_address(const generic_transaction_t *NOTNULL mop);

FORCE_INLINE void
SIM_set_mem_op_virtual_address(generic_transaction_t *NOTNULL mop,
                               logical_address_t va);

FORCE_INLINE logical_address_t
SIM_get_mem_op_virtual_address(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
Retrieve or set the physical or virtual (logical) addresses of a memory transaction.
EXECUTION CONTEXT
Cell Context

SIM_set_mem_op_reissue()

NAME
SIM_set_mem_op_reissue — request transaction reissue
SYNOPSIS
FORCE_INLINE void
SIM_set_mem_op_reissue(generic_transaction_t *NOTNULL mop);

DESCRIPTION
Request that the transaction will be re-issued if a non-zero stall time is returned from a memory hierarchy. Otherwise, the memory model will not see the transaction again.
EXECUTION CONTEXT
Cell Context

SIM_set_mem_op_type()

NAME
SIM_set_mem_op_type — set type of transaction
SYNOPSIS
FORCE_INLINE void
SIM_set_mem_op_type(generic_transaction_t *NOTNULL mop, mem_op_type_t type);

DESCRIPTION
This function sets the type of the memory transaction.
SEE ALSO
generic_transaction_t, SIM_get_mem_op_type
EXECUTION CONTEXT
Cell Context

SIM_set_mem_op_user_data()

NAME
SIM_set_mem_op_user_data, SIM_get_mem_op_user_data — get/set transaction user data
SYNOPSIS
FORCE_INLINE void
SIM_set_mem_op_user_data(generic_transaction_t *NOTNULL mop,
                         void *data);

FORCE_INLINE void *
SIM_get_mem_op_user_data(const generic_transaction_t *NOTNULL mop);

DESCRIPTION
Retrieve or change user data associated with the transaction. This data is not touched by Simics in any way and its handling and interpretation is left to the user. It can be used to pass information from a timing model to a snoop device, but the data does not survive across a stall.
EXECUTION CONTEXT
Cell Context

Device Translators

SIM_free_map_target()

NAME
SIM_free_map_target — free a map target
SYNOPSIS
void
SIM_free_map_target(map_target_t *mt);

DESCRIPTION
Releases a map target and all associated resources.
EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_new_map_target

SIM_map_target_flush()

NAME
SIM_map_target_flush — ensure that old translations are not used
SYNOPSIS
bool
SIM_map_target_flush(const map_target_t *NOTNULL mt,
                     uint64 base, uint64 size, access_t access);

DESCRIPTION
This API function is intended to be used for the implementation the translation_flush interface. The documentation for the translation_flush interface describes how to use this function for the interface implementation.

Additionally, this function can be used as a replacement for the SIM_translation_changed function to do a more fine-grain invalidation in the case when a previously returned translation becomes invalid.

When a previously returned translation becomes invalid the translator object should notify Simics which can have translations cached. To notify Simics the translator object can either do the call to the SIM_translation_changed function or, as a potential performance optimization, do a more fine-grain invalidation by using the SIM_map_target_flush function.

The translator object is expected to call the SIM_map_target_flush function for all targets of all previously returned translations which became invalid. If there are too many translations which are to be invalidated, then, performance-wise, it may be better just to do a single call to the SIM_translation_changed function. Also, if, during invalidation, any of the calls to the SIM_map_target_flush fails (i.e. the false value is returned by the function) then the translator is expected to call the SIM_translation_changed function which always succeeds.

Please note that there is no need to call the SIM_map_target_flush function for the translations which were tagged with the Sim_Translation_Dynamic flag. Either, no invalidation is needed for the destinations where nothing is mapped.

EXECUTION CONTEXT
Cell Context

SIM_map_target_object()

NAME
SIM_map_target_object, SIM_map_target_port, SIM_map_target_target — inspect a map target
SYNOPSIS
conf_object_t *
SIM_map_target_object(const map_target_t *NOTNULL mt);

const char *
SIM_map_target_port(const map_target_t *NOTNULL mt);

const map_target_t *
SIM_map_target_target(const map_target_t *NOTNULL mt);

DESCRIPTION
Helper functions allowing inspection of the map_target_t objects.
RETURN VALUE
Returns a Simics object, port, or chained target which was used for the creation of the mt map target, i.e., the respective argument passed to SIM_new_map_target when the map target was created.
EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_new_map_target

SIM_new_map_target()

NAME
SIM_new_map_target — create a map target
SYNOPSIS
map_target_t *
SIM_new_map_target(conf_object_t *NOTNULL obj, const char *port,
                   const map_target_t *chained_target);

DESCRIPTION
Create and return a new map target. A map target can be viewed as an opaque representation of an object/interface pair which can function either as an endpoint for a memory transaction or as an address space where a memory transaction can be performed.

Map targets are usually used in conjunction with the translator interface and can represent anything which is mappable in a memory space, e.g., IO banks, RAM, ROM, memory spaces, port spaces, bridges, or translators. In order to get better performance, we recommend to allocate a map target once and reuse it rather than to allocate and delete it every time.

If the chained_target parameter is null, obj is searched for one of the following interfaces: ram, rom, io_memory, port_space, translator, transaction_translator, transaction or memory_space. The interfaces are tried in the listed order, and the first interface found determines the "type" of the map target. For example, if obj implements both the io_memory and the translator interface, then the created map target will direct memory transactions to the io_memory interface.

If a map target argument is passed in the chained_target parameter, then obj must implement one of the following interfaces: translator, bridge, or translate. The chained target contains information about a secondary map target used either directly or indirectly by the interface. For objects implementing the translator interface, the chained target is passed as an argument to the translate method. For bridges, the chained target is the target which is accessed through the bridge. For objects implementing translate, the chained target is used as the target of the translation if the translate method returns null.

Note: Information about the chained target is encoded in the created map target, but no direct references are kept to the argument. In other words, ownership is not transferred by this call and the caller is responsible for releasing chained_target as appropriate.

If a string is passed in the port parameter, then Simics looks for port interfaces instead of regular interfaces.

RETURN VALUE
Returns a map target, encoding information about the object, the interface, and the chained target, if any. NULL is returned if an exception was thrown.
EXCEPTIONS
SimExc_Lookup Thrown if no usable port interface was found.
EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_free_map_target, map_target_t, SIM_map_target_object, translator_interface_t

SIM_translation_changed()

NAME
SIM_translation_changed — ensure that old translations are not used
SYNOPSIS
void
SIM_translation_changed(conf_object_t *NOTNULL obj);

DESCRIPTION
Devices implementing the translator interface need to call this function whenever a previously returned translation becomes invalid; the only exception is if all invalid translations were tagged with Sim_Translation_Dynamic, in which case this is not necessary.

Failure to call this function will likely result in Simics continuing to use old translations, since those may have been cached internally.

The object implementing the translator should be passed in the obj parameter.

EXECUTION CONTEXT
Cell Context
SEE ALSO
translator_interface_t

Time and Events

SIM_cycle_count()

NAME
SIM_cycle_count — read cycle counter
SYNOPSIS
cycles_t  
SIM_cycle_count(conf_object_t *NOTNULL obj);

DESCRIPTION
SIM_cycle_count returns the current simulated clock cycle count at obj.

If obj is a cycle counter implementing either the cycle_event interface or the cycle interface, then the returned count is the number of elapsed cycles according to that object. If obj is not a cycle counter, then the default clock associated with the object is queried for its cycle count.

SEE ALSO
SIM_object_clock
RETURN VALUE
SIM_cycle_count returns the current time in number of cycles.
EXECUTION CONTEXT
Cell Context

SIM_event_cancel_time()

NAME
SIM_event_cancel_time, SIM_event_cancel_step — cancel an event before expiration
SYNOPSIS
void
SIM_event_cancel_time(conf_object_t *NOTNULL clock,
                      event_class_t *NOTNULL evclass,
                      conf_object_t *NOTNULL obj,
                      int (*pred)(lang_void *data, lang_void *match_data),
                      lang_void *match_data);

void
SIM_event_cancel_step(conf_object_t *NOTNULL clock,
                      event_class_t *NOTNULL evclass,
                      conf_object_t *NOTNULL obj,
                      int (*pred)(lang_void *data, lang_void *match_data),
                      lang_void *match_data);

DESCRIPTION
All unexpired evclass events posted for obj on clock for which pred returns nonzero will be cancelled and their destructor methods (if any) called. pred will be called with the data associated with the event and the supplied match_data. If pred is null (None in Python), all evclass events for obj on clock will be cancelled.

There are separate calls for events posted at a point in time (cycle or seconds) and on a specific step.

EXCEPTIONS
SimExc_InterfaceNotFound Thrown by SIM_event_cancel_step if the clock object doesn't implement the step interface.

EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_register_event, SIM_event_post_time

SIM_event_class_flags()

NAME
SIM_event_class_flags — get event class flags
SYNOPSIS
event_class_flag_t
SIM_event_class_flags(event_class_t *NOTNULL ec);

DESCRIPTION
Get the event class flags from a registered event class ec.
EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_register_event

SIM_event_find_next_cycle()

NAME
SIM_event_find_next_cycle, SIM_event_find_next_time, SIM_event_find_next_step — find event expiration time
SYNOPSIS
cycles_t
SIM_event_find_next_cycle(conf_object_t *NOTNULL clock,
                          event_class_t *NOTNULL evclass,
                          conf_object_t *NOTNULL obj,
                          int (*pred)(lang_void *data, lang_void *match_data),
                          lang_void *match_data);

double
SIM_event_find_next_time(conf_object_t *NOTNULL clock,
                         event_class_t *NOTNULL evclass,
                         conf_object_t *NOTNULL obj,
                         int (*pred)(lang_void *data, lang_void *match_data),
                         lang_void *match_data);

pc_step_t
SIM_event_find_next_step(conf_object_t *NOTNULL clock,
                         event_class_t *NOTNULL evclass,
                         conf_object_t *NOTNULL obj,
                         int (*pred)(lang_void *data, lang_void *match_data),
                         lang_void *match_data);

DESCRIPTION
Return the number of cycles/seconds/steps to the first event of evclass of obj posted on clock for which pred is true, or −1 if no event matched. pred will be called with the data associated with the event and the supplied match_data. If pred is null (None in Python), the first evclass event for obj on clock will be used.

There are separate calls of events posted at a point in time (cycle or seconds) and on a specific step. Note that the return value of SIM_event_find_next_cycle is only a preliminary estimate; the number of remaining cycles will change if the clock's frequency changes dynamically. To handle dynamically changing clock frequencies correctly, subscribe to the frequency changes via the clock's simple_dispatcher interface.

EXCEPTIONS
SimExc_InterfaceNotFound Thrown by SIM_event_find_next_step if the clock object doesn't implement the step interface: Minus one is returned in such a case.

EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_register_event, SIM_event_post_time

SIM_event_post_time()

NAME
SIM_event_post_time, SIM_event_post_cycle, SIM_event_post_step — post an event
SYNOPSIS
void 
SIM_event_post_time(conf_object_t *NOTNULL clock,
                    event_class_t *NOTNULL evclass,
                    conf_object_t *NOTNULL obj,
                    double seconds,
                    lang_void *user_data);

void
SIM_event_post_cycle(conf_object_t *NOTNULL clock,
                     event_class_t *NOTNULL evclass,
                     conf_object_t *NOTNULL obj,
                     cycles_t cycles,
                     lang_void *user_data);

void
SIM_event_post_step(conf_object_t *NOTNULL clock,
                    event_class_t *NOTNULL evclass,
                    conf_object_t *NOTNULL obj,
                    pc_step_t steps,
                    lang_void *user_data);

DESCRIPTION
An event of evclass for object obj is posted on clock to occur at a given point in the future. The user_data will be associated with the event.

The clock is the object that should be used for keeping track of time for the event. It can be a processor or an instance of the clock class.

If a configuration class was specified when evclass was registered, then obj must be an instance of that class.

The expiration point can be specified in seconds, cycles or steps by using the appropriate call, and these values are relative to the current state. Events that need to run synchronized (Sim_EC_Machine_Sync) can only be posted in seconds or cycles, not steps, since synchronization can only be perform in virtual time.

Note: Events posted with SIM_event_post_cycle are posted at a certain point in time based on the clock's current frequency, not at a certain clock cycle. The difference is significant if the frequency of the clock object can change dynamically.
EXCEPTIONS
SimExc_InterfaceNotFound
Thrown by SIM_event_post_step if the clock object doesn't implement the step interface.
SimExc_General
Thrown if the number of steps or time is negative or too far ahead, and, for Sim_EC_Machine_Sync events, if the event is posted less than a time quantum in the future.

EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_register_event, SIM_event_cancel_time

SIM_get_event_class()

NAME
SIM_get_event_class — get the event class
SYNOPSIS
event_class_t *
SIM_get_event_class(conf_class_t *NOTNULL cl, const char *NOTNULL name);

DESCRIPTION
Get an event class registered for a configuration class, as done by the SIM_register_event function. The cl is the configuration class and name is the name of the event class to retrieve.

If the event class cannot be found, NULL is returned.

EXECUTION CONTEXT
Cell Context
SEE ALSO
SIM_register_event

SIM_register_event()

NAME
SIM_register_event — register an event
SYNOPSIS
event_class_t *
SIM_register_event(
               const char *NOTNULL name,
               conf_class_t *cl,
               event_class_flag_t flags,
               void (*NOTNULL callback)(conf_object_t *obj, lang_void *data),
               void (*destroy)(conf_object_t *obj, lang_void *data),
               attr_value_t (*get_value)(conf_object_t *obj, lang_void *data),
               lang_void *(*set_value)(conf_object_t *obj, attr_value_t value),
               char *(*describe)(conf_object_t *obj, lang_void *data));

DESCRIPTION
Registers events identified by name and to be posted for objects of class cl, and returns the event class to be used in other calls. The supplied methods are:

callback
Called when the event expires.
destroy
Called when the event is removed from the queue without being called. The method is not allowed to use any event API calls; it is mainly intended for freeing event data. May be null.
get_value
Called to convert the event data into a value that can be saved in a configuration. May be null when the event carries no data of interest.
set_value
Called to convert a configuration value into event data. May be null when the event carries no data of interest.
describe
Called to generate a human-readable description of the event to be used in the print-event-queue command. If written in C, must return an allocated string (using MM_MALLOC or MM_STRDUP). May be null, in which case the name is used.

Null function pointers correspond to the value None when invoked from Python.

The flags are typically either zero or Sim_EC_Notsaved, where Sim_EC_Notsaved indicates that the event should not be saved as part of the configuration. In that case, get_value and set_value must both be null, and cl may also be null.

Additionally, the Sim_EC_No_Serialize flag can be used to specify that the event should not serialize the cell if Multicore Accelerator mode (MCA) is activated. This flag allows the event to run in a threaded context instead of the default cell context. As with all threaded context code, the event callback must protect against threading violations by using SIM_acquire_target and SIM_acquire_object. Setting this flag can significantly speed up the simulation if such events are posted frequently.

The other flag bits defined in event_class_flag_t are reserved for internal use in the Simics platform and some tightly coupled modules. See the event queue sample code for details on their use

EXECUTION CONTEXT
Global Context
SEE ALSO
SIM_event_post_time

SIM_run_unrestricted()

NAME
SIM_run_unrestricted — run callback after current instruction
SYNOPSIS
void
SIM_run_unrestricted(conf_object_t *NOTNULL obj,
                     void (*NOTNULL func)(conf_object_t *obj,
                                          lang_void *param),
                     lang_void *user_data);

DESCRIPTION
The func functions will be called immediately, if Simics is not currently running an instruction, or as soon as the current instruction has completed.

Note that with the introduction of Multicore Accelerator, if an instruction is running when calling SIM_run_unrestricted, other simulation threads may continue for a while until they stop and the callback is serviced. This means that an object using SIM_run_unrestricted may receive calls through for example the io_memory interface after returning from the scope where SIM_run_unrestricted is called but before the func callback function is called. For more information on considerations for Multicore Accelerator, see the Simics Model Builder User's Guide.

If several functions are registered this way before any of them has had a chance to run, the functions will be run in their order of registration.

This call is mainly useful for actions that for various reasons can not be done while an instruction is being emulated.

The obj is an object that has a clock (as defined by SIM_object_clock). This object and user_data are passed to the callback function.

Since the callback is run in Cell Context, simulation threads for other cells may be running when the callback is executed. Consequently, only objects in the same cell as obj may be accessed from the callback.

SEE ALSO
SIM_run_alone
EXECUTION CONTEXT
All contexts including Threaded Context (call); Cell Context (callback)

SIM_step_count()

NAME
SIM_step_count — get step count
SYNOPSIS
pc_step_t
SIM_step_count(conf_object_t *NOTNULL obj);

DESCRIPTION
Returns the number of steps executed by the processor obj. A step is a completed instruction, an instruction causing a synchronous exception, or an asynchronous exception (interrupt).
EXCEPTIONS
SimExc_InterfaceNotFound Thrown if the obj object doesn't implement the step interface. Minus one is returned in such a case.

EXECUTION CONTEXT
Cell Context

SIM_time()

NAME
SIM_time — get current simulated time
SYNOPSIS
double
SIM_time(conf_object_t *NOTNULL obj);

DESCRIPTION
SIM_time returns the current time at obj.

The returned time relates to how long the simulation has been running, and is usually not very useful in itself, but it can be used to compare with other times. The time on a specific processor is guaranteed to increase when simulation progresses, even if the clock frequency is changed. When adding a processor, it is assigned a current time to be synchronized with other processors in the simulation, or the time 0.0 if it is the first processor.

Note: The precision of the returned value degrades significantly with simulated time due to its representation as a double. When absolute timestamps are needed for the actual simulation, it is recommended that the SIM_cycle_count function is used instead on the picosecond clock.
Note: Using SIM_time on the picosecond clock will currently give the same result as SIM_time on the default clock. That is, the precision of this API function is limited by the frequency of the default clock.
SEE ALSO
SIM_picosecond_clock
RETURN VALUE
SIM_time returns the current time in seconds as a floating point value.
EXECUTION CONTEXT
Cell Context

Version and Copyrights

SIM_register_copyright()

NAME
SIM_register_copyright — register copyright information
SYNOPSIS
void
SIM_register_copyright(const char *NOTNULL str);

DESCRIPTION
This registers specific copyright information related to an extension module or similar component of Simics. The Simics front-end command "copyright" will list, in addition to Simics copyright notices, any registered notices from libraries or plug-ins that have added a string using this function.

The string should contain only standard ASCII characters, be pre-formatted for at most 80-character width terminal, be non-indented, and have no spurious new-line characters before or after the last line (except for the new-line that marks the end of the last line).

The string will not be copied so needs to be either static or a copy generated by the callee (preferably static).

EXECUTION CONTEXT
Global Context

SIM_version()

NAME
SIM_version, SIM_version_base, SIM_version_major, SIM_license, SIM_license_file, SIM_copyright, SIM_vmxmon_version — get Simics version and license/copyright information
SYNOPSIS
const char *
SIM_version();

const char *
SIM_version_base();

const char *
SIM_version_major();

void
SIM_license();

char *
SIM_license_file(const char *format);

char *
SIM_copyright();

char *
SIM_vmxmon_version();

DESCRIPTION
SIM_version
returns the version of all installed Simics products.
SIM_version_base
returns the version of the Simics base package only.
SIM_version_major
returns the current major version of Simics.
SIM_vmxmon_version
returns the version of the VMP kernel module loaded on the host machine. NULL is returned if the module is not loaded.
SIM_license_file
returns the filename of the currently applying License Agreement (SLA/EULA), if any is found. The format parameter can be either an empty string (text version) or "rtf" (RTF version).
returns the copyright notice for Simics.
SIM_license
doesn't return anything but prints out a short text describing licensing conditions.

SIM_version, SIM_version_base, SIM_version_major return a string owned by Simics. These strings must not be deallocated or modified by the caller.

SIM_vmxmon_version, SIM_license_file, and SIM_copyright return a newly allocated string which is owned by the caller. This means that when the function is called from C its return value should be later freed with the use of the MM_FREE macro.

EXECUTION CONTEXT
Global Context

3.3.1 frags_t

The frags_t data type is part of the Simics API. It is used to manipulate and modify network packets inside models efficiently. It is meant to replace DBuffer in network device models wherever appropriate. See the Model Builder User's Guide for an introduction to programming with frags_t.

Function List

frags_add()

NAME
frags_add — add data to a frags_t
SYNOPSIS
FORCE_INLINE void
frags_add(frags_t *buf, const void *data, size_t len);

DESCRIPTION
Append the new data data of size len to buf. A frags_t can hold up to 8 data fragments.
RETURN VALUE
None
EXECUTION CONTEXT
Cell Context
EXAMPLE
uint8 new_data[2] = { 7, 8 };
frags_add(&foo, new_data, sizeof(new_data));

SEE ALSO
frags_init_add, frags_init_add_from_frags, frags_add_from_frags

frags_add_from_frags()

NAME
frags_add_from_frags — append an existing frags_t to another
SYNOPSIS
FORCE_INLINE void
frags_add_from_frags(frags_t *dst, const frags_t *src,
                     size_t offset, size_t len);

DESCRIPTION
Append len bytes of the data at offset offset in src to dst.
RETURN VALUE
None
EXECUTION CONTEXT
Cell Context
EXAMPLE
frags_add_from_frags(&foo, &bar, 4, frags_len(&bar) - 4);

SEE ALSO
frags_init_add, frags_add, frags_init_add_from_frags

frags_extract()

NAME
frags_extract — extract the contents of a frags_t
SYNOPSIS
void frags_extract(const frags_t *buf, void *vdst);

DESCRIPTION
Copy the whole contents of buf to vdst. The destination buffer vdst should be large enough to contain all data in buf.

This function is completely equivalent to frags_extract_slice() with an offset and a length covering the whole contents of the frags_t, and is provided for convenience.

RETURN VALUE
None
EXECUTION CONTEXT
Cell Context
EXAMPLE
uint8 all_data[frags_len(&foo)];
frags_extract(&foo, all_data);

SEE ALSO
frags_extract_8, frags_extract_slice, frags_extract_alloc, frags_extract_slice_alloc

frags_extract_8()

NAME
frags_extract_8, frags_extract_be16, frags_extract_le16, frags_extract_be32, frags_extract_le32, frags_extract_be64, frags_extract_le64 — extract a value
SYNOPSIS
uint8 frags_extract_8(const frags_t *buf, size_t offset);

uint16 frags_extract_be16(const frags_t *buf, size_t offset);

uint16 frags_extract_le16(const frags_t *buf, size_t offset);

uint32 frags_extract_be32(const frags_t *buf, size_t offset);

uint32 frags_extract_le32(const frags_t *buf, size_t offset);

uint64 frags_extract_be64(const frags_t *buf, size_t offset);

uint64 frags_extract_le64(const frags_t *buf, size_t offset);

DESCRIPTION
Extract a 8, 16, 32 or 64 bits value in either big-endian (_be) or little-endian (_le) format from the contents of the frags_t buf at offset offset.
RETURN VALUE
Extracted value
EXECUTION CONTEXT
Cell Context
EXAMPLE
uint8  val8  = frags_extract_8(&frame, 1);
uint16 val16 = frags_extract_be16(&frame, 2);
uint32 val32 = frags_extract_le32(&frame, 4);
uint32 val64 = frags_extract_be64(&frame, 8);

SEE ALSO
frags_extract, frags_extract_slice

frags_extract_alloc()

NAME
frags_extract_alloc — return a copy of the contents of a frags_t
SYNOPSIS
void *frags_extract_alloc(const frags_t *buf);

DESCRIPTION
Return an allocated copy of the contents of buf. The buffer returned is allocated with MM_MALLOC(), and its ownership is passed to the caller, which should free it when appropriate.

This function is equivalent to allocating a buffer of the correct size with MM_MALLOC() followed by a call to frags_extract(), and is provided for convenience.

RETURN VALUE
A newly allocated copy of the contents
EXECUTION CONTEXT
Cell Context
EXAMPLE
uint8 *all = frags_extract_alloc(&foo);
/* ... */
MM_FREE(all);

SEE ALSO
frags_extract, frags_extract_slice, frags_extract_slice_alloc

frags_extract_slice()

NAME
frags_extract_slice — extract a slice of a frags_t
SYNOPSIS
void frags_extract_slice(const frags_t *buf, void *vdst, size_t offset, 
                         size_t len);

DESCRIPTION
Copy a slice of size len, starting at offset offset, of the contents of buf, to vdst. The destination buffer vdst should be able to contain at least len bytes.
RETURN VALUE
None
EXECUTION CONTEXT
Cell Context
EXAMPLE
uint8 some_data[16];
frags_extract_slice(&foo, some_data, 4, 16);

SEE ALSO
frags_extract_8, frags_extract, frags_extract_alloc, frags_extract_slice_alloc

frags_extract_slice_alloc()

NAME
frags_extract_slice_alloc — return a partial copy of the contents of a frags_t
SYNOPSIS
void *frags_extract_slice_alloc(const frags_t *buf, size_t offset, size_t len);

DESCRIPTION
Return an allocated copy of a slice of size len, starting at offset offset, of the contents of buf. The return value is allocated with MM_MALLOC(), and its ownership is passed to the caller, which should free it when appropriate.

This function is equivalent to allocating a buffer of the correct size with MM_MALLOC() followed by a call to frags_extract_slice(), and is provided for convenience.

RETURN VALUE
A newly allocated, partial copy of the data
EXECUTION CONTEXT
Cell Context
EXAMPLE
uint8 *slice = frags_extract_slice_alloc(&foo, 4, 16);
/* ... */
MM_FREE(slice);

SEE ALSO
frags_extract, frags_extract_slice, frags_extract_alloc

frags_init()

NAME
frags_init — initialize a frags_t
SYNOPSIS
FORCE_INLINE void frags_init(frags_t *buf);

DESCRIPTION
Initialize the frags_t buf. An alternative is to use the FRAGS_INIT constant value.
RETURN VALUE
None
EXECUTION CONTEXT
Cell Context
EXAMPLE
/* Initialization with frags_init() */
frags_t bar;
frags_init(&bar);

/* Initialization with FRAGS_INIT */
frags_t foo = FRAGS_INIT;

SEE ALSO
frags_init_add

frags_init_add()

NAME
frags_init_add — initialize a frags_t with an initial value
SYNOPSIS
FORCE_INLINE void
frags_init_add(frags_t *buf, const void *data, size_t len);

DESCRIPTION
Initialize the frags_t buf and set it to represent the initial data data of size len.

This function is exactly equivalent to using frags_init(), followed by frags_add(), and is provided for convenience.

RETURN VALUE
None
EXECUTION CONTEXT
Cell Context
EXAMPLE
frags_t baz;
uint8 data[5] = { 0, 1, 2, 3, 4 };
frags_init_add(&baz, data, sizeof(data));

SEE ALSO
frags_init, frags_add

frags_init_add_from_frags()

NAME
frags_init_add_from_frags — initialize a frags_t from another
SYNOPSIS
FORCE_INLINE void
frags_init_add_from_frags(frags_t *dst, const frags_t *src,
                          size_t offset, size_t len);

DESCRIPTION
Initialize dst and set its initial value to the data of size len starting at offset offset in src.

This function is exactly equivalent to using frags_init(), followed by frags_add_from_frags(), and is provided for convenience.

RETURN VALUE
None
EXECUTION CONTEXT
Cell Context
EXAMPLE
frags_t bat;
ASSERT(frags_len(&foo) > 16);
frags_init_add_from_frags(&bat, &foo, 16, frags_len(&foo) - 16);

SEE ALSO
frags_init_add, frags_add, frags_add_from_frags

frags_it()

NAME
frags_it — return an iterator
SYNOPSIS
FORCE_INLINE frags_it_t
frags_it(const frags_t *buf, size_t offset, size_t len);

DESCRIPTION
Return an iterator on the fragments that compose the data in buf, starting from offset offset and up to a length of len. To iterate on all the data in buf, offset should be set to 0 and len to the value returned by frags_len().
RETURN VALUE
An iterator on the fragments covering the desired data range
EXECUTION CONTEXT
Cell Context
EXAMPLE
unsigned sum = 0;
for (frags_it_t it = frags_it(&foo, 0, frags_len(&foo));
     !frags_it_end(it);
     it = frags_it_next(it)) {
        unsigned f_len = frags_it_len(it);
        const uint8 *f_data = frags_it_data(it);

        for (int i=0; i<f_len; i++)
                sum += f_data[i];
}

SEE ALSO
frags_it_end, frags_it_next, frags_it_len, frags_it_data

frags_it_data()

NAME
frags_it_data — return the data of the current fragment
SYNOPSIS
FORCE_INLINE const uint8 *
frags_it_data(frags_it_t it);

DESCRIPTION
Return a pointer to the data of the current fragment pointed by the iterator it.
RETURN VALUE
The data of the current fragment
EXECUTION CONTEXT
Cell Context
EXAMPLE
unsigned sum = 0;
for (frags_it_t it = frags_it(&foo, 0, frags_len(&foo));
     !frags_it_end(it);
     it = frags_it_next(it)) {
        unsigned f_len = frags_it_len(it);
        const uint8 *f_data = frags_it_data(it);

        for (int i=0; i<f_len; i++)
                sum += f_data[i];
}

SEE ALSO
frags_it, frags_it_end, frags_it_next, frags_it_len

frags_it_end()

NAME
frags_it_end — return whether an iterator is finished
SYNOPSIS
FORCE_INLINE bool 
frags_it_end(frags_it_t it);

DESCRIPTION
Return true when the iterator it does not have any next fragment to return at the next call of frags_it_next(), and false otherwise.
RETURN VALUE
true if the iterator is finished, false otherwise.
EXECUTION CONTEXT
Cell Context
EXAMPLE
unsigned sum = 0;
for (frags_it_t it = frags_it(&foo, 0, frags_len(&foo));
     !frags_it_end(it);
     it = frags_it_next(it)) {
        unsigned f_len = frags_it_len(it);
        const uint8 *f_data = frags_it_data(it);

        for (int i=0; i<f_len; i++)
                sum += f_data[i];
}

SEE ALSO
frags_it, frags_it_next, frags_it_len, frags_it_data

frags_it_len()

NAME
frags_it_len — return the length of the current fragment
SYNOPSIS
FORCE_INLINE size_t
frags_it_len(frags_it_t it);

DESCRIPTION
Return the length of the current fragment pointed by the iterator it.
RETURN VALUE
The length of the current fragment
EXECUTION CONTEXT
Cell Context
EXAMPLE
unsigned sum = 0;
for (frags_it_t it = frags_it(&foo, 0, frags_len(&foo));
     !frags_it_end(it);
     it = frags_it_next(it)) {
        unsigned f_len = frags_it_len(it);
        const uint8 *f_data = frags_it_data(it);

        for (int i=0; i<f_len; i++)
                sum += f_data[i];
}

SEE ALSO
frags_it, frags_it_end, frags_it_next, frags_it_data

frags_it_next()

NAME
frags_it_next — return the next fragment's iterator
SYNOPSIS
FORCE_INLINE frags_it_t
frags_it_next(frags_it_t it);

DESCRIPTION
Return an iterator pointing at the next data fragment. This function should only be called if frags_end(it) returns false.
RETURN VALUE
An iterator on the next fragment
EXECUTION CONTEXT
Cell Context
EXAMPLE
unsigned sum = 0;
for (frags_it_t it = frags_it(&foo, 0, frags_len(&foo));
     !frags_it_end(it);
     it = frags_it_next(it)) {
        unsigned f_len = frags_it_len(it);
        const uint8 *f_data = frags_it_data(it);

        for (int i=0; i<f_len; i++)
                sum += f_data[i];
}

SEE ALSO
frags_it, frags_it_end, frags_it_len, frags_it_data

frags_len()

NAME
frags_len — return the total data length
SYNOPSIS
FORCE_INLINE size_t frags_len(const frags_t *buf);

DESCRIPTION
Return the total length of the data represented by buf.
RETURN VALUE
The total data length
EXECUTION CONTEXT
Cell Context
EXAMPLE
unsigned len = frags_len(&foo);

frags_prefix()

NAME
frags_prefix — prefix a frags_t with a header
SYNOPSIS
FORCE_INLINE frags_t
frags_prefix(const void *header, size_t header_len, const frags_t *body);

DESCRIPTION
Create a frags_t composed of the header header of size header_len, followed by the contents of the frags_t body.

This function is equivalent to a sequence of frags_init(), frags_add(), frags_add_from_frags() to build a new fragment containing the prefix. It is provided for convenience.

RETURN VALUE
A new frags_t including header and body
EXECUTION CONTEXT
Cell Context
EXAMPLE
uint8 eth_header[14] = { 0 };
frags_t packet = frags_prefix(eth_header, sizeof(eth_header), &foo);

SEE ALSO
frags_suffix, frags_add_from_frags

frags_suffix()

NAME
frags_suffix — append a suffix to a frags_t
SYNOPSIS
FORCE_INLINE frags_t
frags_suffix(const frags_t *body, void *header, size_t header_len);

DESCRIPTION
Create a frags_t composed of the contents of the frags_t body, followed by the data header of size header_len.

This function is equivalent to a sequence of frags_init(), frags_add_from_frags(), frags_add() to build a new fragment containing the suffix. It is provided for convenience.

RETURN VALUE
A new frags_t including body and header
EXECUTION CONTEXT
Cell Context
EXAMPLE
uint8 eth_checksum[4] = { 0 };
frags_t frame = frags_suffix(&foo, eth_checksum, sizeof(eth_checksum));

SEE ALSO
frags_prefix, frags_add_from_frags

frags_t, frags_it_t

NAME
frags_t, frags_it_t
SYNOPSIS
typedef struct frags frags_t;

typedef struct frags_it frags_it_t;

DESCRIPTION
These types encapsulate a data packet, for use by models that send and receive data, such as network devices.

The structures should never be used directly. Only use the accessor functions.

3.3.2 Dynamic Memory Management

These are routines for manual dynamic memory allocation providing some memory leak detection. They replace the standard C malloc facility in Simics APIs.

Example: to allocate an array of 13 elements of type device_t, use

    device_t *d = MM_MALLOC(13, device_t);

It must be possible to get a pointer to the type by appending an asterisk to the type name; so struct foo * is acceptable, but int (*)(void) is not. Use a typedef in these cases.

It is not possible to mix these calls with the malloc facility for the same allocations.

Macro List

MM_FREE()

NAME
MM_FREE — free allocation
SYNOPSIS
MM_FREE(p);

DESCRIPTION
MM_FREE frees an allocation previously made with MM_MALLOC, MM_MALLOC_SZ, MM_ZALLOC, MM_ZALLOC_SZ, MM_REALLOC, MM_REALLOC_SZ or MM_STRDUP.

A null pointer argument is legal, in which case nothing happens.

MM_MALLOC()

NAME
MM_MALLOC, MM_MALLOC_SZ, MM_ZALLOC, MM_ZALLOC_SZ — allocate memory
SYNOPSIS
MM_MALLOC(nelems, type);

MM_MALLOC_SZ(size, type);

MM_ZALLOC(nelems, type);

MM_ZALLOC_SZ(size, type);

DESCRIPTION
MM_MALLOC allocates nelems objects of type type. MM_MALLOC_SZ specifies the total allocation size in bytes.

MM_ZALLOC and MM_ZALLOC_SZ do the same thing as MM_MALLOC and MM_ZALLOC respectively but in addition fill the allocated memory with null bytes.

If nelems or size are zero, either a null pointer or a pointer to a zero-sized allocation is returned.

RETURN VALUE
Pointer to the allocated object(s).
EXECUTION CONTEXT
All contexts (including Threaded Context)

MM_REALLOC()

NAME
MM_REALLOC, MM_REALLOC_SZ — reallocate memory
SYNOPSIS
MM_REALLOC(p, nelems, type);

MM_REALLOC_SZ(p, size, type);

DESCRIPTION
MM_REALLOC changes the size of an allocated memory block to nelems elements. MM_REALLOC_SZ specifies the new size in bytes.

The allocation must originally have been made by a call to MM_MALLOC, MM_MALLOC_SZ, MM_ZALLOC, MM_ZALLOC_SZ, MM_REALLOC, MM_REALLOC_SZ or MM_STRDUP.

If the passed pointer is null, then these macros are equivalent to an allocation of the desired amount. If nelems or size is zero, either a null pointer or a pointer to a zero-sized allocation is returned, and the original allocation is freed.

The allocation must be freed using MM_FREE.

RETURN VALUE
Pointer to the reallocated object(s).
EXECUTION CONTEXT
All contexts (including Threaded Context)

MM_STRDUP()

NAME
MM_STRDUP — duplicate a string
SYNOPSIS
MM_STRDUP(str);

DESCRIPTION
Allocates and initializes a copy of the null-terminated string str. The allocation must be freed with MM_FREE.
RETURN VALUE
Pointer to the newly allocated string.
EXECUTION CONTEXT
All contexts (including Threaded Context)

3.4 Obsolete Device API Types and Functions

The following types and functions are still available when a module is compiled for an obsolete API. Compiling for an obsolete API is described in the Model Builder User's Guide.

The DBuffer library is part of the Simics API. Up to Simics 4.0, it was the preferred method to transfer data blocks, such as network packets, inside the simulation. For code using the new link based on the link library, and for new models, we recommend using the frags_t data type instead.

3.4.1 Obsolete Device API Types

dbuffer_t

NAME
dbuffer_t
SYNOPSIS
typedef struct dbuffer dbuffer_t;

DESCRIPTION
This type is used to store blocks of binary data. It is optimized for fast adding and removing of data, and does fast copying between buffers using copy-on-write semantics.

The type is not inherently thread safe, so each instance must have a single thread as owner, and only the owner can read or write from the instance, however ownership can be transferred to another thread. To share the data with other threads, the instance must first be cloned using dbuffer_clone.

Note: This is a legacy data type. New code should use one of frags_t, bytes_t or buffer_t.

init_prefs_t

NAME
init_prefs_t
SYNOPSIS
typedef struct {
        bool batch_mode;
        bool quiet;
        bool verbose;
        bool python_verbose;
        bool disable_istc;
        bool disable_dstc;
        bool module_cache_enable;
        bool rdp;
        bool sign_module;
        const char *log_file;

        /* The Simics project to use */
        const char *project;       // NULL to use saved prefs value

        const char *package_list;  // internal, do not use

        bool no_windows;
        bool fail_on_warnings;
        const char *deprecation_level; // see sim->warn_deprecated
        bool warn_deprecated;       // same as deprecation_level == 2
        bool no_warn_deprecated;    // same as deprecation_level == 0

        bool warn_multithread;  /* deprecated and ignored (bug 21597) */
        bool check_ifaces;
        bool no_global_settings;    // do not read preferences and recent-files

        /* the following should be -1 if not set by command line options
           to tell SIM_init_simulator() to use the saved preference value */
        int log_enable;
} init_prefs_t;

DESCRIPTION
The init_prefs_t types are deprecated and should not be used in new code.

log_type_t

NAME
log_type_t
SYNOPSIS
typedef enum {
        Sim_Log_Info,           // Normal informational message
        Sim_Log_Error,          // Simics error
        Sim_Log_Spec_Violation, // target program violates the specification
        Sim_Log_Unimplemented,  // not implemented in Simics
        Sim_Log_Critical,       // Critical error stopping Simics
        Sim_Log_Trace,          // Breakpoint trace messages
        Sim_Log_Warning,        // Simics warning
        Sim_Log_Num_Types,      // Do not use
} log_type_t;

DESCRIPTION
This type defines different log types that are used by the logging facility to categorise messages.

3.4.2 Obsolete Device API Functions

SIM_is_loading_micro_checkpoint()

NAME
SIM_is_loading_micro_checkpoint — obsolete API function
SYNOPSIS
bool
SIM_is_loading_micro_checkpoint(conf_object_t *obj);

DESCRIPTION
Don't use. There is no longer a concept of micro-checkpoints after removal of reverse execution.
EXECUTION CONTEXT
Cell Context

dbuffer_append()

NAME
dbuffer_append, dbuffer_prepend, dbuffer_insert — Add data to a dbuffer
SYNOPSIS
uint8 *
dbuffer_append(dbuffer_t *dbuffer, size_t len);

uint8 *
dbuffer_prepend(dbuffer_t *dbuffer, size_t len);

uint8 *
dbuffer_insert(dbuffer_t *dbuffer, size_t offset, size_t len);

DESCRIPTION
These functions will extend the dbuffer with len bytes and return a pointer to the added bytes. The dbuffer_insert function adds the new data at offset in the buffer, while the dbuffer_prepend and dbuffer_append functions add it at the beginning and end, respectively.

The returned pointer points to a memory area that is only guaranteed to contain valid data for the newly added bytes, and it is illegal to reference data before it or more than len-1 bytes ahead. The new memory area is not guaranteed to be initialized.

The returned pointer is also only valid until the next operation on the dbuffer function, except for calling dbuffer_len.

dbuffer_append_external_data()

NAME
dbuffer_append_external_data, dbuffer_prepend_external_data — Add static data
SYNOPSIS
uint8 *
dbuffer_append_external_data(dbuffer_t *dbuffer, void *data,
                             size_t len, bool adopt);

uint8 *
dbuffer_prepend_external_data(dbuffer_t *dbuffer, void *data,
                              size_t len, bool adopt);

DESCRIPTION
These functions work similar to dbuffer_append and dbuffer_prepend, but with the difference that the data isn't copied. Instead, the buffer will reference the data pointed to directly.

If the adopt flag is true, the control of the data block is transferred to the dbuffer. It is assumed to be a block allocated with MM_MALLOC, and will be freed with MM_FREE when the dbuffer is released.

If the adopt flag is false, the dbuffer will not free the memory. Since there is no way to control the lifetime of the external reference if the dbuffer reference has been passed to another function, this option should never be used to point to memory on the stack or to memory that will eventually deallocated. Pointing to static memory is usually safe. This should also only be used for buffers that will only be read from, since there is no way to know when the external pointer is used, and when a copy is used.

SEE ALSO
dbuffer_append

dbuffer_append_value()

NAME
dbuffer_append_value, dbuffer_prepend_value — Add data with uniform content
SYNOPSIS
uint8 *
dbuffer_append_value(dbuffer_t *dbuffer, int value, size_t len);

uint8 *
dbuffer_prepend_value(dbuffer_t *dbuffer, int value, size_t len);

DESCRIPTION
This adds data to a dbuffer and sets all the added bytes to value. It has the same effect as using dbuffer_append or dbuffer_append and calling memset to set the contents.

The return value is a pointer to the data just added.

SEE ALSO
dbuffer_append

dbuffer_clone()

NAME
dbuffer_clone — Make a full copy of another buffer
SYNOPSIS
dbuffer_t *
dbuffer_clone(dbuffer_t *dbuffer);

DESCRIPTION
This function returns a new dbuffer that contains the same data as the buffer given in the dbuffer parameter. This doesn't involve copying any memory, since they can share the same storage initially. However, they are still completely independent, and operations on one buffer has no effect on the other.

The returned dbuffer should be released with dbuffer_free when it is no longer needed.

SEE ALSO
new_dbuffer, dbuffer_free

dbuffer_copy_append()

NAME
dbuffer_copy_append, dbuffer_copy_prepend — Copy data from a dbuffer
SYNOPSIS
void
dbuffer_copy_append(dbuffer_t *dst, dbuffer_t *src, size_t offset, size_t len);

void
dbuffer_copy_prepend(dbuffer_t *dst, dbuffer_t *src, size_t offset, size_t len);

DESCRIPTION
These functions copies len bytes from the dbuffer src, at offset offset, and adds it to the beginning or end of the dbuffer dst.

This can often be done without actually copying any memory, so it is usually very efficient.

SEE ALSO
dbuffer_append

dbuffer_free()

NAME
dbuffer_free — Release a dbuffer
SYNOPSIS
void
dbuffer_free(dbuffer_t *dbuffer);

DESCRIPTION
Release a dbuffer that will not be used anymore. This will also free any data in the buffer that isn't also used by other buffers. After calling this function, the dbuffer must not be used anymore.

See also src/include/simics/util/dbuffer.h

SEE ALSO
new_dbuffer

dbuffer_len()

NAME
dbuffer_len — Get the size of a dbuffer
SYNOPSIS
size_t
dbuffer_len(const dbuffer_t *dbuffer);

DESCRIPTION
This function returns the amount of data stored in a dbuffer. This is the number of bytes that will be returned by dbuffer_read_all.

dbuffer_read()

NAME
dbuffer_read, dbuffer_read_all, dbuffer_read_some — Extract data for reading
SYNOPSIS
const uint8 *
dbuffer_read(dbuffer_t *dbuffer, size_t offset, size_t len);

const uint8 *
dbuffer_read_all(dbuffer_t *dbuffer);

const uint8 *
dbuffer_read_some(dbuffer_t *dbuffer, size_t offset, size_t len,
                  size_t *actual_len);

DESCRIPTION
The offset and len parameters specify a region of the buffer to read from. The returned pointer is guaranteed to point to a contiguous block of memory of size len. It is illegal to write to the block return by these functions, since they may be shared by other dbuffers. Use the dbuffer_update functions if you need to both read and write to the dbuffer.

The returned pointer is only valid until the next operation on the dbuffer, except for calling dbuffer_len.

The offset and len must specify a valid region, so that the end of the region is not past the end of the dbuffer.

The dbuffer_read_some function takes an actual_len parameter, and may return a smaller buffer than requested. The actual number of valid bytes in the returned buffer is stored in *actual_len. It will return a smaller buffer if it would have had to copy memory to return a pointer to the whole region. This means that you can use this function repeatedly to extract all the requested data in the most efficient way. If NULL is passed for actual_len, it will return the full region.

The dbuffer_read_all function assumes 0 for offset, and buffer_len(dbuffer) for len.

SEE ALSO
dbuffer_update, dbuffer_replace

dbuffer_remove()

NAME
dbuffer_remove, dbuffer_remove_head, dbuffer_remove_tail — Remove data from a dbuffer
SYNOPSIS
void
dbuffer_remove(dbuffer_t *dbuffer, size_t offset, size_t remove_len);

void
dbuffer_remove_head(dbuffer_t *dbuffer, size_t remove_len);

void
dbuffer_remove_tail(dbuffer_t *dbuffer, size_t remove_len);

DESCRIPTION
These functions will remove remove_len bytes from dbuffer. The dbuffer_remove function will remove data starting at offset, while the other functions will remove data from the beginning or end of the buffer.

This usually doesn't involve moving any memory contents, and should be very efficient even if the buffer is large.

The size of data to remove must be available in the buffer. For example offset + remove_len must not be greater than the buffers length. Similarly for the dbuffer_truncate function there must be at least new_size bytes in the current buffer.

dbuffer_replace()

NAME
dbuffer_replace, dbuffer_replace_all, dbuffer_replace_some — Replace data
SYNOPSIS
uint8 *
dbuffer_replace(dbuffer_t *dbuffer, size_t offset, size_t len);

uint8 *
dbuffer_replace_all(dbuffer_t *dbuffer);

uint8 *
dbuffer_replace_some(dbuffer_t *dbuffer, size_t offset, size_t len,
                     size_t *actual_len);

DESCRIPTION
The offset and len parameters specify a region of the buffer to write to. The returned pointer is guaranteed to point to a contiguous block of memory of size len, but is not guaranteed to contain the existing data in the buffer. Use these functions when completely replacing a region of the buffer with new data.

The returned pointer is only valid until the next operation on the dbuffer, except for calling dbuffer_len.

The offset and len must specify a valid region, so that the end of the region is not past the end of the dbuffer.

The dbuffer_replace_some function takes an actual_len parameter, and may return a smaller buffer than requested. The actual number of valid bytes in the returned buffer is stored in *actual_len. It will return a smaller buffer if it would have had to copy memory to return a pointer to the whole region. This means that you can use this function repeatedly to write all the requested data in the most efficient way. If NULL is passed for actual_len, it will return the full region.

The dbuffer_replace_all function assumes 0 for offset, and buffer_len(dbuffer) for len.

SEE ALSO
dbuffer_read, dbuffer_update

dbuffer_split()

NAME
dbuffer_split — Split a dbuffer
SYNOPSIS
dbuffer_t *
dbuffer_split(dbuffer_t *dbuffer, size_t offset);

DESCRIPTION
This function returns a new dbuffer that contains the offset first bytes from dbuffer, and removes those bytes from dbuffer The effect is that the dbuffer is split in two halves, leaving the second half in the original dbuffer and returning the first half as a new dbuffer.

The returned dbuffer should be released with dbuffer_free when it is no longer needed.

SEE ALSO
new_dbuffer, dbuffer_free

dbuffer_update()

NAME
dbuffer_update, dbuffer_update_all, dbuffer_update_some — Extract data for updating
SYNOPSIS
uint8 *
dbuffer_update(dbuffer_t *dbuffer, size_t offset, size_t len);

uint8 *
dbuffer_update_all(dbuffer_t *dbuffer);

uint8 *
dbuffer_update_some(dbuffer_t *dbuffer, size_t offset, size_t len,
                    size_t *actual_len);

DESCRIPTION
The offset and len parameters specify a region of the buffer to access. The returned pointer is guaranteed to point to a contiguous block of memory of size len. The block can be used for reading and writing data to the dbuffer.

The returned pointer is only valid until the next operation on the dbuffer, except for calling dbuffer_len.

The offset and len must specify a valid region, so that the end of the region is not past the end of the dbuffer.

The dbuffer_update_some function takes an actual_len parameter, and may return a smaller buffer than requested. The actual number of valid bytes in the returned buffer is stored in *actual_len. It will return a smaller buffer if it would have had to copy memory to return a pointer to the whole region. This means that you can use this function repeatedly to access all the requested data in the most efficient way. If NULL is passed for actual_len, it will return the full region.

The dbuffer_update_all function assumes 0 for offset, and buffer_len(dbuffer) for len.

SEE ALSO
dbuffer_read, dbuffer_replace

new_dbuffer()

NAME
new_dbuffer — Create a new dbuffer
SYNOPSIS
dbuffer_t *
new_dbuffer();

DESCRIPTION
This function returns an empty dbuffer. Use it when you need a new dbuffer, and call dbuffer_free when it isn't needed anymore.

See also src/include/simics/util/dbuffer.h

SEE ALSO
dbuffer_free, dbuffer_clone

4 Model-to-Model Interfaces

a20

Description
This interface is used between the A20 line handling device (typically the keyboard controller) and the x86 processor. The processor implements this interface and the keyboard controller calls it.

SIM_INTERFACE(a20) {
        void (*set_a20_line)(conf_object_t *NOTNULL obj, int value);
        int (*get_a20_line)(conf_object_t *NOTNULL obj);
};

#define A20_INTERFACE "a20"

Execution Context
Cell Context for all methods.

apic_bus

Description
This interface is implemented by all apic buses, and used by the IO-APICs to send a message over the bus.

Messages with delivery mode Apic_Delivery_Mode_Ext_INT needs to be acknowledged. They are acknowledged at the object pointed to by the apic's "pic" attribute via the interrupt_cpu interface.

SIM_INTERFACE(apic_bus) {
        apic_bus_status_t (*interrupt)(conf_object_t *obj,
                                       apic_destination_mode_t dest_mode,
                                       apic_delivery_mode_t delivery_mode,
                                       int level_assert,
                                       apic_trigger_mode_t trigger_mode,
                                       uint8 vector,
                                       uint8 destination);
};

#define APIC_BUS_INTERFACE "apic_bus"

typedef enum {
        Apic_Destination_Mode_Physical = 0,
        Apic_Destination_Mode_Logical = 1
} apic_destination_mode_t;

typedef enum {
        Apic_Delivery_Mode_Fixed = 0,
        Apic_Delivery_Mode_Lowest_Priority = 1,
        Apic_Delivery_Mode_SMI = 2,
        Apic_Delivery_Mode_Remote_Read = 3,
        Apic_Delivery_Mode_NMI = 4,
        Apic_Delivery_Mode_INIT = 5,
        Apic_Delivery_Mode_Start_Up = 6,
        Apic_Delivery_Mode_Ext_INT = 7
} apic_delivery_mode_t;

typedef enum {
        Apic_Trigger_Mode_Edge = 0,
        Apic_Trigger_Mode_Level = 1
} apic_trigger_mode_t;

typedef enum {
        Apic_Bus_Accepted = 0,
        Apic_Bus_Retry = 1,
        Apic_Bus_No_Target = 2,
        Apic_Bus_Invalid = 3
} apic_bus_status_t;

See the architecture software developer's manual for more information about the parameters. For IPIs, the sender is responsible for filtering out reserved vectors (vectors 0 through 15) and flagging the appropriate error on the sending side. For I/O-APIC initiated interrupts, reserved vectors can be sent and will flag errors in the receiving APICs.

Execution Context
Cell Context for all methods.

apic_cpu

Description
This interface is implemented by the local APIC device and is used by the processor and machine initialization code to interact with the local APIC.

The tpr_r and tpr_w methods read and write the task priority register. The format of the tpr argument and the returned value from tpr_r is the same as for CR8, meaning TPR[bits 7:4], zero extended to 64 bits.

Interrupts coming from the CPU itself are passed via the local_int function. The type of interrupt is one of the constants defined in local_apic_interrupt_t.

typedef enum {
        Apic_Lvt_2e = 0x2e0,
        Apic_CMCI = 0x2f0,
        Apic_Performance_Counter = 0x340,
        Apic_Thermal_Sensor = 0x330
} local_apic_interrupt_t;

The init function is called by the CPU when it receives the INIT signal. The APIC should only update its internal state and not propagate this signal further. Both the CPU and the APIC should reset their pending interrupt flags when this function is called. The init function is not called at instantiation time.

The power_on function is called at machine creation time, and the call initializes the APIC to the power on state. The bsp argument is true if the APIC is connected to the boot processor, and false otherwise. The initial APIC ID is set through the apic_id argument. The power_on function would typically be called from component code for the processor that includes the APIC.

The enabled_r method returns bit 11 from the APIC BASE MSR, and is used by the processor to return the correct status for CPUID.

SIM_INTERFACE(apic_cpu) {
        uint64 (*tpr_r)(conf_object_t *NOTNULL obj);
        void (*tpr_w)(conf_object_t *NOTNULL obj, uint64 tpr);
        void (*local_int)(conf_object_t *NOTNULL obj,
                          local_apic_interrupt_t int_type);
        void (*power_on)(conf_object_t *NOTNULL obj, bool bsp, int apic_id);
        void (*init)(conf_object_t *NOTNULL obj);
        bool (*enabled_r)(conf_object_t *NOTNULL obj);
};

#define APIC_CPU_INTERFACE "apic_cpu"

Execution Context
Cell Context for all methods.

arinc429_bus

Description
SIM_INTERFACE(arinc429_bus) {
    void (*send_word)(conf_object_t *bus, uint32 word, int parity_ok);
};

Interface to Arinc-429 serial buses.

The send_word function is used by a device to send an Arinc-429 formatted word. The most significant bit (bit 31) is the parity bit, but if the device have checksumming built in, it can set parity_ok to tell the bus to ignore bit 31 of the data.

If the parity bit is already calculated, pass -1 as parity_ok.

Execution Context
Cell Context for all methods.

arinc429_receiver

Description
SIM_INTERFACE(arinc429_receiver) {
    void (*receive_word)(conf_object_t *dev, uint32 word, int parity_ok);
};

Interface to Arinc-429 compatible receivers.

The receive_word is called when there is traffic on the bus. word contains the data received (with valid parity bit), and the parity_ok tells whether the parity of the word is correct or not.

Execution Context
Cell Context for all methods.

arm

Description
This interface is implemented by ARM processors to provide various functionality that is specific for this class of processors.

The read_register_mode and write_register_mode functions are used to access banked copies of the registers. They are used just like the int_register interface read and write functions, except that they take an extra parameter mode that specifies which register bank should be used. mode should be the mode bits in the cpsr corresponding to the mode shifted right to bits 0-4.

SIM_INTERFACE(arm) {
        uint64 (*read_register_mode)(conf_object_t *processor_obj,
                                     int reg_num, int mode);
        void (*write_register_mode)(conf_object_t *processor_obj,
                                    int reg_num, int mode, uint64 value);
};

#define ARM_INTERFACE "arm"

Execution Context
Cell Context for all methods.

arm_avic

Description
The ARM AVIC interface makes it possible for an ARM processor to get the interrupt vector address from an AVIC device connected to the processor core. Both processor and AVIC must enable the AVIC interface to support this feature.

The processor calls get_interrupt_address function to get the interrupt vector address. The AVIC returns an arm_avic_t struct with a valid field and an address field, the address field is only valid when the valid is not 0.

typedef struct arm_avic {
        int valid;
        uint32 address;
} arm_avic_t;

SIM_INTERFACE(arm_avic) {
        arm_avic_t (*get_interrupt_address)(conf_object_t *obj);
};

#define ARM_AVIC_INTERFACE "arm_avic"

Execution Context
Cell Context for all methods.

arm_coprocessor

Description
A coprocessor for the ARM has to provide the arm_coprocessor_interface. This interface defines the functions that will be called when the coprocessor instructions (cdp, ldc, mcr, mrc, mrrc, mcrr, stc) are executed.

The read_register_64_bit and write_register_64_bit are used for mrrc and mccr instructions which read and write 64 bit values in to two registers.

The interface also defines a flag, finished, which indicates whether a memory transfer operation is finished or not.

The function reset is called when the cpu is reset, and allows the coprocessor to also do a reset, the argument hard_reset indicates whether the reset was soft (0) or hard (1).

SIM_INTERFACE(arm_coprocessor) {
        void (*process_data)(conf_object_t *NOTNULL obj,
                             uint32 CRd,
                             uint32 opcode_1,
                             uint32 CRn,
                             uint32 CRm,
                             uint32 opcode_2,
                             int type);
        void (*load_coprocessor)(conf_object_t *NOTNULL obj,
                                 uint32 CRd,
                                 uint32 N,
                                 uint32 Options,
                                 uint32 value,
                                 int type);

        uint32 (*read_register)(conf_object_t *NOTNULL obj,
                                uint32 opcode_1,
                                uint32 CRn,
                                uint32 CRm,
                                uint32 opcode_2,
                                int type);
        void (*write_register)(conf_object_t *NOTNULL obj,
                               uint32 value,
                               uint32 opcode_1,
                               uint32 CRn,
                               uint32 CRm,
                               uint32 opcode_2,
                               int type);
        uint64 (*read_register_64_bit)(conf_object_t *NOTNULL obj,
                                       uint32 opcode_1,
                                       uint32 CRm,
                                       int type);
        void (*write_register_64_bit)(conf_object_t *NOTNULL obj,
                                      uint64 value,
                                      uint32 opcode_1,
                                      uint32 CRm,
                                      int type);
        uint32 (*store_coprocessor)(conf_object_t *NOTNULL obj,
                               uint32 CRd,
                               uint32 N,
                               uint32 Options,
                               int type);
        void (*reset)(conf_object_t *NOTNULL obj, int hard_reset);
};

#define ARM_COPROCESSOR_INTERFACE "arm_coprocessor"

Execution Context
Cell Context for all methods.

arm_cpu_group_event

Description
This interface is only intended to be used between Arm CPU objects. It contains the functions needed for cross-CPU communication related to event signalling.

signal_event notifies the CPU to set the event register.

SIM_INTERFACE(arm_cpu_group_event) {
        void (*signal_event)(conf_object_t *obj);
};

#define ARM_CPU_GROUP_EVENT_INTERFACE "arm_cpu_group_event"

Execution Context
Threaded Context for all methods.

arm_cpu_group_exclusive

Description
This interface is only intended to be used between Arm CPU objects. It contains the functions needed for cross-CPU communication related to exclusive memory accesses.

mark_exclusive notifies the CPU that another CPU has marked the address range as exclusive. The CPU must then probe all CPUs in the CPU group for exclusive address ranges using probe_exclusive and possibly invalidate them using clear_exclusive before accessing the address range.

clear_and_probe_exclusive notifies the CPU to invalidate any exclusive address ranges that it has overlapping the specified clear address range. Also returns true if the CPU still has any exclusive address ranges overlapping the specified probe address range.

SIM_INTERFACE(arm_cpu_group_exclusive) {
        void (*mark_exclusive)(
                conf_object_t *obj,
                physical_address_t address,
                physical_address_t size);
        bool (*clear_and_probe_exclusive)(
                conf_object_t *obj,
                physical_address_t clear_address,
                physical_address_t clear_size,
                physical_address_t probe_address,
                physical_address_t probe_size);
};

#define ARM_CPU_GROUP_EXCLUSIVE_INTERFACE "arm_cpu_group_exclusive"

Execution Context
Threaded Context for all methods.

arm_cpu_group_tlb

Description
This interface is only intended to be used between Arm CPU objects. It contains the functions needed for cross-CPU communication related to TLB invalidation.

invalidate_tlb notifies the CPU to invalidate TLB entries related to the translation regime. If by_virtual_address is true only entries containing the specified virtual address should be invalidated, otherwise all entries should be invalidated.

SIM_INTERFACE(arm_cpu_group_tlb) {
        void (*invalidate_tlb)(
                conf_object_t *obj,
                arm_translation_regime_t translation_regime,
                bool by_virtual_address,
                logical_address_t virtual_address);
};

#define ARM_CPU_GROUP_TLB_INTERFACE "arm_cpu_group_tlb"

Execution Context
Threaded Context for all methods.

arm_external_debug

Description
This arm_external_debug interface is used for external debug feature.

The handle_semihosting function is called whenever the aarch64 instruction hlt 0xf000 is executed where semihosting is enabled for use.

The read_reg function is called reading the registers in external debug device.

The write_reg function is called writing the registers in external debug device.

Execution Context
Cell Context for all methods.

arm_gic

Description
This arm_gic interface is used accessing registers in a device implementing the Generic Interrupt Controller architecture..

The read_register function is called reading the registers in GIC device.

The write_register function is called writing the registers in GIC device.

The cpu_state_changed function is called to notify the GIC device that the cpu has changed state. This function is only called when the cpu changes state with an interrupt pending.

Execution Context
Cell Context for all methods.

arm_gic_cpu_state

Description
This arm_gic_cpu_state interface is used providing cpu states for a device implementing the Generic Interrupt Controller architecture.

The get_cpu_state_info function is called to get current state of the a CPU, e.g. exception level, secure mode.

Execution Context
Cell Context for all methods.

arm_trustzone

Description
This interface is implemented by ARM processors that supports the arm ARM TrustZone feature. The get_security_mode function returns the current state of the processor, whereas mem_op_security_mode extracts the mode of a memory operation in progress.

The get_security_mode functions corresponds to the expression (cpsr.mode != Monitor && scr.ns) ? Arm_Trustzone_Non_Secure : Arm_Trustzone_Secure. The mem_op_security_mode function always returns Arm_Trustzone_Non_Secure when the processor is in non-secure mode, in secure mode it returns the ns bit in the first-level page table entry for the actual area being accessed.

typedef enum {
        Arm_Trustzone_Secure = 0,
        Arm_Trustzone_Non_Secure = 1
} arm_trustzone_mode_t;

SIM_INTERFACE(arm_trustzone) {
        arm_trustzone_mode_t (*get_security_mode)(conf_object_t *NOTNULL obj);
        arm_trustzone_mode_t (*mem_op_security_mode)(
                conf_object_t *NOTNULL obj,
                generic_transaction_t *NOTNULL memop);
};

#define ARM_TRUSTZONE_INTERFACE "arm_trustzone"

Execution Context
Cell Context for all methods.

bridge

Description
The bridge interface is implemented by objects that bridge between memory spaces. The not_taken function is called if the access is not claimed by any device in the destination memory-space. If a memory transaction reaches a mapping that has the same bridge object as the previous mapping, the access is considered as not taken, and the not_taken function for the first bridge mapping is called.
SIM_INTERFACE(bridge) {
        exception_type_t (*not_taken)(conf_object_t *NOTNULL obj,
                                      conf_object_t *NOTNULL src_space,
                                      conf_object_t *NOTNULL dst_space,
                                      exception_type_t ex,
                                      generic_transaction_t *NOTNULL mem_op,
                                      map_info_t mapinfo);
};

#define BRIDGE_INTERFACE "bridge"

Execution Context
Cell Context for all methods.

can_device

Description
SIM_INTERFACE(can_device) {
        void (*receive)(conf_object_t *obj, can_frame_t *frame);
};
#define CAN_DEVICE_INTERFACE "can_device"

The can_device interface is implemented by CAN controllers. The receive function is called by can-endpoint to pass CAN frame from other can-endpoint to the connected CAN controller.

The CAN frame is expressed by the frame parameter, which is a pointer of can_frame_t. The following is the details of can_frame_t:

  • Standard Format:
    Arbitration Field(11bit_ID+RTR)+Control Field(IDE+r0+DLC)
  • Extended Format:
    Arbitration Field(11bit_sID+SRR+IDE+18bit_eID+RTR)+Control Field(r1+r0+DLC)
Above are the Arbitration Field and Control Field of the physical Standard frame and Extended frame. But the can_frame_t only focus on the logical meanings of such fields and tries to adapt different CAN controllers:
  • identifier: For Standard frame, 11bit_ID should be put in identifier[10:0];for Extended frame, 11bit_sID should be put in identifier[28:18] and 18bit_eID should be put in identifier[17:0].
  • extended: There isn't IDE in can_frame_t, instead, extended is used to indicate if the frame is Extended frame or Standard frame.
  • rtr: There isn't SRR in can_frame_t for Extended frame, instead, rtr is used to indicate if the frame is a remote frame or not. Here we don't care whether the frame is Extended frame or Standard frame.
  • data_length: The data_length contains the arithmetic value of the DLC.
  • data[CAN_DATA_MAX_NUM]: This is the data field of Date frame.
  • crc: This is the crc field of a CAN frame.
typedef struct {
        /* arbitration field */
        uint32 identifier;
        bool extended;
        bool rtr;
        /* control field */
        uint8 data_length;
        /* data field */
        uint8 data[CAN_DATA_MAX_NUM];
        /* crc field */
        uint16 crc;
} can_frame_t;

Execution Context
Cell Context for all methods.

can_link

Description
SIM_INTERFACE(can_link) {
        can_status_t (*send)(conf_object_t *obj, can_frame_t *frame);
};
#define CAN_LINK_INTERFACE "can_link"

The can_link interface is implemented by can-endpoint. The send function is called by CAN controller to pass CAN frame to the connected can-endpoint. Then can-link delivers the CAN frame to other can-endpoints.

Execution Context
Cell Context for all methods.

coreint

Description
Interface between CoreInt capable processor and interrupt controller.

This interface is implemented by CoreInt capable interrupt controllers and allows the processor to automatically acknowledge external interrupts without software intervention.

The acknowledge function is called by the processor when an external interrupt is taken. If coreint is enabled in the interrupt controller, the interrupt controller should lower the interrupt signal towards the processor and return the interrupt source vector. This way the software doesn't have to go and query the interrupt controller for the source. If coreint is not enabled, the interrupt should not do anything and the vector value in the reply is undefined.

#include <simics/pywrap.h>
#include <simics/base/types.h>

#if defined(__cplusplus)
extern "C" {
#endif

typedef struct {
        bool enabled;
        uint64 vector;
} coreint_reply_t;

#define COREINT_INTERFACE "coreint"
SIM_INTERFACE(coreint) {
        coreint_reply_t (*acknowledge)(conf_object_t *obj, conf_object_t *core);
};

Execution Context
Cell Context for all methods.

cxl_map

Description
This interface is used to claim ranges in CXL address spaces.

Functions add_map and del_map are used to add and remove maps, map_obj will be mapped in the address space indicated by type according to the information in info.

Note: This interface is considered tech-preview and may change without notice.

typedef enum {
        CXL_Type_Not_Set,
        CXL_Type_Io,
        CXL_Type_Mem,
        CXL_Type_Cache,
        CXL_Type_Other,
} cxl_type_t;

SIM_INTERFACE(cxl_map)
{
        void (*add_map)(conf_object_t *obj, conf_object_t *map_obj,
                        map_info_t info, cxl_type_t type);
        void (*del_map)(conf_object_t *obj, conf_object_t *map_obj,
                        physical_address_t base, cxl_type_t type);
};

#define CXL_MAP_INTERFACE "cxl_map"

Execution Context
Cell Context for all methods.

cxl_mem_downstream_port_managing

Description
Functions enable_decoder and disable_decoder are used to enable and disable HDM decoders on a cxl-hdm-port device.

SIM_INTERFACE(cxl_mem_downstream_port_managing)
{
        bool (*register_port_mem_obj)(conf_object_t *obj, uint8 port_number,
                                      conf_object_t *port_mem_obj);
        void (*unregister_port_mem_obj)(conf_object_t *obj, uint8 port_number);
};

#define CXL_MEM_DOWNSTREAM_PORT_MANAGING_INTERFACE "cxl_mem_downstream_port_managing"

Execution Context
Cell Context for all methods.

cxl_non_device_decoder_handling

Description
Functions enable_decoder and disable_decoder are used to enable and disable HDM decoders on a cxl-hdm-port device.

SIM_INTERFACE(cxl_non_device_decoder_handling)
{
        int (*enable_decoder)(conf_object_t *obj, uint8 index, uint8 ig,
                              uint8 iw, uint64 base, uint64 size,
                              uint64 target_list);
        int (*disable_decoder)(conf_object_t *obj, uint8 decoder_index);
};

#define CXL_NON_DEVICE_DECODER_HANDLING_INTERFACE "cxl_non_device_decoder_handling"

Execution Context
Cell Context for all methods.

datagram_link

Description
SIM_INTERFACE(datagram_link) {
        /* Transmit a message to the object. */
        void (*receive)(conf_object_t *NOTNULL obj, bytes_t msg);
};

#define DATAGRAM_LINK_INTERFACE "datagram_link"

This interface is implemented by objects that receive messages from a datagram-link, and by the datagram-link connection endpoints themselves.

There is a single function receive(), which is used to pass the message msg to the object obj.

The message msg is treated as a series of bytes with no special format or meaning expected. If obj is a datagram-link endpoint, it will forward the message to all other endpoints registered on the link except the sender, effectively broadcasting the message on the link. If obj is a device, it will simply receive the message as sent by the original sender.

Note that the symmetry of the interface allows two devices to be connected directly to each other and talk as if connected via a datagram-link. This is however not supported by the default datagram-link component, so a special connector must be created for this purpose. Additionally, the standard link features, such as multicell configurations and latency, will not be available in that setup.

Execution Context
receiveCell Context

ethernet_cable

Description
SIM_INTERFACE(ethernet_cable) {
        void (*link_status)(conf_object_t *NOTNULL ep, bool link_up);
};
#define ETHERNET_CABLE_INTERFACE "ethernet_cable"

This interface is implemented by Ethernet devices and link endpoints that are interested in the link status of the peer.

The link_status function is used to notify the peer that the link status at the local end is up or down. The ethernet-cable-link class propagates this information to the device connected at the other end.

Execution Context
link_statusCell Context

ethernet_common

Description
SIM_INTERFACE(ethernet_common) {
        void (*frame)(conf_object_t *NOTNULL obj, const frags_t *frame,
                      eth_frame_crc_status_t crc_status);
};
#define ETHERNET_COMMON_INTERFACE "ethernet_common"

This interface is implemented by objects that receive Ethernet frames, both Ethernet devices and Ethernet link endpoints.

There is a single function frame which sends an Ethernet frame, without preamble nor SFD (Start Frame Delimiter), but with a CRC field.

The crc_status parameter provides out-of-band information on the contents of the frame with regards to the CRC field using one of the values in the eth_frame_crc_status_t enum:

  • Eth_Frame_CRC_Match means that the frame contents are correct. The CRC field in the frame should not be relied upon as its computation may have been skipped for optimization, and it may contain any value, including zero, a random value or a correctly computed CRC.
  • Eth_Frame_CRC_Mismatch means that the frame contents are incorrect. The CRC field in the frame must contain a CRC that does not match the frame contents, i.e., to send an incorrect frame on the link, you must make sure that the CRC field will not match when computed.
  • Eth_Frame_CRC_Unknown means that the relation between the frame contents and the CRC field is unknown. The relation can be established by computing the frame's CRC and comparing it to the frame's CRC field.
typedef enum {
        Eth_Frame_CRC_Match,
        Eth_Frame_CRC_Mismatch,
        Eth_Frame_CRC_Unknown
} eth_frame_crc_status_t;

When a device calls a link's frame function, it can set crc_status to any of the three values. If the link receives a Eth_Frame_CRC_Unknown, it will compute the CRC itself to set the status to Eth_Frame_CRC_Match or Eth_Frame_CRC_Mismatch.

When a link calls a device's frame function, crc_status will be set to either Eth_Frame_CRC_Match or Eth_Frame_CRC_Mismatch, and never Eth_Frame_CRC_Unknown.

When two devices are directly connected to each others without using a link, the interpretation of Eth_Frame_CRC_Unknown is up to the devices' implementation.

Execution Context
frameCell Context

ethernet_probe

Description
//:: pre eth_probe_side_t {{
typedef enum {
        Eth_Probe_Port_A = 0,
        Eth_Probe_Port_B = 1
} eth_probe_side_t;
// }}

//:: pre ethernet_probe_snoop_t {{
typedef void (*ethernet_probe_snoop_t)(lang_void *user_data,
                                       conf_object_t *probe,
                                       eth_probe_side_t to_side,
                                       const frags_t *frame,
                                       eth_frame_crc_status_t crc_status);

//:: pre ethernet_probe_interface_t_def {{
SIM_INTERFACE(ethernet_probe) {
        void (*attach_snooper)(conf_object_t *NOTNULL probe,
                               ethernet_probe_snoop_t snoop_fun,
                               lang_void *user_data);
        void (*attach_probe)(conf_object_t *NOTNULL probe,
                             ethernet_probe_snoop_t snoop_fun,
                             lang_void *user_data);
        void (*detach)(conf_object_t *NOTNULL probe);
        void (*send_frame)(conf_object_t *NOTNULL probe,
                           eth_probe_side_t to_side,
                           const frags_t *frame,
                           eth_frame_crc_status_t crc_status);
};

#define ETHERNET_PROBE_INTERFACE "ethernet_probe"
// }}

This interface is implemented by eth-probe objects. Once a probe has been inserted between a device and an Ethernet link, the functions of this interface can be used to setup callbacks:

attach_snooper()
Attach a snooper function: the probe will pass each frame to the snooper function, then forward it unchanged where it should be going
attach_probe()
Attach a probe function: the probe will pass each frame to the probe function, and give it the responsibility of forwarding the frame or any number of modified or additional frames using the send_frame() function.
detach
Detach the currently registered callback from the probe.
send_frame
Send a frame via the probe, either to the side A or B of the probe. Which side is which can be obtained with the <eth-probe>.info function.

This interface should only be used for inspection, and never as part of the actual simulation. The snoop functions must not affect the simulation in any way.

The clock parameter tells the link on which clock to post the events that call the snoop function. The snoop function will be called at the delivery time of the network packet, which means that it will be called at the same time as any Ethernet devices attached to the same clock that receives packets from the same link.

Snooped frames with a matching CRC will contain the correct frame check sequence.

The user_data parameter is passed to the snoop function every time it is called.

Execution Context
Cell Context for all methods.

ethernet_snoop

Description
typedef void (*ethernet_link_snoop_t)(lang_void *user_data,
                                      conf_object_t *clock,
                                      const frags_t *packet,
                                      eth_frame_crc_status_t crc_status);

//:: pre ethernet_snoop_interface_t {{
SIM_INTERFACE(ethernet_snoop) {
        conf_object_t *(*attach)(conf_object_t *NOTNULL link,
                                 conf_object_t *clock,
                                 ethernet_link_snoop_t snoop_fun,
                                 lang_void *user_data);
};
#define ETHERNET_SNOOP_INTERFACE "ethernet_snoop"
// }}

This interface is implemented by Ethernet link objects. It is used to attach snoop functions to the link. The snoop function will receive all traffic going over the link.

This interface should only be used for inspection, and never as part of the actual simulation. The snoop functions must not affect the simulation in any way.

The clock parameter tells the link on which clock to post the events that call the snoop function. The snoop function will be called at the delivery time of the network packet, which means that it will be called at the same time as any Ethernet devices attached to the same clock that receives packets from the same link.

Snooped frames with a matching CRC will contain the correct frame check sequence.

The user_data parameter is passed to the snoop function every time it is called.

Execution Context
attachGlobal Context

ethernet_vlan_snoop

Description
typedef void (*ethernet_link_snoop_t)(lang_void *user_data,
                                      conf_object_t *clock,
                                      const frags_t *packet,
                                      eth_frame_crc_status_t crc_status);

SIM_INTERFACE(ethernet_vlan_snoop) {
        conf_object_t *(*attach)(
                conf_object_t *NOTNULL link, conf_object_t *clock,
                ethernet_link_snoop_t snoop_fun, lang_void *user_data,
                uint16 vlan_id, bool is_vlan_trunk);
};
#define ETHERNET_VLAN_SNOOP_INTERFACE "ethernet_vlan_snoop"

This interface is implemented by Ethernet VLAN switch link objects. It is used to attach snoop functions to the link. The snoop function will receive all traffic going over the link, either on a single VLAN, or on all of them.

This interface should only be used for inspection, and never as part of the actual simulation. The snoop functions must not affect the simulation in any way.

The clock parameter tells the link on which clock to post the events that call the snoop function. The snoop function will be called at the delivery time of the network packet, which means that it will be called at the same time as any Ethernet devices attached to the same clock that receives packets from the same link.

Snooped frames with a matching CRC will contain the correct frame check sequence.

The user_data parameter is passed to the snoop function every time it is called.

The vlan_id indicates on which VLAN the snoop function should be attached (as its native VLAN).

The is_vlan_trunk flag indicates whether the snoop function should also receive the traffic on all other VLANs, tagged with an 802.1Q tag.

Execution Context
attachGlobal Context

extended_serial

Description
This interface extends the serial_device with a write_at() function. It is similar to the write() function of the mentioned interface, but accepts an on-screen character position. This interface is implemented by text consoles allowing them to be connected to text oriented frame buffers, such as VGA in text mode.

SIM_INTERFACE(extended_serial) {
        void (*write_at)(conf_object_t *obj,
                         int value, int x, int y, int fg, int bg);
        void (*graphics_mode)(conf_object_t *obj, int in_graphics_mode);
};

#define EXTENDED_SERIAL_INTERFACE "extended_serial"

Execution Context
Cell Context for all methods.

firewire_bus

Description
SIM_INTERFACE(firewire_bus) {
        int (*connect_device)(conf_object_t *NOTNULL bus,
                              conf_object_t *NOTNULL dev);
        int (*disconnect_device)(conf_object_t *NOTNULL bus,
                                 conf_object_t *NOTNULL dev);
        void (*set_device_bus_id)(conf_object_t *NOTNULL bus,
                                  conf_object_t *NOTNULL dev,
                                  uint16 bus_id);

        void (*set_id_mask)(conf_object_t *NOTNULL bus,
                            conf_object_t *NOTNULL dev,
                            uint16 id_mask);

        firewire_ack_code_t (*transfer)(conf_object_t *NOTNULL bus,
                                        conf_object_t *NOTNULL source,
                                        dbuffer_t *packet, int crc_calculated);

        int (*register_channel)(conf_object_t *NOTNULL bus,
                                conf_object_t *NOTNULL dev,
                                uint32 channel);
        int (*unregister_channel)(conf_object_t *NOTNULL bus,
                                  conf_object_t *NOTNULL dev,
                                  uint32 channel);

        void (*reset)(conf_object_t *NOTNULL bus);
};
#define FIREWIRE_BUS_INTERFACE "firewire_bus"

This interface must be implemented by all firewire buses.

connect_device is called when a device wants to connect to the bus. The bus should return 0 upon success.

disconnect_device is called when a device wants to disconnect from the bus. The bus should return 0 upon success.

set_device_bus_id sets the bus id for the device. This needs to be called by a device when its Node_IDS[bus_id] field is updated. The new bus id should be placed in bits 15-6 in the bus_id argument.

set_id_mask can be called by a device to specify a mask that should be applied to the device ID when routing transfers. This can be used to e.g. accept transfers to multiple bus-numbers.

transfer sends a packet. The bus will route the transfer to the correct device(s). The source parameter should be set to the device which sent the transfer. The bus uses this parameter to avoid sending packets to their sender. If the crc_calculated argument is non-zero the packet's crc fields are filled in.The return code is one of:

typedef enum {
        /* Values defined in the FireWire specification */
        Firewire_Ack_Complete = 1,
        Firewire_Ack_Pending = 2,
        Firewire_Ack_Busy_X = 4,
        Firewire_Ack_Busy_A = 5,
        Firewire_Ack_Busy_B = 6,
        Firewire_Ack_Tardy = 0xb,
        Firewire_Ack_Conflict_Error = 0xc,
        Firewire_Ack_Data_Error = 0xd,
        Firewire_Ack_Type_Error = 0xe,
        Firewire_Ack_Address_Error = 0xf,
        
        /* Values not defined in FireWire but used in Simics */
        Firewire_Ack_No_Destination = 0x10, /* no destination found */
        Firewire_Ack_No_Ack = 0x11 /* no ack signal sent for packet */
} firewire_ack_code_t;

register_channel can be called to tell the bus that the device want to receive isochronous transfers to channel channel. channel must be in the range [0, 63). A device can register several channels. It is an error to subscribe a device to a channel it is already subscribed to. Returns 0 on success.

unregister_channel tells the bus the device is no longer interested in transfers to channel channel. channel must be in the range [0, 63). It is an error to unsubscribe a device from a channel if it isn't subscribing to it. Returns 0 on success.

reset can be called to cause a bus reset. After the bus reset, all the devices may have received new IDs.

Execution Context
Cell Context for all methods.

firewire_device

Description
SIM_INTERFACE(firewire_device) {
        firewire_ack_code_t (*transfer)(conf_object_t *NOTNULL dev,
                                        dbuffer_t *packet, int crc_calculated);

        void (*reset)(conf_object_t *NOTNULL dev, uint16 id,
                      uint8 root_id,
                      uint32_array_t self_ids);
        uint32 (*get_self_id_template)(
                conf_object_t *NOTNULL dev);

        int (*get_rhb)(conf_object_t *NOTNULL dev);
        uint8 (*get_port_count)(conf_object_t *NOTNULL dev);
        uint16 (*get_port_mask)(conf_object_t *NOTNULL dev);
};
#define FIREWIRE_DEVICE_INTERFACE "firewire_device"

This interface must be implemented by all firewire devices.

transfer is called when the device receives a packet. If the crc_calculated argument is non-zero the packet's crc fields are filled in.The return code is one of:

typedef enum {
        /* Values defined in the FireWire specification */
        Firewire_Ack_Complete = 1,
        Firewire_Ack_Pending = 2,
        Firewire_Ack_Busy_X = 4,
        Firewire_Ack_Busy_A = 5,
        Firewire_Ack_Busy_B = 6,
        Firewire_Ack_Tardy = 0xb,
        Firewire_Ack_Conflict_Error = 0xc,
        Firewire_Ack_Data_Error = 0xd,
        Firewire_Ack_Type_Error = 0xe,
        Firewire_Ack_Address_Error = 0xf,
        
        /* Values not defined in FireWire but used in Simics */
        Firewire_Ack_No_Destination = 0x10, /* no destination found */
        Firewire_Ack_No_Ack = 0x11 /* no ack signal sent for packet */
} firewire_ack_code_t;

reset is called when the bus is reset. id is the new ID of the device (top 10 bits represent the bus number, and the low 6 bits the node ID). root_id is the node ID for the root node. self_ids is the list of Self-ID packets during the Self-ID phase of the reset.

An array of unsigned 32-bit integers.

typedef struct {
        size_t len;
        uint32 *data;
} uint32_array_t;

get_self_id_template is an accessor function called by the bus or other self-ID provider to provide the static parts of the Self-ID for this device. The ID and port parts will be overwritten by the Self-ID provider.

get_rhb gets the current status of the root hold off bit in the device.

get_port_count returns the number of ports the device has. The largest allowed value is 16 and the lowest 1. This should remain constant during the lifetime of the device and always return a valid value.

get_port_mask returns a bitmask. Each bit is one if that port is enabled and zero if it is disabled. The least significant bit describes port 0 and the most significant bit port 15. The bits for ports which do not exist on the device should be set to zero.

Execution Context
Cell Context for all methods.

fmn_station_control

Description
The fmn_station_control interface is implemented by Fast Messaging Network stations for processors prior to the XLP II.

For all functions, the thread_id parameter denotes the thread id for the core that invokes the call.

The send_message function notifies the station to initiate a message send on the FMN. The rt_value parameter carries control bits and the message to send; its content and bit layout is determined by the system architecture. The return value indicates whether the FMN station is able to send the message. The station must check for available resources and immediately return 1 if the message will be queued for delivery, otherwise, if the station is not ready or if no buffers are available, the station immediately returns 0.

The load_message function notifies the station to initiate a message load on the FMN. The bucket indicates the FMN station bucket to read from.

The wait function is used by the core to probe the station if it should put itself to sleep waiting for a message or not. Each bit in the vector corresponds to a bucket to check for messages, i.e. bit 0 corresponds to bucket 0. The station must return 0 if there are any messages in any of the buckets requested. The station must return 1 if there are no messages in any of the buckets. Returning 1 means that the core can go to sleep until the station wakes the core. The station must later send a wake signal to the core when a new message arrive to any of the buckets checked in the last call to wait. The station wakes the core by raising the signal on the wakeup port interface for the core.

The sync function enforces a hazard barrier across the send_message function executions, thereby enforcing a strict ordering of the message sequence delivered to the FMN.

SIM_INTERFACE(fmn_station_control) {
        uint64 (*send_message)(conf_object_t *NOTNULL obj,
                               uint32 thread_id,
                               uint64 rt_value);
        void (*load_message)(conf_object_t *NOTNULL obj,
                             uint32 thread_id,
                             uint8 bucket);
        int (*wait)(conf_object_t *NOTNULL obj,
                    uint32 thread_id,
                    uint8 vector);
        void (*sync)(conf_object_t *NOTNULL obj,
                     uint32 thread_id);

};
#define FMN_STATION_CONTROL_INTERFACE "fmn_station_control"

Execution Context
Cell Context for all methods.

fmn_station_control_v2

Description
The fmn_station_control_v2 interface is implemented by Fast Messaging Network stations for the XLP II processor.

For all functions, the thread_id parameter denotes the thread id for the core that invokes the call.

The send_message function is called when the processor executes the msgsnd instruction. The rt_value parameter contains the value of the rt register. The function must return the value to be written into the rd register.

The load_message function is called when the processor executes the msgld instruction. The rt_value parameter contains the value of the rt register. The function must return the value to be written into the rd register.

The wait function is called when the processor executes the msgwait instruction. The rt_value parameter contains the value of the rt register. The function should return 1 if the receive queues are empty, 0 if not. If the receive queues are empty the station must wake the thread by raising the signal on the wakeup port of the thread when the next message arrives to one of the receive queues.

The sync function is called when the processor executes the msgsync instruction.

SIM_INTERFACE(fmn_station_control_v2) {
        uint64 (*send_message)(conf_object_t *NOTNULL obj,
                               uint32 thread_id,
                               uint64 rt_value);
        uint64 (*load_message)(conf_object_t *NOTNULL obj,
                               uint32 thread_id,
                               uint64 rt_value);
        int (*wait)(conf_object_t *NOTNULL obj,
                    uint32 thread_id,
                    uint64 rt_value);
        void (*sync)(conf_object_t *NOTNULL obj,
                     uint32 thread_id);
};
#define FMN_STATION_CONTROL_V2_INTERFACE "fmn_station_control_v2"

Execution Context
Cell Context for all methods.

frequency

Description
The frequency interface is used to publish a frequency to other objects.

The get method returns the current frequency.

The object implementing this interface is expected to implement the Sim_Notify_Frequency_Change notifier, which should be raised when the object changes its frequency. Objects subscribing to this notifier can acquire the new frequency by doing a new call to the get method.

SIM_INTERFACE(frequency) {
        double (*get)(conf_object_t *NOTNULL obj);
};
#define FREQUENCY_INTERFACE "frequency"

Execution Context
Cell Context for all methods.

frequency_listener

Description
The frequency_listener interface is used for modeling frequency changes.

The frequency change initiator should call set() to set the new frequency. The set() function may be called multiple times with the same frequency value. The frequency is specified by the numerator and denominator arguments in units of Hz.

The set() function should also be used to set the initial value for a target.

An object that implements the frequency_listener interface typically has an attribute that refers to an object and port that implements the simple_dispatcher interface, from where the frequency originates.

The initiator of a frequency change should implement the simple_dispatcher interface, and it should only call the set() function on objects that have registered with this interface.

SIM_INTERFACE(frequency_listener) {
        void (*set)(conf_object_t *NOTNULL obj, uint64 numerator,
                    uint64 denominator);
};

#define FREQUENCY_LISTENER_INTERFACE "frequency_listener"

Execution Context
Cell Context for all methods.

generic_message_device

Description
SIM_INTERFACE(generic_message_device) {
        void (*receive_frame)(conf_object_t *dev, conf_object_t *link,
                              dbuffer_t *frame);
};

#define GENERIC_MESSAGE_DEVICE_INTERFACE "generic_message_device"

This interface is implemented by generic message device objects that connect to generic-message-link objects. It is used by the link object to send messages to the device object. The link should implement the generic_message_link interface.

The receive_frame function is called by the link to send a frame to the device. The frame is passed as a dbuffer_t pointer that may not be modified without cloning it first.

Execution Context
receive_frameCell Context

generic_message_link

Description
SIM_INTERFACE(generic_message_link) {
#ifndef PYWRAP
        int  (*connect_device)(conf_object_t *_obj, conf_object_t *dev,
                               int *new_connection, uint32 address);
        void (*disconnect_device)(conf_object_t *_obj, conf_object_t *dev);
#endif
        void (*send_frame)(conf_object_t *_obj, int id, uint32 address,
                           dbuffer_t *frame, nano_secs_t delay);
};

#define GENERIC_MESSAGE_LINK_INTERFACE "generic_message_link"

Note: This interface is used for gml-link which is based on the link library. Refer to the Link Library for more information.
This interface is implemented by generic message link objects that provide a data link layer interface for frame delivery. It is used by the device object to talk to the link object. The device must implement the generic_message_device interface.

The connect_device function attaches a generic link device to the link. The return value is an identification number that should be used in subsequent calls to the link to identify the device. The address parameter sets the address of the device on the link. Currently the new_connection parameter is not in use, a NULL pointer can be passed as the parameter.

The disconnect_device function detaches a generic link device from the link. It will not receive any more frames from the link and may not call any functions in the interface, except connect_device.

The send_frame function is used by a device to send a generic device frame onto the link to be delivered to another device connected to the same link. The frame should be a dbuffer_t containing a data frame. The address parameter is the address to sent the frame to. The delay makes it possible to add a small delay to the frame. This can be used when a device wants to send multiple frames at once, but want them to be delivered in a specific sequence. Instead of using an event handler to send each frame, they can be sent at once, with an increasing delay for each frame. The delay is given in nanoseconds.

Execution Context
connect_deviceGlobal Context
disconnect_deviceGlobal Context
send_frameCell Context

hpi

Description
This interface defines HPI, Host Port Interface, which can be used by a host to access the DSP memory space. The access functions have been designed to resemble the HPI hardware interface.

The interface consists of three read/write access functions; read/write_hpic() accesses the HPI controller register. Typically the host uses write_hpic() to clear the HINT bit (writing a one to the bit) when the interrupt has been serviced.

The read/write_hpia() functions are used to read or set the address to the memory location which should be later read or written. Reading HPIA either returns HPIAR or HPIAW depending on if last access to HPID was a read or write. Setting HPIA sets both HPIAR and HPIAW.

Finally, to access the memory the read/write_hpid() functions are used. These functions have a autoincrement flag allowing the HPIAR or HPIAW to automatically increment the value with 4 after the access is finished.

All access functions assumes that the registers and data are represented in host endianness.

SIM_INTERFACE(hpi) {
        /* HCNTL = 0 */
        uint32 (*read_hpic)(conf_object_t *obj);
        void  (*write_hpic)(conf_object_t *obj, uint32 value);
        
        /* HCNTL = 1 */
        uint32 (*read_hpia)(conf_object_t *obj);
        void  (*write_hpia)(conf_object_t *obj, uint32 value);
        
        /* HCNTL = 1 (autoincrement == 0) */
        /* HCNTL = 2 (autoincrement == 1) */
        uint32 (*read_hpid)(conf_object_t *obj, int autoincrement);
        void  (*write_hpid)(conf_object_t *obj, uint32 value,
                            int autoincrement);        
};

#define HPI_INTERFACE "hpi"

Execution Context
Cell Context for all methods.

i2c_master_v2

Description
typedef enum {
        I2C_ack = 0,
        I2C_noack = 1
} i2c_ack_t;

SIM_INTERFACE(i2c_master_v2) {
        void (*acknowledge)(conf_object_t *device, i2c_ack_t ack);
        void (*read_response)(conf_object_t *device, uint8 value);
};

#define I2C_MASTER_V2_INTERFACE "i2c_master_v2"

The i2c_master_v2 interface should be implemented by devices that intend to act as a master on an I2C link.

The function acknowledge is called in response to a start or write call in the i2c_slave_v2 interface of the slave device. read_response is called as response to a read call. More details can be found in the documentation of the i2c_slave_v2 interface.

Execution Context
Cell Context for all methods.

i2c_slave_v2

Description
SIM_INTERFACE(i2c_slave_v2) {
        void (*start)(conf_object_t *device, uint8 address);
        void (*read)(conf_object_t *device);
        void (*write)(conf_object_t *device, uint8 value);
        void (*stop)(conf_object_t *device);
        attr_value_t (*addresses)(conf_object_t *device);
};
#define I2C_SLAVE_V2_INTERFACE "i2c_slave_v2"

The i2c_slave_v2 interface is used together with the i2c_master_v2 interface to model communication over an I2C bus. Most calls to a method in the i2c_slave_v2 interface expect a response call to a method in the i2c_master_v2 interface. It is up to each device to find the caller's interface; usually it is configured with an attribute in both the master and slave device.

The i2c_slave_v2 and i2c_master_v2 interfaces replace the obsolete interfaces i2c_master, i2c_slave, i2c_link, and i2c_bridge.

An I2C bus consists of a number of master devices and a number of slave devices. Each slave device listens to one or more 7-bit addresses or 10-bit addresses. It is an error to connect two slave devices to the same bus if they listen to the same address. Communication over the bus is initiated by a master, which can communicate with one slave device at a time. Only one master on a bus can communicate at a time.

Two I2C devices can communicate directly if one implements the i2c_master_v2 interface and the other one implements the i2c_slave_v2 interface. An I2C bus with multiple masters or slaves is typically modeled using an i2c-link-v2 object, where each device is connected to an endpoint object.

The start method starts a transfer. The address parameter is the address of the slave device, encoded as an 8-bit number. To communicate with 7-bit address slave device, using little-endian bit numbering, bit 0 is a read/write bit (0 → master writes, 1 → master reads) and bits 1 to 7 is the 7-bit address of the slave device. The address parameter should normally be in the (inclusive) range 0x10 - 0xef; the ranges 0x00 - 0x0f and 0xf0 - 0xff are reserved for special addressing modes. To communicate with 10-bit address slave device, using little-endian bit numbering, bit 0 is a read/write bit (same as 7-bit address), bits 1 to 2 is part of 10-bit address, and bits 3 to 7 is 10-bit address mode 0b11110.

The slave responds to start using the acknowledge method. The ack parameter may be I2C_ack or I2C_noack if the start is acked or noacked, respectively. In a multi-master configuration, the slave may instead respond by calling the start method in the i2c_slave_v2 interface of the master device; this signals that the master lost the bus arbitration. This is discussed further below.

If a start was acked by a slave device, read/write bit in the start method was 1, the master proceeds with a sequence of read calls. Each call is followed by a read_response call from the slave. If the read/write bit in the start was 0, the master instead proceeds with a sequence of write calls, each one followed by an acknowledge call. The ack parameter of the acknowledge method may be either I2C_ack or I2C_noack, representing ack and noack, respectively.

After sending a number of reads or writes, the master may choose to either call the stop method to issue a stop condition which terminates the transfer, or to call the start method again to issue a repeated start condition. The repeated start condition works like a normal start condition.

When 0 is passed as the address parameter of the start method, a General Call transfer is initiated. A General Call transfer works like a normal write transfer, except that multiple slave devices may acknowledge the start and write requests. The master will conceive a request as acknowledged if it was acknowledged by at least one of the slaves.

When 10-bit address pattern is passed as the address parameter of the start method, a 10-bit address transaction is initiated. A 10-bit address transaction begins with write status (read/write bit should be 0). As mentioned before, bits 1 to 2 are the most significant bits of 10-bit address. Then following is a call to the write method with the last 8 bits of 10-bit address. If the transaction is slave-receiver, the next transfer works like a normal write transfer. If the transaction is slave-transmitter, then the start method is called again with the same address pattern as before, but with bit 0 (the read/write bit) set to 1. This is followed by calls to read like in a normal read transaction.

The addresses method is used to retrieve the set of addresses a device currently listens to. The method is called by the i2c-link-v2 to provide an overview of the bus topology, and to detect address collisions early. The method may not have any side-effects on the simulation. The return value is a list containing all the different values of the address parameter in a start call that the slave would respond to with I2C_ack. The list may also contain an element Nil to mark that the device might respond to other addresses as well. If a device is configured to listen to a specific address but is currently disabled, then that address may still be included in the list.

For example, if a slave device listens to the single 7-bit address 0x55, the return value of addresses would be [0xaa, 0xab], using Python list syntax.

The specification of the return value may be extended in the future, to allow other values than Nil and 8-bit integers. Therefore, callers should not make any assumptions on how the elements are formatted in the return value.

For most I2C devices it is sufficient to implement only one of the i2c_slave_v2 and i2c_master_v2 interfaces. In some cases it may be useful for a device to implement both interfaces, either because the device can act both as a master and as a slave on the bus, or because it needs to use the start and stop methods to monitor start and stop conditions on the bus. I2C link endpoints also implement both interfaces.

If multiple master devices are connected to the same i2c link, then all master devices need to implement the i2c_slave_v2 interface in addition to i2c_master_v2, in order to handle bus arbitration correctly:

  • A master device should monitor calls to the start and stop functions: After a call to start in a master device, the master should not call start in the slave until after a subsequent call to stop in the master.
  • When a master calls start in a link endpoint device, the endpoint may respond with a call to start instead of acknowledge; this means that there was bus arbitration, which the master lost to the given start request. Note that this case can not happen on a latency-free connection, since all arbitration is handled by the master's monitoring of start and stop calls. Note also that user-written slave devices are required to respond with acknowledge to a start call; only the i2c link endpoint (and other i2c infrastructure objects from the Simics-Base package) are allowed to respond with a start call.

Note that there is no need for a master device to implement the i2c_slave_v2 interface if the device only will be used in single-master configurations.

The start, write and read methods in the i2c_slave_v2 interface are allowed to respond synchronously; i.e., the acknowledge or read_response method may be called before the corresponding method in the slave interface has returned. A master that needs to connect directly to a slave device needs to take this into consideration; however, when communicating via an i2c-link-v2 object, the link guarantees that all responses are asynchronous.

Execution Context
addressesGlobal Context
All other methodsCell Context

i3c_daa_snoop

Description
SIM_INTERFACE(i3c_daa_snoop) {
        void (*assigned_address)(conf_object_t *obj, uint64 id,
                                 uint8 bcr, uint8 dcr, uint8 address);
};

#define I3C_DAA_SNOOP_INTERFACE "i3c_daa_snoop"

During DAA process, the assigned address information will be monitored to devices who implement the interface i3c_daa_snoop. Whenever an address is assigned to a slave, the method assigned_address is called in all devices that implement the interface. The parameter id, bcr and dcr in method assigned_address is slave specific daa data which indicates who gets the assigned address. Parameter address stores the assigned address. The 7-bit address is represented as 8-bit number with the highest bit set to 0.

Interface i3c_daa_snoop is mainly implemented by slave who may become secondary master later and needs to know the information about slave addresses.

Execution Context
Cell Context for all methods.

i3c_hdr_master

Description
SIM_INTERFACE(i3c_hdr_master) {
        void (*hdr_read_response)(conf_object_t *obj, bytes_t bytes, bool more);
        void (*hdr_acknowledge)(conf_object_t *obj, i3c_ack_t ack);
};

#define I3C_HDR_MASTER_INTERFACE "i3c_hdr_master"

The interfaces i3c_hdr_slave and i3c_hdr_master are used together to model I3C HDR communication over the bus. HDR modes are entered by sending one of the ENTHDRx broadcast CCCs on the bus through normal SDR communication. Slaves that support HDR shall now internally switch to HDR mode. The master can exit HDR mode by calling hdr_exit in the i3c_hdr_slave interface and then follow it with a stop call. All slaves that support HDR shall now internally switch back to SDR mode.

All write transfers in HDR mode are done using the hdr_write method. Slaves must always respond through method hdr_acknowledge to either ACK or NACK the write. Devices not supporting active acknowledgement for a certain write transfer block must always respond with an ACK as it represents a passive acknowledgement according to MIPI I3C V1.1.1 spec.

All read transfers in HDR mode are done using the hdr_read method. Parameter max_len in method hdr_read is the maximum number of bytes that the slave is allowed to send in response. The slave shall respond with an hdr_read_response call after each hdr_read call. The parameter more indicates if the slave has more data to send. The slave is allowed to send back less than max_len and at the same time set more to true. This feature is an optimization in order to: 1. Minimize the number of hdr_read calls needed to read a large amount of data. 2. Avoid underflow on the slave side by allowing the slave respond with less data.

If more is set to false, the master has to ends it current transfer by either calling hdr_restart or exit HDR through the procedure described above.

Examples of HDR write transactions:

HDR Private Write 256 bytes followed by a 64 byte write:
+-------------+-----------------+--------------------------------------------------------+
| Master      | Slave           | Arguments                                              |
+-------------+-----------------+--------------------------------------------------------+
| hdr_write   |                 | 2 bytes: RnW @ 15 |  CC @ 14:8 | Target Address @ 8:1  |
+-------------+-----------------+--------------------------------------------------------+
|             | hdr_acknowledge | ACK                                                    |
+-------------+-----------------+--------------------------------------------------------+
| hdr_write   |                 | 100-bytes                                              |
+-------------+-----------------+--------------------------------------------------------+
|             | hdr_acknowledge | ACK                                                    |
+-------------+-----------------+--------------------------------------------------------+
| hdr_write   |                 | 100-bytes                                              |
+-------------+-----------------+--------------------------------------------------------+
|             | hdr_acknowledge | ACK                                                    |
+-------------+-----------------+--------------------------------------------------------+
| hdr_write   |                 | 56-bytes                                               |
+-------------+-----------------+--------------------------------------------------------+
|             | hdr_acknowledge | ACK                                                    |
+-------------+-----------------+--------------------------------------------------------+
| hdr_restart |                 |                                                        |
+-------------+-----------------+--------------------------------------------------------+
| hdr_write   |                 | 2 bytes: RnW @ 15 |  CC @ 14:8 | Target Address @ 8:1  |
+-------------+-----------------+--------------------------------------------------------+
|             | hdr_acknowledge | ACK                                                    |
+-------------+-----------------+--------------------------------------------------------+
| hdr_write   |                 | 64-bytes                                               |
+-------------+-----------------+--------------------------------------------------------+
|             | hdr_acknowledge | ACK                                                    |
+-------------+-----------------+--------------------------------------------------------+
| hdr_exit    |                 |                                                        |
+-------------+-----------------+--------------------------------------------------------+
| stop        |                 |                                                        |
+-------------+-----------------+--------------------------------------------------------+
   

The sequence of hdr_write calls could be made differently. Master can send smaller or larger chunks of data in each hdr_write call. The main concerns are to minimize the number of interface calls and to avoid overflow on the slave side. A balance between the two should be considered in the implementation of the master.

HDR Private Read 256 bytes:
+-----------+-------------------+-------------------------------------------------------+
| Master    | Slave             | Arguments                                             |
+-----------+-------------------+-------------------------------------------------------+
| hdr_write |                   | 2 bytes: RnW @ 15 |  CC @ 14:8 | Target Address @ 8:1 |
+-----------+-------------------+-------------------------------------------------------+
|           | hdr_acknowledge   | ACK                                                   |
+-----------+-------------------+-------------------------------------------------------+
| hdr_read  |                   | max_len = 128                                         |
+-----------+-------------------+-------------------------------------------------------+
|           | hdr_read_response | bytes.len = 64, more = true                           |
+-----------+-------------------+-------------------------------------------------------+
| hdr_read  |                   | max_len = 128                                         |
+-----------+-------------------+-------------------------------------------------------+
|           | hdr_read_response | bytes.len = 64, more = true                           |
+-----------+-------------------+-------------------------------------------------------+
| hdr_read  |                   | max_len = 128                                         |
+-----------+-------------------+-------------------------------------------------------+
|           | hdr_read_response | bytes.len = 64, more = true                           |
+-----------+-------------------+-------------------------------------------------------+
| hdr_read  |                   | max_len = 64                                          |
+-----------+-------------------+-------------------------------------------------------+
|           | hdr_read_response | bytes.len = 64, more = false                          |
+-----------+-------------------+-------------------------------------------------------+
| hdr_exit  |                   |                                                       |
+-----------+-------------------+-------------------------------------------------------+
| stop      |                   |                                                       |
+-----------+-------------------+-------------------------------------------------------+

The sequence of hdr_read calls could be made differently. Master can read smaller chunks of data in each hdr_read call. The main concerns are to minimize the number of interface calls and to avoid underflow on the slave side. A balance between the two should be considered in the implementation of the master.

Note: This interface is in tech-preview and may change without notice.

Execution Context
Cell Context for all methods.

i3c_hdr_slave

Description
SIM_INTERFACE(i3c_hdr_slave) {
        void (*hdr_write)(conf_object_t *obj, bytes_t data);
        void (*hdr_read)(conf_object_t *obj, uint32 max_len);
        void (*hdr_restart)(conf_object_t *obj);
        void (*hdr_exit)(conf_object_t *obj);
};

#define I3C_HDR_SLAVE_INTERFACE "i3c_hdr_slave"

Execution Context
Cell Context for all methods.

i3c_master

Description
typedef enum {
        I3C_ack = 0,
        I3C_noack
} i3c_ack_t;


SIM_INTERFACE(i3c_master) {
        void (*acknowledge)(conf_object_t *obj, i3c_ack_t ack);
        void (*read_response)(conf_object_t *obj, uint8 value, bool more);
        void (*daa_response)(conf_object_t *obj,
                             uint64 id, uint8 bcr, uint8 dcr);
        void (*ibi_request)(conf_object_t *obj);
        void (*ibi_address)(conf_object_t *obj, uint8 address);
};

#define I3C_MASTER_INTERFACE "i3c_master"

The interfaces i3c_master i3c_slave and i3c_daa_snoop are used together to model communication over an I3C bus. There are four kinds of devices roles on the I3C bus: Main Master, Secondary Master, Slave and Legacy I2C Slave. Exactly one device must be the Main Master; this is typically configured statically. Main Master should implement the i3c_master interface, while slave should implement the i3c_slave interface. Secondary Master should implement both. Most calls to a method in the slave device interfaces expect a response call to a method in the master device interfaces. One exception is the method sdr_write in the i3c_slave interface, master expects no response when calling it. It is up to each device to find the caller's interfaces; usually it is configured with attributes in both the master and slave device.

Two I3C devices can communicate directly if one implements the i3c_master interface and the other one implements the i3c_slave interface. An I3C bus with multiple masters or slaves is typically modelled using an i3c-link object, where each device is connected to an endpoint object.

An I3C bus consists of a number of master devices and a number of slave devices. Each I3C slave device listens to one or more 7-bit addresses. The slave devices can be I3C slave devices or Legacy I2C slave devices. This is because I3C protocol is compatible with I2C protocol, so that I3C master device can communicate with I2C slave devices. For legacy I2C slave device, the address it listens to is pre-configured by the device, i.e. static address. For I3C slave device, the address it listens to can be either static address or dynamic address. The dynamic address is assigned by master during Dynamic Address Assignment process. It is an error to connect two slave devices to the same bus if they listen to the same address. In a communication, the Current Master refers to the device who now drives the bus. It can be Main Master, or Secondary Master. Usually, communication over the bus is initiated by the Current Master, which can communicate with one or more slave devices at a time. A slave device can request to initiate an communication, i.e., issue an ibi_request, in three cases: Hot-Join, In-Band Interrupt and as a Secondary Master other than the Current Master requesting to become Current Master. Only one device on a bus can communicate at a time.

The start method starts a transfer. The address parameter is the address header combined with read/write bit encoded as an 8-bit number. The least significant bit is the read/write bit and the other bits is the 7-bit address header. If the start method is called from master, the address header can be address pattern 0x7E for broadcast, or specific slave address (either I2C slave static address or I3C slave dynamic address).

In I3C bus or link implementation, every start request will broadcast to all other devices. So does the stop request. This will monitor bus/link status to all devices.

Normally, master starts a transfer, then the slave responds to start using the acknowledge method (implemented by master side interface). The ack parameter may be I3C_ack or I3C_noack if the start is acked or noacked, respectively.

There are five types of different start requests:

I3C master read transaction
If a master's start with specific slave address was acked by other device, and read/write bit in the address parameter of the start method was 1, then master proceeds with a sequence of read calls. Each call is followed by a read_response call from the slave. Parameter data in the method read_response is the data transferred. The procedure is no difference with regard to read from I3C slave or read from I2C slave. In hardware, the ACK/T bit is handled differently for i2c and i3c, and the master is supposed to know whether the slave is an i2c or i3c device. In the i3c case, the slave is supposed to pass the T bit in the more argument of read_response, while an i2c device always passes more as true. Further more, in the i2c case, a master sends an ACK bit, which is not represented explicitly in the interface. The value of this bit can be deduced from whether the following operation is START/STOP or READ. For i3c case, parameter more in method read_response indicates if there are still data waiting to be transferred from slave to master. more is true when there are still data left, false otherwise.
I3C master write transaction (write to I3C slave)
If a master's start with specific slave address was acked by other device, and the read/write bit in the address parameter of start method was 0, the master proceeds with a sdr_write call, no response is expected. Parameter data in method write is the data transferred. The parity bit is not passed explicitly in sdr_write, and that the slave can assume the parity bit is correctly set.
I3C master write transaction (write to I2C slave)
When the master's start request is to write to I2C slave, i.e., master issues a start request to I2C slave address with read/write bit is 0, then master proceeds with a sequence of write calls, each call expects a response call to a method acknowledge. This is quite similar to I2C write transaction.
I3C broadcast transaction
When master starts a transfer with I3C Broadcast Address 0x7E which is passed as address header, i.e., address 0xFC passed in the address argument of method start, a typical I3C message transfer is initiated.

Multiple I3C slave devices may acknowledge the start request. The master will conceive a request as being acknowledged if it was acknowledged by at least one of the slaves. Note that there will be a single acknowledge call in the master; the link or bus handles aggregation of acks.

Master sends the I3C Commands (Common Command Code, CCC) using sdr_write method after receiving ACK, showing to communicate with either all Slaves (Broadcast CCCs) or specific individual Slaves (Direct CCCs). This operation expects no response, and master will proceed.

If Broadcast CCC sent previously, master calls sdr_write method to transfer data to all slaves who acked the initial access.

I3C direct transaction
After sending a Direct CCC, master continues with a repeated start request along with one specific I3C slave address. The transaction goes on just like master is communicating with only one slave. After the communication with one slave, master may be issue a repeated start request to another slave. Further communication is routed only to the targeted slave device.

After sending a number of reads or a number of writes, the master may choose to either call the stop method to issue a stop condition which terminates the transfer, or to call the start method again to issue a repeated start condition. The repeated start condition works like a normal start condition.

The start method and read method in the slave interfaces are allowed to respond synchronously; i.e., the acknowledge or read method may be called before the corresponding method in the slave interfaces has returned. A master that needs to connect directly to a slave device needs to take this into consideration; however, when communicating via an i3c-link object, the link guarantees that all responses are asynchronous.

The method daa_read and method daa_response are used in Dynamic Address Assignment process. Method daa_read is called from master to signal a daa read request. Method daa_response is called from slave to send slave specific 8-bytes data (48-bit Unique ID, BCR, DCR) to master. The parameter id, bcr and dcr in method daa_response represent the slave specific daa data. If multiple slaves response daa data, the slave with the lowest data wins and it will get the assigned address this time. Master calls method write in slave interfaces to send assigned dynamic address to the slave who wins. This operation expects a response call to method acknowledge in master side. Parameter data in method write stores the assigned address.

Master should implement the method stop in the interface i3c_slave in case there is secondary master in the configuration which may issue start request.

Slave can request to start a communication through ibi_request. The request is sent to Current Master which drives the bus now. If the master chooses to continue the slave request, ibi_start is called, this ibi start will broadcast to all devices in the configuration. Then slave can send its address header with ibi_address argument address. The address header can be 0x02 for Hot-Join, or the address of the slave itself for IBI and secondary master with read/write bit 1 and 0 respectively. If more than one slave issues ibi_address, arbitration occurs, the slave with lowest address header wins and the winning address will be delivered to master by link or bus. At that time, master issues ibi_acknowledge to the slave who wins. Other slaves which do not receive ibi_acknowledge will consume it lost arbitration already.

Execution Context
Cell Context for all methods.

i3c_slave

Description
SIM_INTERFACE(i3c_slave) {
        void (*start)(conf_object_t *obj, uint8 address);
        void (*write)(conf_object_t *obj, uint8 value);
        void (*sdr_write)(conf_object_t *obj, bytes_t data);
        void (*read)(conf_object_t *obj);
        void (*daa_read)(conf_object_t *obj);
        void (*stop)(conf_object_t *obj);
        void (*ibi_start)(conf_object_t *obj);
        void (*ibi_acknowledge)(conf_object_t *obj, i3c_ack_t ack);
};

#define I3C_SLAVE_INTERFACE "i3c_slave"

Execution Context
Cell Context for all methods.

i8051_interrupt

Description
SIM_INTERFACE(i8051_interrupt) {
        int (*active_interrupt)(conf_object_t *NOTNULL obj);
        void (*reti)(conf_object_t *NOTNULL obj);
        bool (*suppress_irq)(conf_object_t *NOTNULL obj, uint32 addr);        
};
#define I8051_INTERRUPT_INTERFACE "i8051_interrupt"

The active_interrupt() function returns the interrupt vector address of the highest pending interrupt. This function should only be called when the processor should take an interrupt. This function may also set internal interrupt controller state, which can be cleared by the reti function call when returning from the interrupt.

The reti function is used to notify the interrupt controller that the currently active interrupt has completed.

The suppress_irq function is used to determine whether interrupt should be blocked after a writing access to a memory location.

Execution Context
Cell Context for all methods.

i8051_timer

Description
SIM_INTERFACE(i8051_timer) {
        void (*change_mode)(conf_object_t *NOTNULL obj, uint8 mode);
        void (*switch_timer)(conf_object_t *obj, uint8 caller, bool onoff);
};
#define I8051_TIMER_INTERFACE "i8051_timer"

The change_mode function is used to change the working mode (e.g. 16bit timer, 8 bit timer or event counting etc.) of the timer.

The switch_timer function is used to enable or disable the timer. Timers can be switched on or off by either software or hardware. The parameter caller is either 0 or 1, indicating the control is from software or hardware. Only when the timer is switched on or off by hardware, the third parameter onoff is used, which indicates whether the timer is to be enabled or disabled.

Execution Context
Cell Context for all methods.

ieee_802_15_4_control

Description
SIM_INTERFACE(ieee_802_15_4_control) {
        void (*set_rssi)(conf_object_t *NOTNULL obj,
                         uint64 tgt_ep_id,
                         uint32 rssi);
        void (*remove_rssi)(conf_object_t *NOTNULL obj,
                            uint64 tgt_ep_id);
        void (*clear_all_rssi)(conf_object_t *NOTNULL obj);
};
#define IEEE_802_15_4_CONTROL_INTERFACE "ieee_802_15_4_control"

The ieee_802_15_4_control interface is implemented by the IEEE 802.15.4 link endpoint objects that provide a interface for endpoint configuration. Simics command (Python program) calls set_rssi, remove_rssi and clear_all_rssi to update the RSSI table.

Execution Context
Cell Context for all methods.

ieee_802_15_4_link

Description
SIM_INTERFACE(ieee_802_15_4_link) {
        ieee_802_15_4_transmit_status_t (*transmit)(
                                conf_object_t *NOTNULL obj,
                                const frags_t *frame,
                                uint16 channel_page,
                                uint16 channel_number,
                                ieee_802_15_4_frame_crc_status_t crc_status);
};
#define IEEE_802_15_4_LINK_INTERFACE "ieee_802_15_4_link"

The ieee_802_15_4_link interface is implemented by the IEEE 802.15.4 link endpoint objects that provide an interface for frame traffic.

Transceiver calls transmit to send out frames. The return value is using one of the values in the ieee_802_15_4_transmit_status_t enum:

  • IEEE_802_15_4_Transmit_No_Error means that the frame was sent out without error.
  • IEEE_802_15_4_Transmit_Channel_Contention means that there was collision and the frame was not sent out.
  • IEEE_802_15_4_Transmit_Data_Corruption means that the endpoint detected CRC mismatch and didn't send out the frame.
typedef enum {
        IEEE_802_15_4_Transmit_No_Error = 0,
        IEEE_802_15_4_Transmit_Channel_Contention,
        IEEE_802_15_4_Transmit_Data_Corruption
} ieee_802_15_4_transmit_status_t;

The crc_status parameter provides out-of-band information on the contents of the frame with regards to the CRC field using one of the values in the ieee_802_15_4_frame_crc_status_t enum:

  • IEEE_802_15_4_Frame_CRC_Match means that to the link that, regardless of the actual contents of the CRC field in frame, the CRC is considered matching the frame contents.
  • IEEE_802_15_4_Frame_CRC_Mismatch means that the CRC field and the frame contents do not agree. Just like the Ethernet links, the endpoint does not really send out the packet in this case.
  • IEEE_802_15_4_Frame_CRC16_Unknown/IEEE_802_15_4_Frame_CRC32_Unknown means that the link to compute the CRC and compare it with FCS (Frame Check Sequence) of the MAC frame. If the CRC field and frame contents do not agree, the endpoint does not send out the packet. IEEE_802_15_4_Frame_CRC32_Unknown is for 802.15.4g only.
typedef enum {
        IEEE_802_15_4_Frame_CRC_Match = 0,
        IEEE_802_15_4_Frame_CRC_Mismatch,
        IEEE_802_15_4_Frame_CRC16_Unknown,
        IEEE_802_15_4_Frame_CRC32_Unknown,
} ieee_802_15_4_frame_crc_status_t;

The frequency channels are defined through a combination of channel numbers and channel pages. Channel page is a concept added to IEEE 802.15.4 in 2006 to distinguish between supported PHYs. Both channel page and channel number must match on source and target sides for successful transmission.

Execution Context
Cell Context for all methods.

ieee_802_15_4_probe

Description
typedef void (*ieee_802_15_4_probe_snoop_t)(
                                lang_void *user_data,
                                conf_object_t *probe,
                                ieee_802_15_4_probe_side_t to_side,
                                const frags_t *frame,
                                uint32 rssi,
                                uint16 channel_page,
                                uint16 channel_number,
                                ieee_802_15_4_frame_crc_status_t crc_status);

  • IEEE_802_15_4_Probe_Port_A means that the frame is from device to link.
  • IEEE_802_15_4_Probe_Port_B means that the frame is from link to device.
typedef enum {
        IEEE_802_15_4_Probe_Port_A = 0,
        IEEE_802_15_4_Probe_Port_B = 1
} ieee_802_15_4_probe_side_t;

SIM_INTERFACE(ieee_802_15_4_probe) {
        void (*attach_snooper)(conf_object_t *NOTNULL probe,
                               ieee_802_15_4_probe_snoop_t snoop_fun,
                               lang_void *user_data);
        void (*detach)(conf_object_t *NOTNULL probe);
};
#define IEEE_802_15_4_PROBE_INTERFACE "ieee_802_15_4_probe"

The ieee_802_15_4_probe interface is implemented by the IEEE 802.15.4 probe devices that provide an interface for Simics users to register their own callback to listen to the traffic going-on in the probe. The attach_snooper attaches a snooper function. The probe will pass each frame to the snooper function, then forward it unchanged where it should be going. The detach detaches the currently registered callback from the probe.

This interface should only be used for inspection, and never as part of the actual simulation. The snoop functions must not affect the simulation in any way. The user_data parameter is passed to the snoop function every time it is called.

Execution Context
Cell Context for all methods.

ieee_802_15_4_receiver

Description
SIM_INTERFACE(ieee_802_15_4_receiver) {
        void (*receive)(conf_object_t *NOTNULL obj,
                        const frags_t *frame,
                        uint32 rssi,
                        uint16 channel_page,
                        uint16 channel_number,
                        ieee_802_15_4_frame_crc_status_t crc_status);
        void (*frame_lost)(conf_object_t *NOTNULL obj,
                           uint32 rssi,
                           uint16 channel_page,
                           uint16 channel_number);
};
#define IEEE_802_15_4_RECEIVER_INTERFACE "ieee_802_15_4_receiver"

The ieee_802_15_4_receiver interface is implemented by the IEEE 802.15.4 transceivers that provide an interface for traffic. Endpoints call receive to deliver a frame to transceiver. Transceiver should check if the received frame from endpoint is in the channel that it is using. The channel being used is defined by channel_page and channel_number. Endpoints call frame_lost to notify transceivers on that a frame was lost because of low RSSI value.

Execution Context
Cell Context for all methods.

ieee_802_3_mac

Description
#define IEEE_802_3_MAC_INTERFACE "ieee_802_3_mac"
SIM_INTERFACE(ieee_802_3_mac) {
        int (*receive_frame)(conf_object_t *obj, int phy,
                             dbuffer_t *buf, int crc_ok);
        void (*tx_bandwidth_available)(conf_object_t *obj, int phy);
        void (*link_status_changed)(conf_object_t *obj, int phy,
                                    ieee_802_3_link_status_t status);
};

typedef enum {
        IEEE_link_unconnected,
        IEEE_link_down,
        IEEE_link_up
} ieee_802_3_link_status_t;

Deprecated; use ieee_802_3_mac_v3 instead.

Interface that should be implemented by 802.3 media access control layers.

The receive_frame function is called when a frame has been received by the phy. The frame is passed as a dbuffer_t that may not be modified without cloning it first. The return value have no meaning, callers should ignore it, and new implementations should return 0.

The tx_bandwidth_available is called by the PHY when a previous call to send_frame or check_tx_bandwidth in the ieee_802_3_phy interface have returned no bandwidth available.

link_status_changed is called when the phy detects a change of the link status.

The phy parameter is a number that identifies this particular PHY, in configurations with several PHYs connected to the same MAC.

Execution Context
Cell Context for all methods.

ieee_802_3_mac_v3

Description
#define IEEE_802_3_MAC_V3_INTERFACE "ieee_802_3_mac_v3"
SIM_INTERFACE(ieee_802_3_mac_v3) {
        void (*receive_frame)(
                conf_object_t *obj, int phy, const frags_t *frame, int crc_ok);
        void (*tx_bandwidth_available)(conf_object_t *obj, int phy);
        void (*link_status_changed)(
                conf_object_t *obj, int phy, ieee_802_3_link_status_t status);
};

typedef enum {
        IEEE_link_unconnected,
        IEEE_link_down,
        IEEE_link_up
} ieee_802_3_link_status_t;

Interface that should be implemented by 802.3 media access control layers.

The receive_frame function is called when a frame has been received by the phy. The frame is passed as a frags_t that must not be modified.

The crc_ok flag is set to indicate that the frame is valid with regards to CRC calculations. If the crc_ok flag is not set, the frame is considered invalid. Note that in general, crc_ok does not indicate whether or not the CRC field in the frame can be relied upon, or whether its computation has been skipped to improve simulation performance. When using new-style links, crc_ok set to false indicates that the CRC field contains valid information that is not matching with the frame contents.

The tx_bandwidth_available is called by the PHY when a previous call to send_frame or check_tx_bandwidth in the ieee_802_3_phy_v3 interface have returned no bandwidth available.

link_status_changed is called when the phy detects a change of the link status.

The phy parameter is deprecated and should be ignored.

Execution Context
Cell Context for all methods.

ieee_802_3_phy

Description
#define IEEE_802_3_PHY_INTERFACE "ieee_802_3_phy"
SIM_INTERFACE(ieee_802_3_phy) {

        int (*send_frame)(conf_object_t *obj, dbuffer_t *buf, int replace_crc);
        int (*check_tx_bandwidth)(conf_object_t *obj);
#if !defined(PYWRAP)
        void (*add_mac)(conf_object_t *obj, const uint8 *mac);
        void (*del_mac)(conf_object_t *obj, const uint8 *mac);
        void (*add_mac_mask)(conf_object_t *obj, const uint8 *mac,
                             const uint8 *mask);
        void (*del_mac_mask)(conf_object_t *obj, const uint8 *mac,
                             const uint8 *mask);
#endif
        void (*set_promiscous_mode)(conf_object_t *obj, int enable);

};

Interface that should be implemented by 802.3 physical layers. Deprecated; use ieee_802_3_phy_v2 instead.

Execution Context
Undefined.

ieee_802_3_phy_v2

Description
#define IEEE_802_3_PHY_V2_INTERFACE "ieee_802_3_phy_v2"
SIM_INTERFACE(ieee_802_3_phy_v2) {
        int (*send_frame)(conf_object_t *obj, dbuffer_t *buf, int replace_crc);
        int (*check_tx_bandwidth)(conf_object_t *obj);
        void (*add_mac)(conf_object_t *obj, byte_string_t mac);
        void (*del_mac)(conf_object_t *obj, byte_string_t mac);
        void (*add_mac_mask)(conf_object_t *obj, byte_string_t mac,
                             byte_string_t mask);
        void (*del_mac_mask)(conf_object_t *obj, byte_string_t mac,
                             byte_string_t mask);
        void (*set_promiscous_mode)(conf_object_t *obj, int enable);
};

Deprecated; use ieee_802_3_phy_v3 instead.

Interface that should be implemented by 802.3 physical layers.

The send_frame function is used by a device to send an Ethernet frame. The frame should be a dbuffer_t containing a complete Ethernet frame. excluding the preamble and SFD, but including the CRC. The replace_crc flag indicates whether the CRC is not actually calculated yet. The passed buf should not be modified by the called function. If the function return 0, the frame was sent to the link; In case -1 is returned, there was not enough bandwidth available right now, and the frame could not be sent. The PHY should call the tx_bandwidth_available in the ieee_802_3_mac interface at the MAC, when the frame can be sent.

The check_tx_bandwidth can also be used to check that there is bandwidth available, without sending a frame. It returns 0 if there is no bandwidth available, and a positive value if the frame can be sent right away.

add_mac, del_mac and set_promiscous_mode have the same functionality as the equivalent functions in ethernet_link interface. They do nothing if the PHY is connected to the new-style links using the ethernet_common interface.

The word "promiscuous" is misspelled in the interface.

Execution Context
Cell Context for all methods.

ieee_802_3_phy_v3

Description
#define IEEE_802_3_PHY_V3_INTERFACE "ieee_802_3_phy_v3"
SIM_INTERFACE(ieee_802_3_phy_v3) {
        int (*send_frame)(
                conf_object_t *obj, const frags_t *frame, int replace_crc);
        int (*check_tx_bandwidth)(conf_object_t *obj);
};

Interface that should be implemented by 802.3 physical layers.

The send_frame function is used by a device to send an Ethernet frame. The frame should be a frags_t containing a complete Ethernet frame, excluding the preamble and SFD, but including space for the CRC field. The passed frame must not be modified by the called function.

The replace_crc flag indicates whether the CRC field contents can be modified by the implementing object: if replace_crc is not set, the implementing object will leave the CRC field untouched; if replace_crc is set, the implementing object is free to rewrite the CRC field according to the link constraints. Note that in many cases, setting replace_crc to true will allow the link to assume the CRC field to be matching the frame contents, thus skipping CRC calculation and improving simulation performance. replace_crc should only be set to false when the device wants to send a frame with a CRC field not matching the frame contents.

If the function return 0, the frame was sent to the link; In case -1 is returned, there was not enough bandwidth available right now, and the frame could not be sent. The PHY should call the tx_bandwidth_available in the ieee_802_3_mac_v3 interface at the MAC, when the frame can be sent.

The check_tx_bandwidth can also be used to check that there is bandwidth available, without sending a frame. It returns 0 if there is no bandwidth available, and a positive value if the frame can be sent right away.

Execution Context
Cell Context for all methods.

interrupt_ack

Description
The interrupt_ack_fn_t function is called by an interrupt target to ack an interrupt. Returns the interrupt vector.
typedef int (*interrupt_ack_fn_t)(conf_object_t *NOTNULL);

Interface for acked interrupts. The target is typically a cpu that later calls the supplied ack function when the interrupt is actually taken.

The ack argument in the lower_interrupt function serves no purpose and should not be used.

To recover the ack function after a checkpoint restoration, read it from the interrupt_cpu interface.

SIM_INTERFACE(interrupt_ack) {
        void (*raise_interrupt)(conf_object_t *NOTNULL obj,
                                interrupt_ack_fn_t cb,
                                conf_object_t *ack_obj);
        void (*lower_interrupt)(conf_object_t *NOTNULL obj,
                                interrupt_ack_fn_t cb);
};

#define INTERRUPT_ACK_INTERFACE "interrupt_ack"

Execution Context
Cell Context for all methods.

interrupt_cpu

Description
Interface that must be implemented by an interrupt source that sends interrupts through the x86 interface. Used to reestablish the ack function when loading a checkpoint.

SIM_INTERFACE(interrupt_cpu) {
        interrupt_ack_fn_t ack;
};

#define INTERRUPT_CPU_INTERFACE "interrupt_cpu"

Execution Context
Cell Context for all methods.

interrupt_subscriber

Description
The target is typically a CPU that reacts to the interrupt.

The function notify notifies when an interrupt has occurred.

The function reset is run when the interrupt notifier source is reset.

#define INTERRUPT_SUBSCRIBER_INTERFACE "interrupt_subscriber"
SIM_INTERFACE(interrupt_subscriber) {
        void (*notify)(
                conf_object_t *NOTNULL obj,
                apic_delivery_mode_t delivery_mode,
                bool level_assert,
                apic_trigger_mode_t trigger_mode,
                uint8 vector,
                interrupt_source_t source);
        void (*reset)(conf_object_t *NOTNULL obj);
};

Execution Context
Threaded Context for all methods.

io_memory

Description
This interface is implemented by devices that can be mapped into address spaces (including port spaces). The operation() is called when the object is accessed through an address space.

The obj argument is a pointer to the mapped object and map_info contains information about how and where the device is mapped into memory. The mem_op argument to operation() contains information about the access.

The offset into the device mapping for the access is typically calculated in the following way:

offset = SIM_get_mem_op_physical_address(mem_op) - map_info.base + map_info.start

Note: The map() function is deprecated and should not be used. The function may be called when the object is mapped into an address space, but it is not guaranteed that this happens. The function can be left unimplemented (NULL).
The exception_type_t type, returned by the operation() function may be used to signal errors to Simics, but should in most cases be Sim_PE_No_Exception. If the device does not support inquiry accesses, it should return Sim_PE_Inquiry_Unhandled if mem_op->inquiry is 1.

Note: This interface is legacy. New code should use the transaction interface.
typedef enum {
        Sim_Addr_Space_Conf,
        Sim_Addr_Space_IO,
        Sim_Addr_Space_Memory
} addr_space_t;

SIM_INTERFACE(io_memory) {
        int (*DEPRECATED_FUNC(map))(conf_object_t *NOTNULL obj,
                                    addr_space_t memory_or_io,
                                    map_info_t map_info);
        exception_type_t (*operation)(conf_object_t *NOTNULL obj,
                generic_transaction_t *NOTNULL mem_op,
                map_info_t map_info);
};

#define IO_MEMORY_INTERFACE "io_memory"

Execution Context
Cell Context for all methods.

map_demap

Description
Interface used to dynamically add and remove mappings in a memory space. The first argument to all functions, space is the memory space to map an object in.

The map_simple function adds a device/port pair to the memory map. The added device (port) must implement either the ram, rom, io_memory, port_space, translator, transaction_translator, transaction or memory_space interfaces.

The map_bridge function adds a device/port pair to the memory map to act as a bridge that translates memory accesses before passing them on to another object. The added device (port) must implement either the translate interface or the bridge interface, and the target and target_port parameter specifies the object behind the bridge. The target is typically another memory space.

The unmap removes an object from the memory map. The dev and port parameters are the same as those given to the map_simple and map_bridge functions.

The unmap_address removes all mappings that map object and start at the base address.

The add_map, remove_map, add_default and remove_default functions are deprecated and should not be used. Both base and length of the map_info_t structure should be 0 to map a default_target.

All functions in the map_demap return 1 on success and 0 on failure.

More information about the different kinds of memory space mappings is available in Simics Model Builder User's Guide.

SIM_INTERFACE(map_demap) {
        /* old-style */
        int (*add_map)(conf_object_t *NOTNULL space,
                       conf_object_t *NOTNULL dev,
                       conf_object_t *target,
                       map_info_t map_info);
        int (*remove_map)(conf_object_t *NOTNULL space,
                          conf_object_t *NOTNULL dev,
                          int function);
        int (*add_default)(conf_object_t *NOTNULL space,
                           conf_object_t *NOTNULL dev,
                           conf_object_t *target,
                           map_info_t map_info);
        void (*remove_default)(conf_object_t *NOTNULL space);

        /* new-style */
        int (*map_simple)(conf_object_t *NOTNULL space,
                          conf_object_t *NOTNULL dev,
                          const char *dev_port,
                          map_info_t map_info);
        int (*map_bridge)(conf_object_t *NOTNULL space,
                          conf_object_t *NOTNULL dev,
                          const char *dev_port,
                          conf_object_t *target,
                          const char *target_port,
                          map_info_t map_info);
        int (*unmap)(conf_object_t *NOTNULL space,
                     conf_object_t *NOTNULL dev,
                     const char *dev_port);
        int (*unmap_address)(conf_object_t *NOTNULL space,
                             conf_object_t *NOTNULL dev,
                             physical_address_t base,
                             const char *dev_port);
};

#define MAP_DEMAP_INTERFACE "map_demap"

Execution Context
Cell Context for all methods.

mdio45_bus

Description
SIM_INTERFACE(mdio45_bus) {
        uint16 (*read_register)(conf_object_t *obj, int phy, int mmd, int reg);
        void   (*write_register)(conf_object_t *obj, int phy, int mdd, int reg,
                                 uint16 value);

};
#define MDIO45_BUS_INTERFACE "mdio45_bus"

Interface that should be implemented by classes that either represent an MDIO bus, or multi PHY devices implementing the IEEE 802.3 clause 45 MDIO management interface.

The read_register function should return the 16-bit value of the specified register. phy specifies the PHY address (0-31), mmd specifies the MMD (MDIO manageable device) within the PHY (0-31) and reg specifies the register number within the MMD (0-65535).

Devices modeling a single PHY should implement the mdio45_phy interface instead.

Execution Context
Cell Context for all methods.

mdio45_phy

Description
SIM_INTERFACE(mdio45_phy) {
        uint16 (*read_register)(conf_object_t *obj, int mmd, int reg);
        void   (*write_register)(conf_object_t *obj, int mmd, int reg,
                                 uint16 value);

};
#define MDIO45_PHY_INTERFACE "mdio45_phy"

Interface that should be implemented by classes representing a single PHY implementing the IEEE 802.3 clause 45 MDIO management interface.

The read_register function should return the 16-bit value of the specified register. mmd specifies the MMD (MDIO manageable device) within the PHY (0-31) and reg specifies the register number within the MMD (0-65535).

Devices modeling either an MDIO bus, or multiple PHYs should implement the mdio45_bus interface instead.

Execution Context
Cell Context for all methods.

memory_space

Description
This interface is implemented by classes that provide linear address spaces.

Other objects may perform accesses in the address space using the access function or one of the simplified access functions, or may ask for mapped objects using space_lookup. Typical usage of this interface would be memory accesses from devices or processors.

The space_lookup function would be used to find end-points for a memory request. The mop needs to be crafted similarly as for a regular read or write operation and would typically be created with SIM_make_mem_op_read or SIM_make_mem_op_write. The return value for space_lookup is a list of all mappings that match the input mop.

The access function operates on a generic transaction that would typically be created with SIM_make_mem_op_read or SIM_make_mem_op_write. The access_simple function is similar to access but takes some additional arguments instead of a complete generic_transaction_t structure. An inquiry version of this function is available as access_simple_inq. Both these functions can perform endian conversion if the buffer pointed to by buf contains a value in host endian byte-order. To avoid endian conversion, Sim_Endian_Target should be specified as endian. These two functions are not available from Python.

The read and write methods are primarily intended for use in Python. They operate on data encapsulated in attribute values which should be of data type; in Python, this corresponds to tuples of integers (bytes). These two methods signal errors by raising a frontend exception. They can be used to read or write up to 1024 bytes in a single call. The return value from write should be ignored.

The fill method fills size bytes starting at start with value. It only works on memory, and returns the number of bytes actually written before encountering something that isn't RAM.

SIM_INTERFACE(memory_space) {
        map_list_t *(*space_lookup)(conf_object_t *NOTNULL obj,
                                    generic_transaction_t *NOTNULL mop,
                                    map_info_t mapinfo);
        exception_type_t (*access)(conf_object_t *NOTNULL obj,
                                   generic_transaction_t *NOTNULL mop);
#if !defined(PYWRAP)
        exception_type_t (*access_simple)(conf_object_t *obj,
                                          conf_object_t *initiator,
                                          physical_address_t addr,
                                          uint8 *buf,
                                          physical_address_t len,
                                          read_or_write_t type,
                                          endianness_t endian);
        exception_type_t (*access_simple_inq)(conf_object_t *obj,
                                              conf_object_t *initiator,
                                              physical_address_t addr,
                                              uint8 *buf,
                                              physical_address_t len,
                                              read_or_write_t type,
                                              endianness_t endian);
#endif /* !PYWRAP */
        attr_value_t (*read)(conf_object_t *NOTNULL obj,
                             conf_object_t *initiator,
                             physical_address_t addr,
                             int length,
                             int inquiry);
        exception_type_t (*write)(conf_object_t *NOTNULL obj,
                                  conf_object_t *initiator,
                                  physical_address_t addr,
                                  attr_value_t data,
                                  int inquiry);
        cycles_t (*DEPRECATED_FUNC(timing_model_operate))(
                conf_object_t *NOTNULL space,
                generic_transaction_t *NOTNULL mop);
        uint64 (*fill)(conf_object_t *NOTNULL obj,
                       physical_address_t start, uint64 size, uint8 value,
                       bool inquiry);
};

#define MEMORY_SPACE_INTERFACE "memory_space"

Execution Context
Cell Context for all methods.

microwire

Description
This interface is used to communicate with a 3-wire (microwire) serial EEPROM device, for example, the 93Cxx series, via its pins. To set the values of the CS, SK, and DI pins, use the set_cs(), set_sk(), and set_di() functions, respectively. To read the value output on the DO pin, use the get_do() function. Zero represents low signal and non-zero high signal. The read_word() and write_word() functions are provided to shortcut high-level operations. They operate on 8-bit or 16-bit entities depending on the width of the eeprom.

#define MICROWIRE_INTERFACE "microwire"

SIM_INTERFACE(microwire) {
        void (*set_cs)(conf_object_t *obj, int cs);
        void (*set_sk)(conf_object_t *obj, int sk);
        void (*set_di)(conf_object_t *obj, int di);
        int  (*get_do)(conf_object_t *obj);
        uint16 (*read_word)(conf_object_t *obj, int offset);
        void (*write_word)(conf_object_t *obj, int offset, uint16 value);
};

Execution Context
Cell Context for all methods.

mii

Description
SIM_INTERFACE(mii) {
        int    (*serial_access)(conf_object_t *obj, int data_in, int clock);
        uint16 (*read_register)(conf_object_t *obj, int index);
        void   (*write_register)(conf_object_t *obj, int index, uint16 value);
};
#define MII_INTERFACE "mii"

Obsolete interface that is implemented by some PHY's that support the MII management interface.

It has the same methods as the mii_management interface, but does not pass along the PHY number.

To support low-level bitwise accesses via MDIO and MDC pins, the function serial_access can be used. It is recommended to leave this function unimplemented and let an instance of mii-management-bus convert the low-level bit operations to higher level read/write register calls.

Execution Context
Cell Context for all methods.

mii_management

Description
SIM_INTERFACE(mii_management) {
        int    (*serial_access)(conf_object_t *obj, int data_in, int clock);
        uint16 (*read_register)(conf_object_t *obj, int phy, int reg);
        void   (*write_register)(conf_object_t *obj, int phy, int reg,
                                 uint16 value);
};
#define MII_MANAGEMENT_INTERFACE "mii_management"

Interface that should be implemented by classes that represents one or multiple PHY's that have MII management interfaces.

The read_register function should return the 16-bit value of the specified register. There are 32 registers numbered 0-31. The phy argument indicates the PHY number (0-31). Classes that represents one PHY can ignore this argument. The write_register function is called when a register is written.

To support low-level bitwise accesses via MDIO and MDC pins, the function serial_access can be used. It is recommended to leave this function unimplemented and let an instance of mii-management-bus convert the low-level bit operations to higher level read/write register calls. The serial_access function takes as argument the MDIO and MDC pin levels on the master, and return the MDIO pin from the slave. Note that mii-management-bus also have signal interfaces for these pins.

Execution Context
Cell Context for all methods.

mips

Description
This interface is implemented by MIPS processors to provide various functionality that is specific for this class of processors.

There are currently no MIPS-specific functions.

SIM_INTERFACE(mips) {
        int dummy;
};

#define MIPS_INTERFACE "mips"

Execution Context
Not applicable.

mips_cache_instruction

Description
This mips_cache_instruction interface is used when side-effects are wanted when cache instructions are run.

The cache_instruction function is called whenever the cache instruction is run, and the parameters operation and vaddr are taken directly from the instruction.

The exact meaning of operation is processor-dependent.

A non-zero return value indicates that an exception should be raised on the MIPS core), whereas a zero value means no exception.

SIM_INTERFACE(mips_cache_instruction) {
        int (*cache_instruction)(conf_object_t *NOTNULL self,
                                 conf_object_t *NOTNULL cpu,
                                 uint32 op, logical_address_t vaddr);
};
#define MIPS_CACHE_INSTRUCTION_INTERFACE "mips_cache_instruction"

Execution Context
Cell Context.

mips_coprocessor

Description
This mips_coprocessor interface is implemented by MIPS coprocessors. The MIPS processor cores use this interface to access coprocessor registers.

The read_register function returns a 64-bit value from a coprocessor register. The return value should be zero extended if the coprocessor register is less than 64-bits.

The write_register function writes a 64-bit value to a coprocessor register. The target register can be smaller than 64-bits.

The thread_id is the thread id for the calling processor core. The reg and sel selects the coprocessor register to read or write. For instructions that make use of the whole implementation-defined bits 15:0, that field is passed as reg and sel is zero.

SIM_INTERFACE(mips_coprocessor) {
        uint64 (*read_register)(conf_object_t *NOTNULL obj,
                                uint32 thread_id,
                                uint32 reg,
                                uint32 sel);
        void (*write_register)(conf_object_t *NOTNULL obj,
                               uint32 thread_id,
                               uint64 value,
                               uint32 reg,
                               uint32 sel);
};
#define MIPS_COPROCESSOR_INTERFACE "mips_coprocessor"

Execution Context
Cell Context for all methods.

mips_eic

Description
The mips_eic must be implemented by devices that acts as MIPS External Interrupt Controllers. After the external IRQ signal in the CPU has been raised, the CPU will query the registered External Interrupt Controller for information about the current interrupt request. When the CPU starts the interrupt servicing it calls the handled function.

The cpu_pending_irqs function sends current cause register which stores the pending irqs for software irq, timer irq, fdci irq and pci irq. The external irq controller should take this information to do irq arbitration.

requested_ipl should used to return the requested interrupt priority level.

There are two options for vector offset calculation. Option 1, EIC device returns a vector number. This vector number will be used together with intctl.vs to calculate the offset. Option 2, EIC returns the offset directly. When using option 1, the requested_vect_num function should be used to return the vector number. When using option 2, the requested_offset should be used to return the offset of the requested interrupt.

The reg_set should return the shadow register set number.

SIM_INTERFACE(mips_eic) {
        void (*cpu_pending_irqs)(conf_object_t *NOTNULL obj, uint32 cause);
        uint32 (*requested_ipl)(conf_object_t *NOTNULL obj);
        uint32 (*requested_offset)(conf_object_t *NOTNULL obj);
        uint32 (*requested_vect_num)(conf_object_t *NOTNULL obj);
        uint32 (*reg_set)(conf_object_t *NOTNULL obj);
        void (*handled)(conf_object_t *NOTNULL obj);
};

#define MIPS_EIC_INTERFACE "mips_eic"

Execution Context
Cell Context for all methods.

mips_exception_query

Description
Used to query information of an exception from a cpu_exception_cb_t callback.
SIM_INTERFACE(mips_exception_query) {
        logical_address_t (*return_pc)(conf_object_t *cpu,
                                       exception_handle_t *handle);
};

#define MIPS_EXCEPTION_QUERY_INTERFACE "mips_exception_query"

pc is used to get the address of the faulting instruction. return_pc is used to get the return address for the exception. number is used to get the exception number.

Execution Context
Cell Context for all methods.

mips_ite

Description
This mips_ite interface is implemented by the CPU, for communicating with the MIPS Inter-Thread Communication Unit.

The set_dtag_lo function sets the DTagLo SPR.

The get_dtag_lo function returns the value of the DTagLo SPR.

The get_errctl function returns the value of the ErrCtl SPR.

The block_tc function marks the current TC as blocked on gating storage and swaps in another TC.

The gated_exception function throws an immediate exception.

The current_tc_num function returns the currently running TC number on the VPE.

The unblock_tc function unblocks the specified TC if it is currently blocked on gating storage.

The is_big_endian function indicates if the CPU expects big endian memory storage.

SIM_INTERFACE(mips_ite) {
        void (*set_dtag_lo)(conf_object_t *NOTNULL obj, uint32 value);
        uint32 (*get_dtag_lo)(conf_object_t *NOTNULL obj);
        uint32 (*get_errctl)(conf_object_t *NOTNULL obj);
        void (*block_tc)(conf_object_t *NOTNULL obj);
        void (*gated_exception)(conf_object_t *NOTNULL obj);
        int (*current_tc_num)(conf_object_t *NOTNULL obj);
        void (*unblock_tc)(conf_object_t *NOTNULL obj, int tc_num);
        bool (*is_big_endian)(conf_object_t *NOTNULL obj);
};
#define MIPS_ITE_INTERFACE "mips_ite"

Execution Context
Cell Context for all methods.

multi_level_signal

Description
Interface to model a signal with multiple levels, such as an analog signal.

Note: Obsoleted by the uint64_state interface.
The signal initiator (i.e. the object producing the signal) should call signal_level_change when the level changes. Multiple calls with the same level should be accepted by the signal receiver.

The optional function signal_current_level can be called when a new target is connected.

SIM_INTERFACE(multi_level_signal) {
        void (*signal_level_change)(conf_object_t *NOTNULL obj, uint64 level);
        void (*signal_current_level)(conf_object_t *NOTNULL obj, uint64 level);
};
#define MULTI_LEVEL_SIGNAL_INTERFACE "multi_level_signal"

Execution Context
Cell Context for all methods.

nand_flash

Description
The nand_flash interface is used to perform read and write accesses and control some pins on NAND Flash devices.

The read_access() and write_access() functions perform read and write accesses.

The set_command_latch_enable(), set_address_latch_enable(), set_write_protect() and set_spare_area_enable() functions set the input level of the pins with the same names. 0 represents low input and 1 represents high input.

The chip enable and ready/busy pins are not modelled. The NAND Flash device assumes that chip enable is always asserted, and the device is never busy.

#define NAND_FLASH_INTERFACE "nand_flash"

SIM_INTERFACE(nand_flash) {
        uint16 (*read_access)(conf_object_t *obj);
        void (*write_access)(conf_object_t *obj, uint16 value);

        void (*set_command_latch_enable)(conf_object_t *obj, int value);
        void (*set_address_latch_enable)(conf_object_t *obj, int value);
        void (*set_write_protect)(conf_object_t *obj, int value);
        void (*set_spare_area_enable)(conf_object_t *obj, int value);
};

Execution Context
Cell Context for all methods.

network_breakpoint

Description
The network_breakpoint interface is implemented by objects that handles ethernet links to have breakpoints. The add is used to set a breakpoint on a given src mac address or gived dst mac address or by ether type. If they are combined then the criteria is that all given has to match. The remove is used to remove an existing breakpoint.
SIM_INTERFACE(network_breakpoint) {
        int64 (*add)(conf_object_t *NOTNULL obj, bytes_t src_mac_addr,
                     bytes_t dst_mac_addr, int ether_type,
                     break_net_cb_t cb, bool once, int64 bp_id);
        void (*remove)(conf_object_t *NOTNULL obj, int64 bp_id);
};
#define NETWORK_BREAKPOINT_INTERFACE "network_breakpoint"

Execution Context
Global Context for all methods

nios

Description
This interface is implemented by Intel® Nios® processors to provide various functionality that is specific for this class of processors.

There are currently no Nios-specific functions.

SIM_INTERFACE(nios) {
        int dummy;
};

#define NIOS_INTERFACE "nios"

Execution Context
Not applicable.

nios_cache

Description
This nios_cache interface is used when the side-effects are required for cache instructions.

Each function is called when the corresponding instruction is executed. See Nios® II processor reference guide, section 8, for further information.

SIM_INTERFACE(nios_cache) {
        void (*flushd)(conf_object_t *NOTNULL self, logical_address_t addr);
        void (*flushda)(conf_object_t *NOTNULL self, logical_address_t addr);
        void (*flushi)(conf_object_t *NOTNULL self, logical_address_t addr);
        void (*flushp)(conf_object_t *NOTNULL self);
        void (*initd)(conf_object_t *NOTNULL self, logical_address_t addr);
        void (*initda)(conf_object_t *NOTNULL self, logical_address_t addr);
        void (*initi)(conf_object_t *NOTNULL self, logical_address_t addr);
        void (*sync)(conf_object_t *NOTNULL self);
};
#define NIOS_CACHE_INTERFACE "nios_cache"

Execution Context
Cell Context for all methods.

nios_custom

Description
This nios_custom interface is used when the custom instruction needs to be used.

The custom function is called whenever the custom instruction is executed.

See Nios® II processor reference guide page 8-35 for further information about the parameters.

SIM_INTERFACE(nios_custom) {
        uint32 (*custom)(conf_object_t *NOTNULL self, uint32 n,
                         uint32 a, uint32 b, uint32 c, uint32 rA, uint32 rB,
                         bool readra, bool readrb, bool writerc);
};
#define NIOS_CUSTOM_INTERFACE "nios_custom"

Execution Context
Cell Context

nios_eic

Description
The nios_eic must be implemented by devices that acts as Nios® External Interrupt Controllers. After the external IRQ signal in the CPU has been raised, the CPU will query the registered External Interrupt Controller for information about the current interrupt request. When the CPU calls the handled function, it has finished processing the request.

The handler function should return the logical address of the interrupt handler.

The level should return the interrupt level.

The reg_set should return the shadow register set number.

The nmi should indicate if this is a non-maskable interrupt.

See Nios® II processor reference guide page 3-41 for further information.

SIM_INTERFACE(nios_eic) {
        logical_address_t (*handler)(conf_object_t *NOTNULL obj);
        uint32 (*level)(conf_object_t *NOTNULL obj);
        uint32 (*reg_set)(conf_object_t *NOTNULL obj);
        bool (*nmi)(conf_object_t *NOTNULL obj);

        void (*handled)(conf_object_t *NOTNULL obj);
};

#define NIOS_EIC_INTERFACE "nios_eic"

Execution Context
Cell Context for all methods.

pci_bridge

Description
This interface is implemented by all PCI bridges. For interrupts, the initiating device is specified with a pci-bus object and PCI device number pair, and the pin represents PCI interrupt lines (A, B, C, or D) as numbers in the range of 0 to 3.

SIM_INTERFACE(pci_bridge) {
        void (*system_error)(conf_object_t *obj);
        void (*raise_interrupt)(conf_object_t *obj, conf_object_t *pci_bus,
                                int device, int pin);
        void (*lower_interrupt)(conf_object_t *obj, conf_object_t *pci_bus,
                                int device, int pin);
};

#define PCI_BRIDGE_INTERFACE		"pci_bridge"

Execution Context
Cell Context for all methods.

pci_bus

Description
This interface is implemented by all PCI buses and its functions are accessed by PCI devices. For further details, see Model Builder User's Guide, chapter "Modeling PCI Devices".

Note: The memory_access function is deprecated and must not be called (as it is not implemented by Simics pci-bus object). The interrupt_acknowledge, special_cycle, add_default and remove_default functions are also deprecated, but they are still implemented by Simics pci-bus and thus callable.
SIM_INTERFACE(pci_bus) {
        /* Deprecated; memory_access */
        exception_type_t (*memory_access)(
                conf_object_t *obj, generic_transaction_t *NOTNULL mem_op);
        void (*raise_interrupt)(conf_object_t *obj, conf_object_t *NOTNULL dev,
                                int pin);
        void (*lower_interrupt)(conf_object_t *obj, conf_object_t *NOTNULL dev,
                                int pin);
        /* Deprecated; interrupt_acknowledge */
        int (*interrupt_acknowledge)(conf_object_t *obj);
        int (*add_map)(conf_object_t *obj, conf_object_t *dev,
                       addr_space_t space, conf_object_t *target,
                       map_info_t info);
        int (*remove_map)(conf_object_t *obj, conf_object_t *dev,
                          addr_space_t space, int function);
	void (*set_bus_number)(conf_object_t *obj, int bus_id);
	void (*set_sub_bus_number)(conf_object_t *obj, int bus_id);
        /* Deprecated; add_default, remove_default */
        void (*add_default)(conf_object_t *obj, conf_object_t *dev,
                            addr_space_t space, conf_object_t *target,
                            map_info_t info);
        void (*remove_default)(conf_object_t *obj, addr_space_t space);
        void (*bus_reset)(conf_object_t *obj);
        /* Deprecated; special_cycle */
        void (*special_cycle)(conf_object_t *obj, uint32 value);
        void (*system_error)(conf_object_t *obj);

        int (*get_bus_address)(conf_object_t *obj, conf_object_t *NOTNULL dev);

        void (*set_device_status)(conf_object_t *obj, int device, int function,
                                  int enabled);

        /* Memory spaces */
        conf_object_t *(*configuration_space)(conf_object_t *obj);
        conf_object_t *(*io_space)(conf_object_t *obj);
        conf_object_t *(*memory_space)(conf_object_t *obj);
};
#define PCI_BUS_INTERFACE		"pci_bus"

Execution Context
Cell Context for all methods.

pci_device

Description
This interface is implemented by all PCI devices (including bridges).

Note: The interrupt_acknowledge and special_cycle functions are deprecated. The functions can be left unimplemented (NULL).
SIM_INTERFACE(pci_device) {
        void (*bus_reset)(conf_object_t *obj);

        /* Deprecated; interrupt_acknowledge, special_cycle */
        int (*DEPRECATED_FUNC(interrupt_acknowledge))(conf_object_t *obj);
        void (*DEPRECATED_FUNC(special_cycle))(conf_object_t *obj,
                                               uint32 value);

        /* System Error */
        void (*system_error)(conf_object_t *obj);

        /* peer-to-peer interrupt mechanism */
        void (*interrupt_raised)(conf_object_t *obj, int pin);
        void (*interrupt_lowered)(conf_object_t *obj, int pin);
};

#define PCI_DEVICE_INTERFACE "pci_device"

Execution Context
Cell Context for all methods.

pci_downstream

Description
The pci_downstream interface is implemented by PCI(e) buses to handle downstream transactions.
SIM_INTERFACE(pci_downstream) {
        exception_type_t (*operation)(conf_object_t *obj,
                                      generic_transaction_t *mem_op,
                                      addr_space_t space);
};
#define PCI_DOWNSTREAM_INTERFACE   "pci_downstream"

Execution Context
Cell Context for all methods.

pci_express

Description
Deprecated as part of the old PCIe library. Replaced by the new PCIe library.

Note: This interface is deprecated. The transaction interface implemented by the pcie-bus (upstream and downstream ports) can be used to send any type of message with any type of routing by adding related pcie_type and pcie_msg_route ATOMs to the transaction.
This interface can be implemented by any PCI Express device, switch or endpoint. It is also implemented by the pci-bus, which will pass it on to the other end; e.g. if the endpoint sends a message, the pci-bus will pass it on to the bridge (downport), and if the downport sends it, it will be broadcasted to all devices on the bus.

Please note that message routing is not supported. The implications of this limitation is that a switch does not know if the message is intended for the switch itself or for some device connected to it. In addition, since the bus does not replace the src parameter when forwarding the message, and the bus does not support port mappings, it is impossible for a bus-to-bus bridge (up-port/down-port) to know from which bus the message originates making it impossible to forward the message to the other side.

Another way of looking at this limitation is to say that the only message routing currently supported is the implicit routing that terminates at the receiver (Type[2:0] = 0b100), so bus-to-bus bridges should not try to forward the message to the other side.

src is the object sending the message. type is one of:

typedef enum {
        /* Address Translation */
        PCIE_ATS_Invalidate = 0x01,
        PCIE_ATS_Invalidate_Completion = 0x02,
        PCIE_PRS_Request    = 0x04,
        PCIE_PRS_Response   = 0x05,

        PCIE_Latency_Tolerance_Reporting = 0x10,
        PCIE_Optimized_Buffer_Flush_Fill = 0x12,

        /* INTx emulation */
        PCIE_Msg_Assert_INTA       = 0x20,
        PCIE_Msg_Assert_INTB       = 0x21,
        PCIE_Msg_Assert_INTC       = 0x22,
        PCIE_Msg_Assert_INTD       = 0x23,
        PCIE_Msg_Deassert_INTA     = 0x24,
        PCIE_Msg_Deassert_INTB     = 0x25,
        PCIE_Msg_Deassert_INTC     = 0x26,
        PCIE_Msg_Deassert_INTD     = 0x27,

        /* Power Management */
        PCIE_PM_Active_State_Nak   = 0x14,
        PCIE_PM_PME                = 0x18,
        PCIE_PM_Turn_Off           = 0x19,
        PCIE_PM_PME_TO_Ack         = 0x1B,

        /* Error Messages */
        PCIE_ERR_COR               = 0x30,
        PCIE_ERR_NONFATAL          = 0x31,
        PCIE_ERR_FATAL             = 0x33,

        /* Locked Transaction */
        PCIE_Unlock                = 0x00,

        /* Slot Power Limit */
        PCIE_Set_Slot_Power_Limit  = 0x50,

        PCIE_Precision_Time_Measurement = 0x52,

        /* Hot Plug Messages */
        PCIE_HP_Power_Indicator_On        = 0x45,
        PCIE_HP_Power_Indicator_Blink     = 0x47,
        PCIE_HP_Power_Indicator_Off       = 0x44,
        PCIE_HP_Attention_Button_Pressed  = 0x48,
        PCIE_HP_Attention_Indicator_On    = 0x41,
        PCIE_HP_Attention_Indicator_Blink = 0x43,
        PCIE_HP_Attention_Indicator_Off   = 0x40,

        PCIE_Vendor_Defined_Type_0 = 0x7e,
        PCIE_Vendor_Defined_Type_1 = 0x7f,

        PCIE_Locked_Transaction    = 0x00,  // legacy name for PCIE_Unlock

        /* Data Link Layer (virtual) Messages

           NOTE: these messages only exist on Simics simulator, as they are
           normally part of the Data Link Layer which is below the level of
           abstraction for Simics PCIe models

           According to PCIe rev 2.0, when a target receives a message that it
           does not recognize or support, except for the "Vendor Defined Type
           1" message, it should treat the request as an "Unsupported Request"
           and report it accordingly (see sec 2.3.1 for reference).
    
           Hence models that comply with rev 2.0 must be updated to either
           1) handle these messages or 2) ignore these messages.

           Ideally we would like to use a new pcie_link interface to transmit
           this information - see bug 17849 for more info. */
        PCIE_DLL_Link_Down = -1,
        PCIE_DLL_Link_Up = -2,
} pcie_message_type_t;

The contents of payload depends on type.

SIM_INTERFACE(pci_express) {
        int (*send_message)(conf_object_t *dst, conf_object_t *src,
                            pcie_message_type_t type, byte_string_t payload);
};
#define PCI_EXPRESS_INTERFACE "pci_express"

Execution Context
Cell Context for all methods.

pci_express_hotplug

Description
Deprecated as part of the old PCIe library. Replaced by the new PCIe library.

This interface is intended for PCI Express switches that need to monitor the status of their downports. The interface should be implemented by the bridge object.

presence_change is called from the pci-bus when an device is added or removed from the bus. is_present is set to 1 when the device is added, and 0 when it is removed.

inject_power_fault can be used to simulate a power fault on the downport. It is never called automatically.

press_attention_button can be called to simulate the attention button being pressed. The switch can respond to this by e.g. raising an interrupt and setting appropriate status bits. It is never called automatically.

set_mrl_state is similar to attention_button_press but controls the Manually operated Retention Latch. Set locked to 1 to simulate it being locked/closed, and 0 to simulate it being unlocked/opened.

Finally, get_mrl_state returns the state of the Manually operated Retention Latch.

SIM_INTERFACE(pci_express_hotplug) {
        /* This is sent when a device is added or removed from the bus. */
        void (*presence_change)(conf_object_t *dst, conf_object_t *NOTNULL src,
                                int is_present);
        void (*inject_power_fault)(conf_object_t *obj);
        void (*press_attention_button)(conf_object_t *obj);
        void (*set_mrl_state)(conf_object_t *obj, int locked);
        int  (*get_mrl_state)(conf_object_t *obj);
};
#define PCI_EXPRESS_HOTPLUG_INTERFACE "pci_express_hotplug"

Execution Context
Cell Context for all methods.

pci_interrupt

Description
This interface should only be used when a device other than the bridge handles PCI interrupts on the PCI bus. The initiating device is specified with a PCI device number, and the pin represents PCI interrupt lines (A, B, C, or D) as numbers in the range of 0 to 3.

SIM_INTERFACE(pci_interrupt) {
        void (*raise_interrupt)(conf_object_t *obj, conf_object_t *pci_bus,
                                int device, int pin);
        void (*lower_interrupt)(conf_object_t *obj, conf_object_t *pci_bus,
                                int device, int pin);
};

#define PCI_INTERRUPT_INTERFACE		"pci_interrupt"

Execution Context
Cell Context for all methods.

pci_multi_function_device

Description
This interface is intended for PCI devices that want to have multiple functions implemented within the same device instance, as compared to the scheme of having each PCI function defined in a separate instance.

supported_functions is called from the pci-bus to find out how many functions are supported by this device. The expected return value is a list of tuples, where each tuple contains the PCI function number followed by one or two elements controlling what to map into the bus' config-space. The list can consist of any number of tuples using any and all of the supported formats:

  • (fun, str); maps the named port-interface on the object implementing the current interface. For example, the name of the bank that provides the configuration registers for this function.
  • (fun, obj); maps the object expecting configuration access is handled by io_memory implemented directly on the object.
  • (fun, obj, str); maps the named port-interface on the provided object.

The list can contain a mix of formats, each entry corresponds to a unique mapping of a function.

For ARI enabled PCIe devices, the device number is assumed to be zero thus it is an error to try to claim a function number greater than seven while connecting with a device number greater than zero.

SIM_INTERFACE(pci_multi_function_device) {
        attr_value_t (*supported_functions)(conf_object_t *obj);
};
#define PCI_MULTI_FUNCTION_DEVICE_INTERFACE "pci_multi_function_device"

Execution Context
Global Context for all methods.

pci_upstream

Description
This interface is implemented by PCI(e) buses and bridges to handle upstream transactions (primarily memory or IO).

A PCI(e) bus typically forwards all transactions to an upstream bridge.

PCI(e) bridges either forward a transaction to its primary side bus or initiate a downstream operation on the secondary bus using the pci_downstream interface.

It should be noted that a PCI bridge using this interface will see peer-to-peer traffic from its secondary interface; this is a difference compared to real hardware where such transactions never involve the bridge. To behave like real hardware, PCI bridges should send all peer-to-peer traffic downstream.

SIM_INTERFACE(pci_upstream) {
        exception_type_t (*operation)(conf_object_t *obj,
                                      generic_transaction_t *mem_op,
                                      addr_space_t space);
};
#define PCI_UPSTREAM_INTERFACE   "pci_upstream"

Execution Context
Cell Context for all methods.

pci_upstream_operation

Description
This interface is implemented by PCI(e) buses to handle upstream transactions (primarily memory or IO) from PCI(e) devices.

The initiator should be the PCI device object itself. There are currently no requirements on this object in terms of interfaces. It is intended for future use and could be left NULL.

The 16-bit Requester ID is provided by the rid parameter. This is the ID that uniquely identifies the initiator in a PCIe hierarchy, also more commonly known as the BDF (Bus/Device/Function). This ID can be left blank (0) by non-PCIe devices if the BDF is not known.

Return value is of type exception_type_t and maps, just like all other PCI interfaces, onto PCI concepts accordingly:

Sim_PE_No_Exception
OK
Sim_PE_IO_Not_Taken
Master Abort
Sim_PE_IO_Error
Target Abort

Other return values are currently unexpected.

SIM_INTERFACE(pci_upstream_operation) {
        exception_type_t (*read)(conf_object_t *obj,
                                 conf_object_t *initiator,
                                 uint16 rid,
                                 addr_space_t space,
                                 physical_address_t address,
                                 buffer_t buffer);
        exception_type_t (*write)(conf_object_t *obj,
                                  conf_object_t *initiator,
                                  uint16 rid,
                                  addr_space_t space,
                                  physical_address_t address,
                                  bytes_t buffer);
};
#define PCI_UPSTREAM_OPERATION_INTERFACE   "pci_upstream_operation"

Execution Context
Cell Context for all methods.

pcie_adapter_compat

Description
Deprecated as part of the old PCIe library. Replaced by the new PCIe library.

This interface is used by PCI buses that want to be compatible with PCIe devices created with the new PCIe library. This interface is implemented by the legacy-pcie-upstream-adapter.

SIM_INTERFACE(pcie_adapter_compat) {
        void (*set_secondary_bus_number)(conf_object_t *obj,
                                         int secondary_bus_number);
};
#define PCIE_ADAPTER_COMPAT_INTERFACE		"pcie_adapter_compat"


Execution Context
Cell Context for all methods.

pcie_device

Description
This interface must be implemented by all PCIe devices that can receive downstream transactions.

connected and disconnected are used to indicate that the device is (dis)connected to port_obj with device id device_id and may use the pcie_map interface to add/remove functions and claim/release other resources. These functions should only be called once for each (dis)connected physical device no matter how many physical or virtual functions it has. The device_id contains the device number (D part of B:D:F) and should use 0 as the function number (F part of B:D:F).

hot_reset is used to indicate that a Hot Reset has been signaled on the PCIe link to which the device is connected. It is up to the device to reset functions and other resources mapped using the pcie_map interface.

Note: This interface is considered tech-preview and may change without notice.

SIM_INTERFACE(pcie_device) {
        void (*connected)(conf_object_t *obj, conf_object_t *port_obj,
                          uint16 device_id);
        void (*disconnected)(conf_object_t *obj, conf_object_t *port_obj,
                             uint16 device_id);
        void (*hot_reset)(conf_object_t *obj);
};

#define PCIE_DEVICE_INTERFACE "pcie_device"

Execution Context
Global Context for all methods.

pcie_function_info

Description
This interface should be implemented by all PCIe functions that wants to provide useful information for inspecting the function.

get_device_id returns the device id of the function.

get_upstream_target returns the upstream target of the PCIe device the PCIe function belongs to.

is_virtual_function returns true if the function is a virtual function.

get_bar_map_obj returns the object that is mapped by the BAR at bar_offset. If there is no BAR register at bar_offset, NULL is returned. For a physical function, the bar_offset is the offset in the Type 0/1 Configuration Space Header. For a virtual function, the bar_offset is the offset in the SR-IOV Extended Capability structure of the associated physical function (starting at 0x24).

SIM_INTERFACE(pcie_function_info)
{
        uint16 (*get_device_id)(conf_object_t *obj);
        conf_object_t *(*get_upstream_target)(conf_object_t *obj);
        bool (*is_virtual_function)(conf_object_t *obj);
        conf_object_t *(*get_bar_map_obj)(conf_object_t *obj, uint8 bar_offset);
};

#define PCIE_FUNCTION_INFO_INTERFACE "pcie_function_info"

Execution Context
Cell Context for all methods.

pcie_hotplug_events

Description
This interface should be implemented by Hot-Plug capable Downstream Ports. Such devices should be either a Downstream Port of a PCI Express Switch or a Root Port of PCI Express Root Complex.

The device that implements this interface should on the invocation of any of the methods in this interface should do the following:

1. If the applicable Hot-Plug capability has been enabled, set the new value of the corresponding Hot-Plug event in the applicable register. 2. If the value changed from its previous value, set the changed register value for the applicable Hot-Plug event. 3. If the value changed from its previous value, notify software using an interrupt if notifications are enabled for the applicable Hot-Plug event and an interrupt mechanism has been configured by the software (MSI/MSI-X or PCI-compatible INTx Emulation).

The presence_change() method is called by the pcie-downstream-port (if its upstream target implements this interface) when it goes from having no adapter present to having an adapter present and vice versa.

SIM_INTERFACE(pcie_hotplug_events) {
        void (*presence_change)(conf_object_t *obj, pcie_hotplug_pd_t state);
        void (*power_fault)(conf_object_t *obj);
        void (*attention_button_pressed)(conf_object_t *obj);
        void (*mrl_sensor)(conf_object_t *obj, pcie_hotplug_mrl_t state);
        void (*data_link_layer)(conf_object_t *obj, bool is_active);
};

#define PCIE_HOTPLUG_EVENTS_INTERFACE "pcie_hotplug_events"

Execution Context
Cell Context for all methods.

pcie_map

Description
This interface is used to claim ranges in PCIe address spaces and to manage virtual functions.

Functions add_map and del_map are used to add and remove maps, map_obj will be mapped in the address space indicated by type according to the information in info.

Functions add_function, del_function, enable_function and disable_function are used to add, delete, enable and disable functions, both virtual and physical. The supplied map_obj must be a valid map-target, it will receive both Config and Message transactions. For Message transactions, the device id (not including bus number) will be in bits 55:48 of the 64-bit address. For Config transactions, the device id is not part of the address. The supplied device_and_function passed to these methods should contain the device and function number (D:F part of B:D:F).

The function get_device_id returns the current device id of dev_obj, as a 16 bit number. Note that the bus number part is saved immediately after the RC/Switch sets it, even if no successful Config-Write has been made.

Note: This interface is considered tech-preview and may change without notice.

typedef enum {
        PCIE_Type_Not_Set,
        PCIE_Type_Mem,
        PCIE_Type_IO,
        PCIE_Type_Cfg,
        PCIE_Type_Msg,
        PCIE_Type_Other,
} pcie_type_t;

SIM_INTERFACE(pcie_map) {
        void (*add_map)(conf_object_t *obj, conf_object_t *map_obj,
                        map_info_t info, pcie_type_t type);
        void (*del_map)(conf_object_t *obj, conf_object_t *map_obj,
                        physical_address_t base, pcie_type_t type);
        void (*add_function)(conf_object_t *obj, conf_object_t *map_obj,
                             uint16 device_and_function);
        void (*del_function)(conf_object_t *obj, conf_object_t *map_obj,
                             uint16 device_and_function);
        void (*enable_function)(conf_object_t *obj, uint16 device_and_function);
        void (*disable_function)(conf_object_t *obj,
                                 uint16 device_and_function);
        uint16 (*get_device_id)(conf_object_t *obj, conf_object_t *dev_obj);
};

#define PCIE_MAP_INTERFACE "pcie_map"

Execution Context
Cell Context for all methods.

pcie_port_control

Description
This interface is used to configure instances of the pcie-downstream-port

The set_secondary_bus_number method should be called whenever the Secondary Bus Number register in the Type 1 Configuration Header of this downstream port changes.

The hot_reset method sends a hot reset to all downstream devices

Note: This interface is considered tech-preview and may change without notice.

SIM_INTERFACE(pcie_port_control) {
        void (*set_secondary_bus_number)(conf_object_t *obj, uint64 value);
        void (*hot_reset)(conf_object_t *obj);
};

#define PCIE_PORT_CONTROL_INTERFACE "pcie_port_control"

Execution Context
Cell Context for all methods.

pmr

Description
SIM_INTERFACE(pmr) {
        uint64 (*get)(
                conf_object_t *obj,
                int pmr_number,
                bool instruction_read);
        void (*set)(
                conf_object_t *obj,
                int pmr_number,
                uint64 value,
                bool instruction_write);
};
#define PMR_INTERFACE "pmr"

This interface provides a way for a user to write their own handler for the performance monitor register bank. The processor's pmr_handler attribute should be set point at the to the module, which implements the pmr interface. When set, all reads and writes toward the defined PMR registers will be forwarded to the user module instead. Simics CPU module will perform all the privilege checks and only forward the read/write if it is permitted.

The supervisor registers are checkpointed by the CPU module and the register content for the PMR registers is distributed to the user module in the finalize phase, after the pmr_handler has been set.

The function get is used for attribute reads, int_register reads or for mfpmr instructions. The value for the PMR register should be returned. The instruction_read will be true only for mfpmr instructions, allowing distinction between register reads by the user and instructions which could have side-effects.

Similar, the set function is used for attribute writes, int_register writes or for mtpmr instructions. The instruction_write will be true only for mtpmr instructions. The value indicates the value written to the PMR register.

Execution Context
Cell Context for all methods.

port_space

Description
I/O port interface.
SIM_INTERFACE(port_space) {
        exception_type_t (*port_operation)(conf_object_t *NOTNULL pspace_obj,
                                           generic_transaction_t *NOTNULL mop,
                                           map_info_t map_info);
        attr_value_t (*read)(conf_object_t *NOTNULL obj,
                             conf_object_t *initiator,
                             physical_address_t addr,
                             int length,
                             int inquiry);
        exception_type_t (*write)(conf_object_t *NOTNULL obj,
                                  conf_object_t *initiator,
                                  physical_address_t addr,
                                  attr_value_t data,
                                  int inquiry);
};

#define PORT_SPACE_INTERFACE "port_space"

Execution Context
Cell Context for all methods.

ppc

Description
SIM_INTERFACE(ppc) {
        void (*PYTHON_METHOD clear_atomic_reservation_bit)(conf_object_t *cpu);
        void (*PYTHON_METHOD raise_machine_check_exception)(conf_object_t *cpu,
                                                            ppc_mc_exc_t exc);

        /* Timebase */
        unsigned (*PYTHON_METHOD get_timebase_enabled)(conf_object_t *cpu);
        void     (*PYTHON_METHOD set_timebase_enabled)(conf_object_t *cpu,
                                                       unsigned enabled);
        /* Power mode */
        ppc_sleep_state_t (*PYTHON_METHOD get_sleep_state)(conf_object_t *cpu);
        void (*PYTHON_METHOD set_sleep_state)(conf_object_t *cpu,
                                              ppc_sleep_state_t state);
};

#define PPC_INTERFACE "ppc"

The clear_atomic_reservation_bit() function clears the reservation bit which is set by an lwarx instruction. Clearing the reservation will cause a following stwcx. instruction to fail. This function is typically used by a cache hierarchy supporting SMP.

The raise_machine_check_exception() function raises a machine check exception. The exc argument is of the following type:

typedef enum {
        Sim_PPC_Generic_MC,

        Sim_PPC_MC_TEA,
        Sim_PPC_MC_MCP,
        Sim_PPC_Bus_Address_Parity,
        Sim_PPC_Bus_Data_Parity,
        Sim_PPC_Instruction_Cache_Parity,
        Sim_PPC_Data_Cache_Parity,
        Sim_PPC_L2_Data_Parity,
        Sim_PPC_L3_Data_Parity,
        Sim_PPC_L3_Address_Parity,
        
        Sim_PPC970_Data_Cache_Parity,
        Sim_PPC970_Data_Cache_Tag_Parity,
        Sim_PPC970_D_ERAT_Parity,
        Sim_PPC970_TLB_Parity,
        Sim_PPC970_SLB_Parity,
        Sim_PPC970_L2_Load_ECC_Parity,
        Sim_PPC970_L2_Page_Table_ECC_Parity,
        Sim_PPC970_Uncacheable_Load_Parity,
        Sim_PPC970_MC_External
} ppc_mc_exc_t;

The get_timebase_enabled and set_timebase_enabled functions can be used to query and set the enabled state of the timebase.

Execution Context
Cell Context for all methods.

pulse

Description
Interface to model a pulse, meaning an event that triggers.

SIM_INTERFACE(pulse) {
        void (*pulse)(conf_object_t *NOTNULL obj);
};

#define PULSE_INTERFACE "pulse"

Execution Context
Cell Context for all methods.

ram

Description

The ram interface is implemented by classes that provide random access read/write memory. The rom interface is identical to ram but provides read only memory (writes are dropped by the memory system).

Both the ram and rom interfaces are Simics internal, and should not be used by user-defined classes.

The get_page method is obsolete and should not be implemented.

The fill method fills a range with a specified byte value.

The read method reads a number of bytes from address addr into the buffer data. The number of bytes read is given by the buffer size.

The write method writes the bytes in data to address addr.

The touch method is similar to the read and write methods, except that no data is actually transferred; the method triggers side effects like revoking conflicting direct-memory permissions from affected pages. The rw argument determines whether the operation is a handled as a read or as a write.

The flags argument is a bitmask which modify the behavior of read, write and touch operations in various ways.

The size method returns the memory size in bytes; that is, the highest usable address plus one.

typedef enum {
        Sim_Ram_Op_Fetch = 1,           /* Read is an instruction fetch. */
        Sim_Ram_Op_Non_Coherent = 2,    /* Operation should not cause
                                           atomic reservations to be lost. */
} ram_operation_flags_t;

SIM_INTERFACE(ram) {
#ifndef PYWRAP
        /* The get_page is method is obsolete and should be left
           unimplemented. */
        page_t *(*get_page)(conf_object_t *NOTNULL obj,
                            physical_address_t addr);
#endif
        void (*fill)(conf_object_t *NOTNULL obj,
                     physical_address_t start, uint64 length, uint8 value);

        exception_type_t (*read)(conf_object_t *NOTNULL obj,
                                 conf_object_t *initiator,
                                 uint64 addr, buffer_t data,
                                 ram_operation_flags_t flags);
        
        exception_type_t (*write)(conf_object_t *NOTNULL obj,
                                  conf_object_t *initiator,
                                  uint64 addr, bytes_t data,
                                  ram_operation_flags_t flags);
        
        exception_type_t (*touch)(conf_object_t *NOTNULL obj,
                                  conf_object_t *initiator,
                                  uint64 addr, uint64 size,
                                  read_or_write_t rw,
                                  ram_operation_flags_t flags);

        uint64 (*size)(conf_object_t *NOTNULL obj);
};
#define RAM_INTERFACE "ram"
#define ROM_INTERFACE "rom"

typedef ram_interface_t rom_interface_t;

Execution Context
Cell Context for all methods.

riscv_coprocessor

Description
The riscv_coprocessor interface makes it possible for RISC-V processors to read and write Control and Status Registers (CSRs) like mtime

SIM_INTERFACE(riscv_coprocessor) {
        uint64 (*read_register)(conf_object_t *obj, uint64 number);
        void (*write_register)(conf_object_t *obj, uint64 number, uint64 value);
};

#define RISCV_COPROCESSOR_INTERFACE "riscv_coprocessor"

Execution Context
Cell Context for all methods.

riscv_custom_csr

Description
The riscv_custom_csr interface lets other Simics objects implement custom CSR-registers and get callback for each access.

For the methods below, cpu is the RISC-V CPU model that is extended and ext_obj is the extension object.

The register_csr method registers a custom CSR at csr_address. The arguments name and description are for disassembly and int_register interface. The argument access is the function implementing the CSR access. Return true if CSR is successfully registered.

typedef enum {
        /* Access through csr/csri instruction */
        Riscv_CSR_Instruction_Access = Sim_Gen_Spr_Instruction_Access,

        /* Access through attribute */
        Riscv_Attribute_Access = Sim_Gen_Spr_Attribute_Access,

        /* Access through int_register_interface */
        Riscv_Int_Register_Access = Sim_Gen_Spr_Int_Register_Access,
} riscv_csr_access_type_t;

typedef uint64 (*riscv_csr_access_cb_t)(conf_object_t *obj,
                                        conf_object_t *cpu,
                                        uint32 csr_address,
                                        uint64 value,
                                        uint64 write_mask,
                                        riscv_csr_access_type_t type);

The register_reset method registers a reset callback for the extension. The reset_func callback will be called in connection with the core CPU reset flow.

typedef uint64 (*riscv_reset_cb_t)(conf_object_t *obj,
                                   conf_object_t *cpu);

SIM_INTERFACE(riscv_custom_csr) {

        bool (*register_csr)(conf_object_t *cpu,
                             conf_object_t *ext_obj,
                             uint32 csr_address,
                             const char *name,
                             const char *description,
                             riscv_csr_access_cb_t access);

        void (*register_reset)(conf_object_t *cpu,
                               conf_object_t *csr_obj,
                               riscv_reset_cb_t reset_func);
};

#define RISCV_CUSTOM_CSR_INTERFACE "riscv_custom_csr"

Execution Context
Global Context for all methods.

riscv_imsic

Description
RISC-V Internal interface.

SIM_INTERFACE(riscv_imsic) {
        // GEILEN
        uint32 (*num_guest_files)(conf_object_t *obj);

        // id is either one of the standard files, machine or supervisor,
        // or one of the guest files (vgein).

        uint64 (*read_irq_file)(conf_object_t *obj, riscv_imsic_file_id_t id, uint32 offset);
        uint64 (*read_and_write_irq_file)(conf_object_t *obj, riscv_imsic_file_id_t id,
                                          uint32 offset, uint64 new_value, uint64 mask);

        uint64 (*read_xtopei)(conf_object_t *obj, riscv_imsic_file_id_t id);
        uint64 (*read_and_write_xtopei)(conf_object_t *obj, riscv_imsic_file_id_t id,
                                        uint64 value, uint64 mask);
};

#define RISCV_IMSIC_INTERFACE "riscv_imsic"

Execution Context
Cell Context for all methods.

riscv_instruction_action

Description
The riscv_instruction_action interface helps with implementing semantics for user defined instruction.

The cpu argument in all methods below is the processor object implementing this interface.

X registers read_X_register return the current value of X register number. write_X_register updates the value of X register number to value. To help with disassembly name_X_register returns the name of the X register number.

Control and status registers, CSRs These accesses are not seen as instruction accesses, all access checks are bypassed and no exception will be thrown. read_CSR returns current value of the CSR at address. write_CSR updates the value of the CSR at address to value. Not all bits of all CSRs is writable.

Memory accesses using logical address A logical address is passed through MMU based on current mode. This means that an access can raise exception for page fault or illegal access. read_memory returns a value of size> bytes zero extended to 64 bits from memory at address/ write_memory writes size bytes to memory at address. Both read_memory and write_memory can raise exception for unaligned data access if the core does not support unaligned accesses.

load_memory_buf loads buf.len bytes from address to buf. store_memory_buf writes buf.len bytes from buf to address. These methods do not raise exception for unaligned accesses, instead large and/or unaligned accesses are broken down to multiple smaller aligned accesses.

Other get_current_cpu_mode returns current cpu mode. raise_exception raises exception with code put in th xCAUSE CSR and tval put in the xTVAL CSR.

SIM_INTERFACE(riscv_instruction_action) {
        uint64 (*read_x_register)(conf_object_t *cpu, uint32 number);
        void (*write_x_register)(conf_object_t *cpu, uint32 number, uint64 value);
        const char * (*name_x_register)(conf_object_t *cpu, uint32 number);

        uint64 (*read_csr)(conf_object_t *cpu, uint32 address);
        void (*write_csr)(conf_object_t *cpu, uint32 address, uint64 value);

        // Logical address
        uint64 (*read_memory)(conf_object_t *cpu, uint64 address,
                              uint32 size);
        void (*write_memory)(conf_object_t *cpu, uint64 address,
                             uint32 size, uint64 value);

        void (*load_memory_buf)(conf_object_t *cpu, uint64 address, buffer_t buf);
        void (*store_memory_buf)(conf_object_t *cpu, uint64 address, bytes_t buf);

        riscv_cpu_mode_t (*get_current_cpu_mode)(conf_object_t *cpu);

        void (*raise_exception)(conf_object_t *cpu, uint64 code, uint64 tval);
};

#define RISCV_INSTRUCTION_ACTION_INTERFACE "riscv_instruction_action"

Execution Context
Threaded Context for all methods. Must be only called from within an instruction emulation callback registered using the cpu_instruction_decoder interface.

riscv_signal_sgeip

Description
The riscv_signal_sgeip interface makes it possible to signal Supervisor Guest External (SGE) interrupts with a corresponding vgein. This is used together with an IMSIC and signaled from the IMSIC.
SIM_INTERFACE(riscv_signal_sgeip) {
        void (*signal_raise)(conf_object_t *NOTNULL obj, uint64 vgein);
        void (*signal_lower)(conf_object_t *NOTNULL obj, uint64 vgein);
};

#define RISCV_SIGNAL_SGEIP_INTERFACE "riscv_signal_sgeip"

Execution Context
Cell Context for all methods.

rs232_console

Description
Currently Simics internal.

typedef enum {
        Stop_Bits_1,
        Stop_Bits_1p5,
        Stop_Bits_2
} stop_bits_t;

typedef enum {
        Parity_None,
        Parity_Even,
        Parity_Odd
} parity_mode_t;


SIM_INTERFACE(rs232_console) {
        /* Set line parameters */
        void (*set_baudrate)(conf_object_t *obj, int rate, int commit);
        void (*set_data_bits)(conf_object_t *obj, int bits, int commit);
        void (*set_stop_bits)(conf_object_t *obj, stop_bits_t stop_bits,
                              int commit);
        void (*set_parity_mode)(conf_object_t *obj, parity_mode_t parity_mode,
                                int commit);

        /* Flow control lines */
        void (*set_dtr)(conf_object_t *obj, int status);
        void (*set_rts)(conf_object_t *obj, int status);

        /* Break */
        void (*set_break)(conf_object_t *obj, int status);
};

#define RS232_CONSOLE_INTERFACE "rs232_console"

Execution Context
Cell Context for all methods.

rs232_device

Description
Currently Simics internal.

SIM_INTERFACE(rs232_device) {
        /* Flow control lines */
        void (*cts)(conf_object_t *obj, int status);
        void (*dsr)(conf_object_t *obj, int status);

        /* Ring indicator */
        void (*ring)(conf_object_t *obj, int status);

        /* Carrier detect */
        void (*carrier)(conf_object_t *obj, int status);

        /* Break */
        void (*got_break)(conf_object_t *obj);

        /* Frame error */
        void (*got_frame_error)(conf_object_t *obj);
};

#define RS232_DEVICE_INTERFACE "rs232_device"

Execution Context
Cell Context for all methods.

sata

Description
SIM_INTERFACE(sata) {
        void (*receive_fis)(conf_object_t *obj, const bytes_t fis);
};

#define SATA_INTERFACE "sata"

This interface is implemented by SATA objects that provide an interface for serial data delivery.

This interface can be used in both direction in SATA communication. The receive_fis function is used by a device to send a SATA FIS to the SATA controller(HBA). The same function is used when sending a SATA FIS from HBA to SATA device. The FIS should be a bytes_t containing a complete SATA FIS. Different types of FIS may have different length. Please follow SATA specification when determine the length and content of the FIS.

Execution Context
Cell Context for all methods.

scale_factor_listener

Description
The scale_factor_listener interface is used for modeling changes in scale factors. It is mainly used by the frequency_bus device, to allow an external device to affect how much the bus scales its input frequency.

The scale_factor_listener has exactly the same semantics as the frequency_listener interface, the two interfaces only differ in convention: The parameters to scale_factor_listener.set() are typically a scale factor rather close to 1, while the parameters of frequency_listener represent a base frequency in Hz, which is typically significantly larger than 1000000.

See the documentation on the frequency_listener interface for more information.

SIM_INTERFACE(scale_factor_listener) {
        void (*set)(conf_object_t *NOTNULL obj, uint64 numerator,
                    uint64 denominator);
};

#define SCALE_FACTOR_LISTENER_INTERFACE "scale_factor_listener"

Execution Context
Cell Context for all methods.

serial_device

Description
Interface used to connect serial devices together. It can be implemented both by devices such as UARTs and text consoles, and by links.

A character (byte) is sent with the write() function; obj is the receiving device or link, and value is either a data byte, or the out-of-band value TTY_ABORT.

The receiver will return the number of characters accepted; i.e. 1 on success and 0 if it could not handle the new byte. If the receiver returns 0, it must later call receive_ready() in the sender's serial_device interface to signal that new bytes can now be accepted. A serial device must handle the case where the receive_ready() function is called although it has no more bytes to send.

#define TTY_ABORT   0x100

SIM_INTERFACE(serial_device) {
        int (*write)(conf_object_t *obj, int value);
        void (*receive_ready)(conf_object_t *obj);
};

#define SERIAL_DEVICE_INTERFACE "serial_device"

Execution Context
Cell Context for all methods.

serial_peripheral_interface_master

Description
SIM_INTERFACE(serial_peripheral_interface_master) {
        void (*spi_response)(conf_object_t *obj, int bits, dbuffer_t *payload);
};

#define SERIAL_PERIPHERAL_INTERFACE_MASTER_INTERFACE \
        "serial_peripheral_interface_master"

The serial_peripheral_interface_master interface is implemented by all SPI master devices. The interface contains a single function spi_response, called by the slave device in response to a spi_request call. The parameters bits and payload have the same meaning as in the spi_request call, and a SPI response should always have the same length in bits as the corresponding request.

SEE ALSO
serial_peripheral_interface_slave_interface_t
Execution Context
Cell Context for all methods.

serial_peripheral_interface_slave

Description
SIM_INTERFACE(serial_peripheral_interface_slave) {
        void (*spi_request)(conf_object_t *obj, int first, int last,
                            int bits, dbuffer_t *payload);
        void (*connect_master)(conf_object_t *obj, conf_object_t *master,
                               const char *port,
                               serial_peripheral_interface_flags_t flags);
        void (*disconnect_master)(conf_object_t *obj, conf_object_t *master);
};

#define SERIAL_PERIPHERAL_INTERFACE_SLAVE_INTERFACE \
        "serial_peripheral_interface_slave"

The serial_peripheral_interface_slave interface is implemented by all SPI slave devices.

The connect_master and disconnect_master functions are used to select which master device is connected. At most one master device can be connected to a slave device at once. The flags parameter to connect_master should be set according to the documentation of the serial_peripheral_interface_flags_t type.

An SPI transfer consists of a number of consecutive calls to the spi_request function. The parameters first and last represent the rise and fall of the Slave Select (SS) pin: first is true on the first spi_request call of a transfer, while last is true on the last call of a transfer.

The bits and payload parameters describe the data sent by the master device. bits defines the number of bits to send, while payload defines the data to transfer. The size of the payload buffer should be ceil(bits / 8) bytes. The first byte corresponds to the first 8 sent bits, and the least significant bit in each byte corresponds to the first sent bit. For example, the 11-bit sequence (first) 11011111101 (last) will be represented as two bytes, 0xfb followed by 0x5.

SEE ALSO
serial_peripheral_interface_master_interface_t, serial_peripheral_interface_flags_t
Execution Context
Cell Context for all methods.

signal

Description
The signal interface is for modeling a logical signal, such as a reset or interrupt. Signals are always active high in Simics with respect to their function. This may not correspond to the actual electrical level in a real system.

A signal connection has one initiator and one target object, where the initiator calls methods the interface implemented by the target.

The initiator object should have a configuration attribute that pointing to the target object or to an interface port of the target. This attribute, like all other attributes representing object connections, should be of the object kind, or a list of two entries where the first is an object and the second a string representing the name of the port.

The initiator should call signal_raise() to raise the signal level to its active level in the target. Once raised, the same initiator may not call signal_raise() again without an intervening call to signal_lower(). Similarly, an already low signal may not be lowered again by a signal_lower() call from the same initiator. The two functions represent the rising and the falling edge of the signal.

The target should handle the case where a signal is lowered directly after it has been raised and treat this call sequence as a valid pulse even within a single clock cycle. The target should also allow the signal to remain raised for some time before it is lowered.

While a target is disconnected, the input signal level is assumed to be low. When an initiator connects to a target by hot plugging, signal_raise() should be called if the output signal from the initiator was high. If the signal was low, then no function in the target should be called.

If the signal level is high on disconnect, then the initiator has to call signal_lower() before disconnecting from the target. Connect and disconnect is typically done by changing the attribute in the initiator that identifies the target object.

When an initiator is reset, it should call signal_lower() if the actual hardware also lowers the output signal on a reset. The target, on the other hand, should not reset its remembered value of the input.

When a connection attribute is restored from a checkpoint or during reverse execution, no function should be called in the signal interface of the target since the actual signal level does not change. The attribute setter code can distinguish between hot-plugging and state restoring by using SIM_object_is_configured() and SIM_is_restoring_state. See the latter of the two for more documentation.

When an object is first created and the initial signal level is high, the initiator has to call the signal_raise() function in the target. This can not be done earlier than in finalize_instance (C/C++) or in post_init() (DML) since the target has to be fully configured. Again, this should not be done when restoring a checkpoint.

There must only be a single initiator connected to a target, with the exception of the signal-bus that may have several initiators.

A target that needs more than one input signal should use ports to implement several signal interfaces.

SIM_INTERFACE(signal) {
        void (*signal_raise)(conf_object_t *NOTNULL obj);
        void (*signal_lower)(conf_object_t *NOTNULL obj);
};

#define SIGNAL_INTERFACE "signal"

Execution Context
Cell Context for all methods.

simple_dispatcher

Description
The simple_dispatcher interface is used for subscribing to changes of some monitored state. The interface is currently used for subscribing to changes in frequencies and to changes in frequency scale factors, via the interfaces frequency_listener and scale_factor_listener, respectively.

A device subscribes with the subscribe function. Before this function returns, it should send a signal to the calling object, telling the current state. After this, signals should be sent whenever the monitored state changes.

The function unsubscribe should be used to unsubscribe from monitored changes. A listener may not subscribe or unsubscribe twice on the same port.

SIM_INTERFACE(simple_dispatcher) {
        void (*subscribe)(conf_object_t *NOTNULL bus,
                          conf_object_t *NOTNULL listener,
                          const char *listener_port);
        void (*unsubscribe)(conf_object_t *NOTNULL bus,
                            conf_object_t *NOTNULL listener,
                            const char *listener_port);
};

#define SIMPLE_DISPATCHER_INTERFACE "simple_dispatcher"

Execution Context
Global Context for all methods.

simple_interrupt

Description
A device calls interrupt() to logically raise an interrupt and interrupt_clear() to lower an interrupt.

The first argument is the object to interrupt, usually a cpu. The integer argument to both functions may indicate an interrupt level or interrupt pin depending on the receiving device.

On ARM the integer argument indicates whether the interrupt is normal or fast, by being either ARM_INT_IRQ or ARM_INT_FIQ defined by the ARM API (by including <simics/arch/arm.h>).

Note: Obsoleted by the signal interface.
SIM_INTERFACE(simple_interrupt) {
        void (*interrupt)(conf_object_t *NOTNULL obj, int value);
        void (*interrupt_clear)(conf_object_t *NOTNULL obj, int value);
};

#define SIMPLE_INTERRUPT_INTERFACE "simple_interrupt"

Execution Context
Cell Context for all methods.

smm_instrumentation_subscribe

Description
This interface allows a user to keept track of System Management Mode switches in the processor.

The register_smm_enter_before_cb registers a callback of type smm_switch_cb_t that will be called before the processor enters System Management Mode.

The register_smm_enter_after_cb registers a callback of type smm_switch_cb_t that will be called after the processor has entered System Management Mode.

The register_smm_leave_before_cb registers a callback of type smm_switch_cb_t that will be called before the processor leaves System Management Mode.

The register_smm_leave_after_cb registers a callback of type smm_switch_cb_t that will be called after the processor has left System Management Mode.

The callback in all cases looks like this: This callback type is used by the smm_instrumentation_subscribe to implement instrumentation.

typedef void (*smm_switch_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        lang_void *user_data);

The obj argument is the user object that registered the callback, or NULL if no such object exists.

The cpu argument is the processor that enters/leaves System Management Mode.

The user_data argument is the callback user data, passed to the register methods.

Execution Context
Global Context for all methods.

sparc_v8

Description
SIM_INTERFACE(sparc_v8) {
        uint64 (*read_window_register)(conf_object_t *cpu, int window, int reg);

        void (*write_window_register)(conf_object_t *cpu,
                                      int window, int reg, uint64 value);
        void (*power_down)(conf_object_t *cpu);
};
#define SPARC_V8_INTERFACE "sparc_v8"

SPARC V8 specific functions.

This interface is implemented by SPARC V8 processors to provide various functionality that is specific for this class of processors.

The read_window_register and write_window_register functions can be used to access registers in any register window.

The register number when accessing windowed registers is 0 - 7 for accesses to the global registers, 8 - 15 for the out registers of the selected window, 16 - 23 for the local registers, and 24 - 31 for the in registers.

The power_down function is used to command the processor to enter power down mode. During power down mode, the processor will not execute any instructions, it will instead fast forward the execution to the next event. If the event is an external interrupt the power down mode is exited and execution resumed, in other cases the event will be handled and the processor will remain in power down mode and fast forward to the next event.

One use for the power_down function is for example to have an external device such as an memory mapped PMU force the processor into power down mode.

Execution Context
Cell Context for all methods.

sparc_v8_ecc_fault_injection

Description
SIM_INTERFACE(sparc_v8_ecc_fault_injection) {
        void (*inject_instr_access_exception)(conf_object_t *cpu);
        void (*inject_data_access_exception)(conf_object_t *cpu);
        void (*inject_reg_access_error)(conf_object_t *cpu);        
};
#define SPARC_V8_ECC_FAULT_INJECTION_INTERFACE "sparc_v8_ecc_fault_injection"

Support the injection of uncorrectable ECC faults. It can be used to inject (1) V8_Exc_Data_Access_Exception, (2) V8_Exc_Instruction_Access_Exception, and (3) V8_Exc_R_Register_Access_Error. The functions in this interface can only be called by breakpoint callback functions. Once an ecc fault is injected, new ecc faults can not be injected until the current one is handled.

The inject_data_access_exception plants an V8_Exc_Data_Access_Error for memory access on a location. The fault is injected when the breakpoint callback function of the location is called.

The inject_instr_access_exception plants an V8_Exc_Instruction_Access_Exception for an instruction, and this fault is injected when the breakpoint callback function of the instruction location is called.

The inject_data_access_exception is used for injecting V8_Exc_R_Register_Access_Error for a register access. It is right now not implemented.

Execution Context
Cell Context for all methods.

spr

Description
SIM_INTERFACE(spr) {
        void (*register_user_handlers)(
                conf_object_t *cpu,
                int64 spr_number,
                gen_spr_user_getter_func_t getter,
                lang_void *user_getter_data,
                gen_spr_user_setter_func_t setter,
                lang_void *user_setter_data,
                int privilege_checks);
        void (*unregister_user_handlers)(
                conf_object_t *cpu,
                int64 spr_number);

        void (*set_target_value)(
                conf_object_t *cpu,
                uint64 value);

        void (*stash_value)(
                conf_object_t *cpu,
                int64 spr_number,
                uint64 value);
        uint64 (*fetch_value)(
                conf_object_t *cpu,
                int64 spr_number);

        gen_spr_ret_t (*default_getter)(
                conf_object_t *cpu,
                int64 spr_number,
                gen_spr_access_type_t type);
        gen_spr_ret_t (*default_setter)(
                conf_object_t *cpu,
                int64 spr_number,
                uint64 value,
                gen_spr_access_type_t type);

        const char *(*get_name)(
                conf_object_t *cpu,
                int64 spr_number);
        int64 (*get_number)(
                conf_object_t *cpu,
                const char *spr_name);

};
#define SPR_INTERFACE "spr"

The register_spr_user_handlers function will register user implemented get and set functions that will be called every time a read or write access is made to the SPR with number spr. The getter and setter function is of the following type:

typedef gen_spr_ret_t (*gen_spr_user_getter_func_t)(
        conf_object_t *cpu,
        int64 spr_number,
        gen_spr_access_type_t type,
        lang_void *user_data);

The type parameter in the get and set functions is one of the following, depending on where from the access originated:

typedef enum {
        /* Access from a mfspr/mtspr instruction */
        Sim_Gen_Spr_Instruction_Access,

        /* Access through attribute */
        Sim_Gen_Spr_Attribute_Access,

        /* Access through int_register interface */
        Sim_Gen_Spr_Int_Register_Access,

        /* For compatibility with former PPC-only implementation */
        Sim_PPC_Spr_Instruction_Access  = Sim_Gen_Spr_Instruction_Access,
        Sim_PPC_Spr_Attribute_Access    = Sim_Gen_Spr_Attribute_Access,
        Sim_PPC_Spr_Int_Register_Access = Sim_Gen_Spr_Int_Register_Access
} gen_spr_access_type_t;

Both the get and the set functions must return one of these enum values:

typedef enum {
        Sim_Gen_Spr_Ok,        /* SPR access was OK */
        Sim_Gen_Spr_Illegal,   /* SPR access should trigger illegal insn exc */
        Sim_Gen_Spr_Privilege, /* SPR access should trigger privilege exc */

        Sim_Gen_Spr_Processor_Sleeps, /* SPR access suspends the processor */

        /* For compatibility with former PPC-only implementation */
        Sim_PPC_Spr_Ok        = Sim_Gen_Spr_Ok,
        Sim_PPC_Spr_Illegal   = Sim_Gen_Spr_Illegal,
        Sim_PPC_Spr_Privilege = Sim_Gen_Spr_Privilege
} gen_spr_ret_t;

If privilege_checks is not zero, Simics will do privilege checks when a mfspr/mtspr instruction is executed. If this does not produce the desired results, you can register the SPR handlers with privilege_checks set to zero, and do you own checks in your handlers.

The function unregister_spr_user_handlers will remove any registered user handlers for a particular SPR.

The function spr_set_target_value should be called from the get function. The value will be written to the target register for instruction accesses, and returned for attribute and int register interface accesses. If this function is not called, the target register is not changed for instruction accesses (and the mfspr thus acts as a nop).

The functions spr_stash_value and spr_fetch_value can be used to store a SPR value in the processor. This is useful if only the getter (or only the setter) has been overridden with a user handler.

Sometimes it may be desirable to let the processor take care of the access. The functions spr_default_getter and spr_default_setter exist for this purpose.

The function spr_get_name takes spr_number as parameter and returns the name of the SPR.

The function spr_get_number takes the spr_name and returns the SPR number, or -1 if the register does not exist.

Note that the following registers cannot be overridden with user handlers: xer, lr and ctr.

Execution Context
register_user_handlers Global Context
unregister_user_handlers Global Context
set_target_valueCell Context
stash_valueCell Context
fetch_valueCell Context
default_getterCell Context
default_setterCell Context
get_nameCell Context
get_numberCell Context

telemetry

Description
The telemetry interface is used to fetch telemetry data.

A model implements one or more telemetry-classes. These are identified by an identifier (class ID) and a name. The telemetries also has a name and an identifier (telemetry ID).

This layout forms a two level hierarchy with classes and their telemetries. The class and telemetry ID's are represented as integers and must be part of a contiguous range starting from zero, i.e., the hierarchy can be viewed as a table with telemetries, where the row numbers (>= 0), represents the class ID's, and the column numbers (>=0) represents the telemetry ID's. For unknown ID's NULL should be returned.

Both telemetry_class_id and telemetry_id can be enumerated using the functions get_telemetry_class_name and get_telemetry_name by starting with an ID of zero and go upp until NULL is returned. A model should not log an error when an invalid ID is presented (but logging info on level 3 makes sense for debug purposes). Error handling for missing expected telemetry IDs should be handled in the model requesting and retrieving the telemetry value.

The get_telemetry_class_id function returns the telemetry_class_id for the telemetry class with name telemetry_class_name. If no telemetry class with that name is found or that telemetry class is not enabled a negative number is returned.

The get_telemetry_class_name returns the name of the corresponding telemetry_class_id. If no telemetry class is found with that id the value NULL is returned.

The get_telemetry_class_description can return a description string for the telemetry_class_id. If no telemetry class is found with that id the value NULL is returned.

The get_telemetry_id function returns the telemetry_id for the telemetry with name telemetry_name belonging to telemetry_class_id. If no telemetry with that name is found in the telemetry class a negative number is returned.

The get_telemetry_name returns the name of the corresponding telemetry_id belonging to telemetry_class_id. If no telemetry with that id is found in the telemetry class the value NULL is returned.

The get_telemetry_description can return a description string for the telemetry_id belonging to telemetry_class_id. If no telemetry with that id the value is found NULL is returned.

The get_value function returns the value for the telemetry_id within telemetry_class_id.

Note all known telemetry_classes are not always enabled in all models, i.e. get_telemetry_class_name can return a valid name for some telemetry_class_id but get_telemetry_id on that name may still return an invalid identifier if that telemetry_class is not enabled in the model.

Note that the identifiers may vary between invocations of the model and must not be stored between runs.

The command list-telemetry-classes can be helpful while developing with the telemetry-interface.

typedef int telemetry_class_id_t;

typedef int telemetry_id_t;

SIM_INTERFACE(telemetry) {
        telemetry_class_id_t (*get_telemetry_class_id)(conf_object_t *obj,
                                                       const char *telemetry_class_name);
        const char *(*get_telemetry_class_name)(conf_object_t *obj,
                                                telemetry_class_id_t telemetry_class_id);
        const char *(*get_telemetry_class_description)(conf_object_t *obj,
                                                      telemetry_class_id_t telemetry_class_id);
        telemetry_id_t (*get_telemetry_id)(conf_object_t *obj,
                                           telemetry_class_id_t telemetry_class_id,
                                           const char *telemetry_name);
        const char *(*get_telemetry_name)(conf_object_t *obj,
                                          telemetry_class_id_t telemetry_class_id,
                                          telemetry_id_t telemetry_id);
        const char *(*get_telemetry_description)(conf_object_t *obj,
                                                 telemetry_class_id_t telemetry_class_id,
                                                 telemetry_id_t telemetry_id);
        attr_value_t (*get_value)(conf_object_t *obj,
                                  telemetry_class_id_t telemetry_class_id,
                                  telemetry_id_t telemetry_id);
};

#define TELEMETRY_INTERFACE "telemetry"

Execution Context
Global Context for all methods.

transaction_translator

Description
The transaction_translator interface is implemented by objects which would like to inspect and/or modify transactions before forwarding them to devices or address spaces. In Simics documentation, such objects are usually called translator objects or, simply, translators. In comparison with the simpler translator interface, the transaction_translator interface provides an opportunity to inspect/modify transactions. We recommend using the translator interface when the additional functionality is not needed.

The interface has one method called translate. The arguments passed to this method describe the access and thus allow a translator to perform a proper translation. Here is a short description of the translate method's parameters:
- addr is an address of the access;
- access is a bitmask specifying all requested access types;
- t is a transaction;
- callback is a callback that should be called by the object implementing the interface;
- data should be passed to callback as it is when the callback is invoked by the translator object.
All these arguments are described in detail below.

The transactions done by the translators may be cached by Simics. To ensure efficient flushing of Simics internal caches we recommend that the objects implementing the transaction_translator interface implement also the translation_flush interface. The absence of the translation_flush interface may lead to a substantial decrease of simulation speed.

Whenever a previously returned translation becomes invalid the translator objects are expected to use either SIM_map_target_flush (preferably) or SIM_translation_changed function to ensure that Simics will flush any cached translations. Please refer to the documentation of these functions for the information about how they should be used.

An object implementing the transaction_translator interface should invoke callback passing to it tree arguments: translation, transaction and data. The translation argument describes the translation that was done, i.e. the transaction destination. Please refer to the translation_t documentation for the complete description. The transaction argument is either the original transaction passed to the transaction_translator interface or, if a translator object wants to append atoms to the t transaction, a new transaction created via transaction chaining. The transaction chaining is described in detail in the "Transaction Chaining" chapter of the Model Builder's User Guide. Finally, the data argument is a parameter which should be passed as it is when callback is invoked by the translator object. Simics will report an error if a translator object doesn't invoke callback from the translate method of the transaction_translator.

If it is needed, a translator may route transactions based on the value of certain transaction's atoms. The initiator atom is a good example of such an atom. Please note that not all atoms are suited for routing transactions based on their value. This should be checked in the documentation for the specific atom.

The callback function returns transaction completion status. This status should be usually returned as it is by the translate method. The status value is also needed in the case when a translator object appends atoms via transaction chaining with a non-zero completion atom. In that case the returned status should be used when the SIM_monitor_chained_transaction function is called.

Please note that memory accesses in Simics are not always issued with the transactions of the transaction_t type. For example, memory access can be done with the use of the legacy generic_transaction_t type. One more such example is lookup accesses which are done via the direct_memory_lookup interface. All such accesses are converted, if it is needed, and presented to the translator object via the t parameter.

The access parameter specifies access types in the form of a bitmask. Its value may be of interest if a translation is done differently based on whether it is a read, write or instruction fetch transaction. It can be noted that a transaction itself already contains information whether it is a read, write or an instruction fetch. Usually, the access parameter just reflects that value. However, for lookup accesses done via the direct_memory_lookup interface the access argument may have more bits set. If a translation which are valid for all requested accesses cannot be performed, then a null value should be set in the target of the translation argument passed to callback. In this case, the requestor is expected to repeat the interface call with just a single bit set in the access mask, e.g. Sim_Access_Read.

SIM_INTERFACE(transaction_translator) {
        exception_type_t (*translate)(
                conf_object_t *NOTNULL obj,
                uint64 addr,
                access_t access,
                transaction_t *t,
                exception_type_t (*NOTNULL callback)(
                        translation_t translation,
                        transaction_t *transaction,
                        cbdata_call_t data),
                cbdata_register_t data);
};

#define TRANSACTION_TRANSLATOR_INTERFACE "transaction_translator"

Execution Context
Cell Context for all methods.

translate

Description
The translate interface is implemented by objects that bridge between memory spaces.

Note: There is the translator interface which is a more restricted version of the translate interface and should be used when possible. It allows for better control of memory operations in the Simics core and can therefore allow optimizations in the memory handling.
The return value of the translate method should be a memory space, to which the access is translated at the offset given by the physical address of mem_op. If the return value is NULL, then the access is translated to the default target provided in the configuration (in a memory-space object, this is the 6th index, target, of an entry in the map attribute).

If the translator marks mem_op as ignored before returning NULL (using the function SIM_set_mem_op_ignore), then the return value is ignored, and the transaction is instead terminated in the translator and handled as an ordinary I/O access.

During a translation, the translator may modify the physical address of mem_op, but may have no other side-effects. This is because the caller can choose to cache the translation, in which case the translator is bypassed in subsequent accesses.

The translator can use SIM_mem_op_ensure_future_visibility to inhibit caching. Inhibiting caching can be useful for debugging, but typically comes with a significant performance cost if there is RAM behind the translator.

The addition of the direct_memory interface in Simics 5 results in new typical access patterns for the translate interface. Where previously non-inquiry accesses of any size would result in caching in initiating CPU objects, with the use of direct_memory no such implicit caching ever takes place. Instead, caching requests are separate and fed through the translate method as inquiry accesses of the size that is intended to be cached. This means that for a translate object to work properly in a configuration with CPUs using direct_memory, inquiry accesses must be properly handled. Routing such inquiry accesses to non-memory, terminating them in the translator (which is not an allowed behavior for a translate object), or calling SIM_mem_op_ensure_future_visibility on them results in the requesting CPU not being able to cache the requested memory region.

Using the translate interface in models is error prone and usually not recommended unless all alternatives have been exhausted. Explicit map and demap operations in a memory space avoid the problems with translate interface implementation correctness.

The usage of the translate interface is by necessity less optimal than the usage of the memory-space class as a call out from the simulation kernel should be made. That said when the translate() method is called the transaction may be cached in the STC if the user code does not explicitly block such caching, though depending on a number of factors it may not always be cached. If the translation is cached in the STC then performance is the same as with a memory-space.

There are two reasons to use the translate interface rather than a simple memory-space: 1) To implement something that the memory-space does not support, such as different read and write translations, or manipulation of the transaction, or 2) the translation is accessed infrequently, but updated on most accesses.

Note: Up to and including Simics 4.8, inhibiting caching for the instruction stream did not prevent Simics-provided CPU models from caching. Models therefore had to use flush or SIM_flush_cell_caches on mapping changes to get the desired effect. This is no longer needed since Simics 5.
Up to and including Simics 4.8, CPU models would cache memory for transactions that pass through a translator in blocks that are larger than the size provided in the transaction. This meant that a translator needed to invalidate caches even if a translation changed that had strictly not passed through the interface. For correctness, when any state that had an effect on the translation logic changed, the translator would therefore invalidate all mappings in all initiators, even for mappings that are outside of what has passed through the translator. These types of workarounds are no longer required since Simics 5.

SIM_INTERFACE(translate) {
        conf_object_t *(*translate)(conf_object_t *NOTNULL obj,
                                    generic_transaction_t *NOTNULL mem_op,
                                    map_info_t mapinfo);
};

#define TRANSLATE_INTERFACE "translate"

Execution Context
Cell Context for all methods.

translation_flush

Description
The translation_flush interface is an optional interface which can be implemented by objects implementing the transaction_translator or translator interface. The interface is used by Simics an optimization when Simics flushes its simulation caches. Simics caches translations returned by translators but quite often this cache needs to be invalidated, usually, due to the changes in the memory map of the target system. In such cases Simics may use this interface (if it is available) to do a fine-grain invalidation of its simulation caches.

The translation_flush interface has one method - flush_range - which will be called whenever there is a need to flush simulation caches. The flush_range method has the following parameters:
- base is the start of the region to flush;
- size is the size of the region to flush;
- access is a bitmask which specifies targets for what access types should be flushed;
- default_target is only used for translators implementing the translator interface and has the same as value as the default_target parameter of the translate method of the translator interface. Please see the documentation of the translator for more information about the parameter.

In the flush_range method, the translator object is expected to flush all previously returned destinations of the translation requests that the translator did for the [base, base+size) range. The flushing is done by calling the SIM_map_target_flush function for the destination map target(s). If no translation requests were processed to the range since the last invocation of the flush_range method then no flushing is needed, and the flush_range may immediately return the true value.

Please note that there is no need to call the SIM_map_target_flush function for the translations which were tagged with the Sim_Translation_Dynamic flag. Either, no invalidation is needed for the parts of the range where nothing is mapped.

The return value is used to report whether the invalidation request completed successfully, i.e. whether all calls to the SIM_map_target_flush function succeeded (i.e. returned the true value). If a call to the SIM_map_target_flush fails (i.e. the false value is returned) then the flush_range function is expected to return immediately with the false return value. If, for some reason, the translator cannot invalidate all possible destinations, then it can just immediately return the false value.

If false is returned, then all translations in the simulator will typically be flushed, which could be an expensive operation.

EXAMPLE
Here is pseudo code providing a sample implementation of the flush_range method:
   bool flush_range(obj, base, size, access):
       for (map_target, start, size) in destinations(obj, base, size, access):
           if not SIM_map_target_flush(map_target, start, size, access):
               return False
       return True
   

SIM_INTERFACE(translation_flush) {
        bool (*flush_range)(
                conf_object_t *obj,
                uint64 base,
                uint64 size,
                access_t access,
                const map_target_t *default_target);
};

#define TRANSLATION_FLUSH_INTERFACE "translation_flush"

Execution Context
Cell Context for all methods.

translator

Description
The translator interface is implemented by objects which perform address translations or map memory transactions to devices or address spaces.

The translate method takes a physical address addr and returns a value of the type translation_t which describes the translation for an address range which must include addr. Please refer to the translation_t documentation for a complete description of the return value and more information regarding the implementation of translator objects.

A translator can translate read transactions, write transactions and instruction fetches differently. The access parameter is set to all requested access types in the form of a bitmask. The translator should return null in the target field if a translation valid for all requested accesses cannot be performed; when this happens, the requestor is expected to repeat the interface call with just a single bit set in the access mask, e.g. Sim_Access_Read.

The default_target parameter is a default target, which can be NULL, of the translator mapping (i.e., the target field of the respective memory-space's map entry specifying mapping).

SIM_INTERFACE(translator) {
        translation_t (*translate)(conf_object_t *NOTNULL obj,
                                   physical_address_t addr,
                                   access_t access,
                                   const map_target_t *default_target);
};

#define TRANSLATOR_INTERFACE "translator"

Execution Context
Cell Context for all methods.

usb

Description
The usb_interface_t interface is implemented by all USB hosts. USB devices use the interface to communicate with the USB host. The interface is Simics internal, and may be changed in future versions of Simics. It should not be used by user-defined classes.

The connect_device() function is called by the USB device to connect to the USB. The host returns the physical port to which the device is connected, or -1 on connection error (for example, if all ports are occupied). Parameter to connect_device() is the maximum data speed for the USB device.

The disconnect_device() function is called by the USB device when it wants to disconnect from the USB. The host returns 0 on success.

The complete_transfer() function is called by a USB device when it has completed a transfer. Refer to the usb_device_t interface documentation to know more about how a transfer is sent to the USB device.

SIM_INTERFACE(usb) {
        int (*connect_device)(conf_object_t *bus_obj,
                              conf_object_t *NOTNULL dev_obj,
                              usb_speed_t speed);
        int (*disconnect_device)(conf_object_t *bus_obj,
                                 conf_object_t *NOTNULL dev_obj);
        void (*complete_transfer)(conf_object_t *bus_obj,
                                  conf_object_t *NOTNULL dev_obj,
                                  usb_transfer_t *NOTNULL transfer);
};

#define USB_INTERFACE "usb"

Execution Context
connect_deviceGlobal Context
disconnect_device Global Context
complete_transferCell Context

usb_device

Description
The usb_device_interface_t interface is implemented by all USB devices. It is used by the USB host to communicate with the USB devices. The interface is Simics internal, and may be changed in future versions of Simics. It should not be used by user-defined classes.

The submit_transfer() function is used by the USB host controller to send a new transfer to a USB device. Transfers are the basic means of communication between the USB host controller and the USB devices. A transfer contains all information needed to handle control, bulk, interrupt, and isochronous transfers. A transfer to a USB device simply moves the control from the USB host to the USB device. The USB device can then decide when to send back any useful data to the USB host. The USB device receives a pointer to the transfer to handle. It can either handle the transfer immediately or send the transfer back later using the complete_transfer() function in the usb_interface_t interface, which is implemented by the USB host.

The USB device must return USB_Transfer_Completed when it handles the transfer immediately, i.e., it has filled the required fields in the transfer structure. The USB device must return USB_Transfer_Not_Ready for unfinished transfers, i.e., the USB device does not have any interesting data to deliver at this point. The isochronous and interrupt transfers contain a field indicating how long time the USB host expects the USB device to wait before returning the transfer. Note that it is just an indication on how often this transfer is scheduled in the periodic list and USB devices can complete the transfers at any time. A value of 0 means that the USB host does have any expectations about the return time.

The abort_transfer() function tells the USB device to abort a transfer previously issued by the USB host. The USB device should not call the complete_transfer() function for a request that has been aborted.

The reset() function is used by the USB host to reset the USB device.

The USB host expects the device to return the same transfer pointer it received when completing, i.e., the transfer pointer is used to identify uniquely a transfer.

SIM_INTERFACE(usb_device) {
        usb_transfer_completion_t (*submit_transfer)(conf_object_t *dev_obj,
                                                     usb_transfer_t *transfer);
        void (*abort_transfer)(conf_object_t *dev_obj,
                               usb_transfer_t *transfer);
        void (*reset)(conf_object_t *dev_obj);
};

#define USB_DEVICE_INTERFACE "usb_device"

Execution Context
Cell Context for all methods.

vectored_interrupt

Description
This interface is typically implemented by processors with interrupts that have vectors and priorities supplied by their sources.

The set_level() method sets the interrupt level on the target object; zero indicates that no interrupt is requested. The interrupt source should implement the vectored_interrupt_source interface.

SIM_INTERFACE(vectored_interrupt) {
        void (*set_level)(conf_object_t *NOTNULL obj,
                          conf_object_t *NOTNULL source, int level);
};
#define VECTORED_INTERRUPT_INTERFACE "vectored_interrupt"

Execution Context
Cell Context for all methods.

vectored_interrupt_source

Description
This interface is implemented by interrupt sources that use the vectored_interrupt interface.

The acknowledge() method is called to acknowledge a requested interrupt of the given level on the interrupt target. It should return an interrupt vector number, -1 if no vector is supplied, or -2 if the object does not accept the acknowledgement.

SIM_INTERFACE(vectored_interrupt_source) {
        int (*acknowledge)(conf_object_t *NOTNULL obj,
                           conf_object_t *NOTNULL target, int level);
};
#define VECTORED_INTERRUPT_SOURCE_INTERFACE "vectored_interrupt_source"

Execution Context
Cell Context for all methods.

virtiofs_fuse

Description
This interface is intended for implementing a FUSE request handler.

handle_request This method takes a FUSE request in req . It then returns a buffer_t object with the FUSE response. The caller of handle_request must free the data field in the returned buffer_t object.

SIM_INTERFACE(virtiofs_fuse)
{
        buffer_t (*handle_request)(conf_object_t * obj, bytes_t req);
};

#define VIRTIOFS_FUSE_INTERFACE "virtiofs_fuse"

Execution Context
Cell Context for all methods.

vmp

Description
The vmp interface is used to control enabling of VMP and VMP features from a user perspective. Models should use x86_vmp_control for potential blocking of VMP.

This is an internal interface between VMP and the Simics Base package, and it may change at any time without notice.

SIM_INTERFACE(vmp) {
        bool (*class_has_support)(conf_object_t *obj);
        bool (*host_support)(conf_object_t *obj);
        bool (*compatible_config)(conf_object_t *obj);
        bool (*enable)(conf_object_t *obj);
        void (*disable)(conf_object_t *obj);
        bool (*enabled)(conf_object_t *obj);
        void (*set_threshold)(conf_object_t *obj, int threshold);
        bool (*get_feature)(conf_object_t *obj, vmp_feature_t feature);
        bool (*set_feature)(conf_object_t *obj, vmp_feature_t feature, bool val);
        uint64 (*get_info)(conf_object_t *obj, vmp_info_t info);
};
#define VMP_INTERFACE "vmp"

Execution Context
Cell Context for all methods.

vmx_instrumentation_subscribe

Description
This x86 specific interface allows a user to keept track of VMX mode switches in the processor.

The register_vmx_mode_leave_cb registers a callback of type vmx_mode_switch_cb_t that will be called before the processor leaves a particular VMX mode.

The register_vmx_mode_enter_cb registers a callback of type vmx_mode_switch_cb_t that will be called after the processor enters a particular VMX mode.

The callback in both cases looks like this: This callback type is used by the vmx_instrumentation_subscribe to implements VMX mode switch instrumentation.

typedef void (*vmx_mode_switch_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        vmx_mode_t mode,
        physical_address_t vmcs_address,
        lang_void *user_data);

The obj argument is the user object that registered the callback, or NULL if no such object exists.

The cpu argument is the processor that switches VMX mode.

The mode that will be left or entered is passed in the mode argument in the callback.

The different VMX modes are defined in the following type: This enum is used to distinguish VMX modes. It is used by the vmx_mode_switch_cb_t.

typedef enum {
        Vmx_Off = 0,
        Vmx_Root = 1,
        Vmx_Non_Root = 2
} vmx_mode_t;

The vmcs_address argument specifies the Virtual Machine Control Structure address that is currently being used. If not available, it will be passed as (physical_address_t)(-1).

When leaving a mode and then entering another mode, the mode can actually be reported as to be the same in certain situations. This is not a bug, it is a consequent of how Simics is implemented. It would require a lot of extra code to filter those out.

The user_data argument is the callback user data, passed to the register methods.

SIM_INTERFACE(vmx_instrumentation_subscribe) {
        cpu_cb_handle_t *(*register_vmx_mode_leave_cb)(
                conf_object_t *cpu,
                conf_object_t *connection,
                vmx_mode_switch_cb_t cb,
                lang_void *user_data);
        cpu_cb_handle_t *(*register_vmx_mode_enter_cb)(
                conf_object_t *cpu,
                conf_object_t *connection,
                vmx_mode_switch_cb_t cb,
                lang_void *user_data);
};

#define VMX_INSTRUMENTATION_SUBSCRIBE_INTERFACE \
        "vmx_instrumentation_subscribe"

Execution Context
Global Context for all methods.

x86

Description
The x86 interface exports functionality used by several other objects to interact with the processor. The set_pin_status function is used to set/clear certain processor pins.

typedef enum {
        Pin_Init,
        Pin_Smi,
        Pin_Nmi,
        Pin_Ignne,
        Pin_Mcerr,
        Pin_Cmci
        /* Do not add new pins. Instead, define individual signal ports */
} x86_pin_t;

The start_up function is used by the local APIC to bring the processor obj out of the waiting for start-up IPI state, with a start address of start_address.

The interrupt function tells the CPU that an interrupt is waiting. The interrupt vector number is given by the ack callback function. It is not allowed to call the ack callback during the interrupt call itself. The data object should implement the interrupt_cpu interface. Note that the interrupt_cpu interface defines the ack function, which should be the same as the ack argument. It is recommended that new implementations does not use rely on the ack argument, but rather looks up the callback through the interrupt_cpu interface from the object given by the data argument. The interrupt function returns 1 if the interrupt is accepted, and 0 if it is not accepted because there is already an interrupt queued up to be processed. If 0 is returned, the caller should retry the call after one step. It should wait one step since the handling of an interrupt takes one step.

If a checkpoint was taken when an interrupt was waiting, the acknowledge callback function can be recovered by looking up the interrupt_cpu interface at the APIC object given in the data parameter.

If the interrupt was cancelled before it was acknowledged, the uninterrupt function is used. It is also called by the acknowledge callback. Thus, each invocation of interrupt is followed by exactly one call to uninterrupt at all times. The ack parameter is unused and should be ignored. When the processor is reset, it forgets a waiting interrupt so it is not necessary to call uninterrupt during a reset.

The functions in the interrupt_ack interface provides almost the same functionality as the interrupt and uninterrupt functions in this interface. The only difference is that the interrupt function in this interface returns 0 when the interrupt cannot be handled which allows the device to retry later.

The has_pending_interrupt and has_waiting_interrupt calls should return information about interrupts in progress. An interrupt is said to be pending if it is acked by the processor and will be taken before execution of the next instruction. An interrupt is waiting if the logical interrupt line is high, but the interrupt has not yet been acked. These functions are used for sanity checks by the APIC. The APIC should keep track of posted interrupts by itself. These functions return 1 if an interrupt is pending/waiting, and 0 otherwise.

The logical_to_linear function returns the translated linear address from the given logical address and segment register number. The function uses the current content of control registers and segment registers to calculate the linear address. The tagged return value is marked invalid if no valid translation exists, for example if the passed logical address is beyond the segment limit of the passed segment or if it is non-canonical. The encoding of segment is 0 for ES, 1 for CS, 2 for SS, 3 for DS, 4 for FS, and 5 for GS.

The linear_to_physical function returns the physical address corresponding to the given linear address. The function uses the current content of control registers, TLBs and possibly page tables to calculate the physical address. A return value of -1 signals that no valid mapping exists.

enter_acpi_c2_state is called from the chipset power module to request the CPU to enter an energy-saving state.

SIM_INTERFACE(x86) {
        void (*set_pin_status)(conf_object_t *obj,
                               x86_pin_t pin, int status);
        void (*start_up)(conf_object_t *obj, uint32 start_address);
        int  (*interrupt)(conf_object_t *obj,
                          int (*ack)(conf_object_t *obj),
                          conf_object_t *data);
        void (*uninterrupt)(conf_object_t *obj,
                            int (*ack)(conf_object_t *obj));
        int  (*has_pending_interrupt)(conf_object_t *obj);
        int  (*has_waiting_interrupt)(conf_object_t *obj);
        tagged_linear_address_t (*logical_to_linear)(conf_object_t *obj,
                                                     int segment,
                                                     logical_address_t addr);
        physical_address_t (*linear_to_physical)(conf_object_t *obj,
                                                 data_or_instr_t d_or_i,
                                                 linear_address_t addr);
        void (*enter_acpi_c2_state)(conf_object_t *obj);
};

#define X86_INTERFACE "x86"

Execution Context
Cell Context for all methods.

x86_access_type

Description
This interface is used to query information about the x86_access_type_t enum. The get_enum_name method returns the C enum name for the access type. get_short_name returns a corresponding short name. More than one access type may have the same short name. The get_description returns a longer description of the access type. The implicit function returns true if the access type is considered implicit or false if it is considered explicit. This information is used by the cpu_instrumentation_subscribe interface to separate accesses in the two different categories.

SIM_INTERFACE(x86_access_type) {
        const char *(*get_enum_name)(conf_object_t *obj, x86_access_type_t at);
        const char *(*get_short_name)(conf_object_t *obj, x86_access_type_t at);
        const char *(*get_description)(conf_object_t *obj, x86_access_type_t at);
        bool (*implicit)(conf_object_t *obj, x86_access_type_t at);
};

#define X86_ACCESS_TYPE_INTERFACE "x86_access_type"

Execution Context
Cell Context for all methods.

x86_address_query

Description
The x86_address_query interface is used to query information about an address for the x86 architecture and should be used from a cpu_memory_address_cb_t callback.

SIM_INTERFACE(x86_address_query) {
        x86_seg_t (*segment)(
                conf_object_t *cpu, address_handle_t *handle);
        page_crossing_info_t (*get_page_crossing_info)(
                conf_object_t *cpu, address_handle_t *handle);
};
#define X86_ADDRESS_QUERY_INTERFACE "x86_address_query"        

The segment is used to get the segment register used in the address calculation. The handle is the address handle passed to cpu_memory_address_cb_t.

If the access crosses a page boundary the access will be split into two calls. The get_page_crossing_info can be used to distinguish the different cases from each other. The value returned is of type page_crossing_info_t and is one of: Sim_Page_Crossing_None (no crossing access), Sim_Page_Crossing_First (first part of a crossing access), Sim_Page_Crossing_Second (second part of a crossing access).

Execution Context
Cell Context for all methods, but must be called from a callback receiving a handle of type address_handle_t.

x86_cache_flush

Description
The x86 cache flush interface is implemented by objects which need to do some special handling when the cpu flushes the cache.

The flush method is invoked when the cpu executes an invd or a wbinvd instruction. The writeback parameter is set for the later instruction.

SIM_INTERFACE(x86_cache_flush) {
        void (*flush)(conf_object_t *obj, conf_object_t *cpu, bool writeback);
};
#define X86_CACHE_FLUSH_INTERFACE "x86_cache_flush"

Execution Context
Cell Context for all methods.

x86_cpuid

Description
SIM_INTERFACE(x86_cpuid) {
	cpuid_ret_t (*cpuid)(conf_object_t *obj, conf_object_t *cpu,
                             uint32 in_eax, uint32 in_ebx, uint32 in_ecx,
                             uint32 in_edx);
};
#define X86_CPUID_INTERFACE "x86_cpuid"

The CPUID interface makes it possible to customize responses to CPUID requests. The cpuid method should set taken to nonzero if it managed to handle the request, zero otherwise. When taken is non-zero, then the returned values in out_a, out_b, out_c, and out_d will be written to the first four general purpose registers. Assigning external handlers to the leaf range reserved for MAGIC instruction implementation has no effect, because the MAGIC implementation always takes priority.

Execution Context
Cell Context for all methods.

x86_cpuid_query

Description
This interface is implemented by CPUs and can be used to query the values that would be returned by the CPUID instruction. The interface calculates the return value both from built in default values and from any handlers that would be installed using the x86_cpuid interface.

This is a preliminary interface. Based on feedback, this interface can and will be changed without regard for the usual ABI compatibility rules.

SIM_INTERFACE(x86_cpuid_query) {
        cpuid_value_t (*cpuid_query)(conf_object_t *obj, uint32 leaf,
                                     uint32 subleaf);
};
#define X86_CPUID_QUERY_INTERFACE "x86_cpuid_query"

Execution Context
Cell Context for all methods.

x86_cstate

Description
The methods in this interface can be used to read or change the current power state the CPU is in. A state value of 0 corresponds to C0, a value of 1 corresponds to C1, etc. HLT will be reported as state 1, substate 0. MWAIT will reported based upon the eax hint, decoded as state = (eax[7:4] + 1) mod 16, substate = eax[3:0].

set_cstate will perform side-effects such as putting the processor to sleep or waking it up, and call the registered cstate listeners.

typedef struct {
        uint32 state;
        uint32 sub_state;
} x86_cstate_t;

SIM_INTERFACE(x86_cstate) {
        x86_cstate_t (*get_cstate)(conf_object_t *cpu_obj);
        void (*set_cstate)(conf_object_t *cpu_obj,
                           uint32 state, uint32 sub_state);
};

#define X86_CSTATE_INTERFACE "x86_cstate"

Execution Context
Cell Context for all methods.

x86_cstate_notification

Description
Objects registered in the CPU's cstate_listeners attribute will be called via the notification method whenever the CPU's cstate changes. Only changes caused by instruction execution or calls to the x86_cstate.set_cstate function will trigger a notification, not attribute accesses. See the x86_cstate interface for how the C-state is encoded in the parameters.

SIM_INTERFACE(x86_cstate_notification) {
        void (*notification)(conf_object_t *listener, conf_object_t *cpu,
                             uint32 state, uint32 sub_state);
};

#define X86_CSTATE_NOTIFICATION_INTERFACE "x86_cstate_notification"

Execution Context
Cell Context.

x86_ept

Description
The interface provides insight into the Extended Page Table (EPT) address translation performed by target processors for virtual machine operations. It takes a result of the first level translation (the classical paging), called a guest physical address, and returns matching host physical address.

The guest_physical_to_physical function translates a guest physical address to a host physical address. The cpu_mode argument sets the processor mode for the lookup. Access type is defined by access. The function returns a physical_block_t struct with valid bit and the address. The host physical address is valid when the valid flag is not 0. The function also returns block_start and block_end. The start and end of a block has the same linear mapping as the translated address. The range is inclusive, so block_end should be the address of the last byte of the block. This information can be used to figure out how often the function needs to be called for traversing larger address ranges.

If the chosen processor's current mode does not use EPT translation, the function should use the identity mapping between guest and host physical addresses. An example of such situation would be an x86 processor outside of VMX non-root mode or with EPT controls disabled.

To check if the processor's current VMCS state has EPT enabled, is_ept_active function should be used.

SIM_INTERFACE(x86_ept) {
        physical_block_t (*guest_physical_to_physical)(
                conf_object_t *obj,
                generic_address_t address,
                x86_processor_mode_t cpu_mode,
                access_t access);
        bool (*is_ept_active)(conf_object_t* obj);
};

#define X86_EPT_INTERFACE "x86_ept"

Execution Context
Cell Context for all methods.

x86_exception

Description
The methods in this interface is used to raise exceptions from the instrumentation replace or user decoder functionality (it is illegal to invoke these methods from any other context). The methods perform longjmps and do not return.

This interface is internal and may change without notice.

SIM_INTERFACE(x86_exception) {
        void (*DE_fault)(conf_object_t *cpu);

        void (*BR_fault)(conf_object_t *cpu);
        void (*UD_fault)(conf_object_t *cpu);
        void (*NM_fault)(conf_object_t *cpu);
        void (*DF_abort)(conf_object_t *cpu, const char *desc);

        void (*TS_fault)(conf_object_t *cpu, uint16 sel);
        void (*NP_fault)(conf_object_t *cpu, uint16 sel_vec, bool is_vec);

        void (*SS_fault)(conf_object_t *cpu, uint16 sel);
        void (*GP_fault)(conf_object_t *cpu, uint16 sel_vec, bool is_vec,
                         const char *desc);
        void (*PF_fault)(conf_object_t *cpu, linear_address_t laddr,
                         uint32 ecode);
        void (*MF_fault)(conf_object_t *cpu);
        void (*AC_fault)(conf_object_t *cpu);
        void (*XM_fault)(conf_object_t *cpu);
};
#define X86_EXCEPTION_INTERFACE "x86_exception"

Execution Context
The methods in this interface may only be called from user decoder service routines.

x86_exception_query

Description
The x86_exception_query interface is used to query information about an exception for the x86 architecture and should be used from a cpu_exception_cb_t callback.

SIM_INTERFACE(x86_exception_query) {
        uint8 (*vector)(
                conf_object_t *cpu, exception_handle_t *handle);
        x86_exception_source_t (*source)(
                conf_object_t *cpu, exception_handle_t *handle);
        uint32 (*error_code)(
                conf_object_t *cpu, exception_handle_t *handle);
};
#define X86_EXCEPTION_QUERY_INTERFACE "x86_exception_query"        

The vector method is used to get the exception vector. The source method is used to get the source of the exception and the error_code method is used to get the error code of the exception.

Execution Context
Cell Context for all methods, but must be called from a callback receiving a handle of type exception_handle_t.

x86_execution_mode

Description
The interface provides insight into the processor execution mode.

The get_execution_mode returns the current processor execution mode. Note that several fields in the returned x86_execution_mode_t structure can be non-zero simultaneously.

typedef struct x86_execution_mode {
        uint64 ac:1,
               seam:1,
               sgx:1,
               smm:1,
               vmx_root:1,
               vmx_non_root:1;
} x86_execution_mode_t;

SIM_INTERFACE(x86_execution_mode) {
        x86_execution_mode_t (*get_execution_mode)(conf_object_t *obj);
};

#define X86_EXECUTION_MODE_INTERFACE "x86_execution_mode"

Execution Context
Cell Context for all methods.

x86_instruction_query

Description
The x86_instruction_query interface is used to query additional information about an instruction for the x86 architecture and is a complement to the cpu_instruction_query interface.

SIM_INTERFACE(x86_instruction_query) {
        linear_address_t (*linear_address)(conf_object_t *cpu,
                                           instruction_handle_t *handle);
};

#define X86_INSTRUCTION_QUERY_INTERFACE "x86_instruction_query"

The linear_address is used to get the linear address of the instruction.

Execution Context
Threaded Context for all methods, but must be called from a callback receiving a handle of type instruction_handle_t.

x86_instrumentation_subscribe

Description
The x86_instrumentation_subscribe interface is an x86 specific complement to the cpu_instrumentation_subscribe interface. It is implemented by processor objects that support instrumentation. It has the same requirements as the cpu_instrumentation_subscribe interface.

SIM_INTERFACE(x86_instrumentation_subscribe) {
        cpu_cb_handle_t *(*register_mode_switch_cb)(
                conf_object_t *cpu, conf_object_t *connection,
                x86_mode_switch_cb_t cb,
                lang_void *user_data);
        cpu_cb_handle_t *(*register_illegal_instruction_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_instruction_decoder_cb_t cb,
                cpu_instruction_disassemble_cb_t disass_cb,
                lang_void *data);
};
#define X86_INSTRUMENTATION_SUBSCRIBE_INTERFACE \
        "x86_instrumentation_subscribe"

The register_mode_switch_cb method is used to register a callback that is called whenever the processor cpu changes execution mode. The connection argument is the user object that registers the callback. This object will be passed to the callback when it is called. cb is the callback and user_data is user data for the callback. The signature of the callback looks like this:

typedef void (*x86_mode_switch_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        x86_detailed_exec_mode_t mode,
        lang_void *user_data);

The obj is the connection object that registered the callback. new_mode argument contains the new mode. The possible modes available are captured in the x86_detailed_exec_mode_t type:

typedef enum {
        X86_Detailed_Exec_Mode_Real_16,
        X86_Detailed_Exec_Mode_Real_32,
        X86_Detailed_Exec_Mode_V86,
        X86_Detailed_Exec_Mode_Protected_16,
        X86_Detailed_Exec_Mode_Protected_32,
        X86_Detailed_Exec_Mode_Protected_64,
        X86_Detailed_Exec_Mode_Compatibility_16,
        X86_Detailed_Exec_Mode_Compatibility_32,
} x86_detailed_exec_mode_t;

The user_data is the user data associated with the callback.

register_illegal_instruction_cb lets a user to implement new instructions. The cb argument is a callback function that will be called every time Simics does not decode an instruction. Allows new x86 instructions to be implemented which otherwise cause illegal instruction exception. Compared to register_instruction_decoder_cb method of cpu_instrumentation_subscribe interface this interface cannot change any instruction that correctly decodes according to the existing instruction set architecture. From this callback the user can accept the instruction or deny it. In most cases this only happens once per instruction address since Simics usually caches decoding results in the internal instruction cache. If the cache is flushed the callback may be called again. This instrumentation feature (if used alone) does not prevent VMP execution since illegal instructions cause exit while running inside VMP mode.

The callback signature looks like this:

typedef int (*cpu_instruction_decoder_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        decoder_handle_t *decoder_handle,
        instruction_handle_t *iq_handle,
        lang_void *user_data);

The instruction bytes are read by using the get_instruction_bytes method of the cpu_instruction_query interface together with the iq_handle. The returned value is of a cpu_bytes_t type. To access the bytes use the data and the size members in the returned value.

If the decoder requires more bytes (i.e., because the new instruction is longer), a negative integer value should be returned by the cb function, indicating the number of bytes needed. For example, if the available bytes are 3 but the decoder need at least 4 bytes, -4 should be returned. The callback will then be called again with more available bytes (this can be repeated if the new instruction requires even more bytes at this point). Note that requesting more data than actual needed can cause spurious page faults if the data crosses a page boundary.

If the instruction is accepted by the callback a positive integer number should be returned corresponding to the length of the instruction. In this case the register_emulation_cb method of the cpu_instruction_decoder interface should be called to set the actual (user) function that Simics will call each time the instruction is executed.

If the cb callback should ignore the instruction the number 0 should be returned. This means that any other registered decoder will have a chance to decode the instruction. If no decoder accepts it, Simics will generate illegal instruction exception.

The register_emulation_cb method also needs the decoder_handle which is available in the dedoder callback. For more information, see the documentation of the cpu_instruction_decoder interface.

A disass_cb argument should also be passed to the register_illegal_instruction_cb method. This function is called every time Simics wants to disassemble an instruction. For every accepted instruction a corresponding disassembly string should be returned by this function. It has the following signature:

typedef tuple_int_string_t (*cpu_instruction_disassemble_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        generic_address_t addr,
        cpu_bytes_t bytes);

obj is the object registering the register_illegal_instruction_cb and cpu is the processor disassembling the instruction. addr is the address of the instruction in a generic form. This means that it is typically a physical address or a logical address depending on the context of the disassembling. The address can be used for offset calculations, i.e., displaying an absolute address instead of a relative one, for example in a branch instruction. The bytes argument should be used to read instruction bytes. The return value is of type tuple_int_string_t and should be filled with the instruction length and an allocated (e.g., malloc) string representing the disassembly of the instruction. The ownership of the string is transferred to the calling environment which will free it when it is no longer needed.

If too few bytes are passed for the instruction to be disassembled a negative value should be returned for the length indicating the needed bytes. The disass_cb is then called again with more bytes. If the instruction is rejected a length of 0 should be returned and the string should be set to NULL.

To remove the callback used one of the methods remove_callback or remove_connection_callbacks in the cpu_instrumentation_subscribe interface.

The callback can also be enabled and disabled with the corresponding methods in the cpu_instrumentation_subscribe interface.

Execution Context
Global Context for all methods.

x86_instrumentation_subscribe_v2

Description
The x86_instrumentation_subscribe_v2 interface is an x86 specific complement to the cpu_instrumentation_subscribe interface. It is implemented by x86 processor objects that support instrumentation. It works in the same way as the cpu_instrumentation_subscribe interface, and the methods remove/enabled/disable_callback and remove/enabled/disable_connection_callbacks in that interface should be used to operate on callbacks in this interface as well, using the cpu_cb_handle_t handle.

The v2 variant fixes some problems with the x86_instrumentation_subscribe. In that interface, the register_mode_switch_cb method was invoked when the new mode had already been set up. This means that if you need to do some bookkeeping when leaving a mode, that mode had already been switched out in the callback. For instance, descriptor registers has already been changed.

This interface adds two methods to handle this, register_mode_leave_cb and register_mode_enter_cb. The leave variant is called when the processor still is located in the previous mode, but about to enter a new mode, and the enter variant is called when the processor has switched to the new mode (corresponds to the register_mode_switch_cb in the old x86_instrumentation_subscribe interface).

The register_illegal_instruction_cb works as in the x86_instrumentation_subscribe interface.

SIM_INTERFACE(x86_instrumentation_subscribe_v2) {
        cpu_cb_handle_t *(*register_mode_enter_cb)(
                conf_object_t *cpu, conf_object_t *connection,
                x86_mode_switch_cb_t cb,
                lang_void *user_data);
        cpu_cb_handle_t *(*register_mode_leave_cb)(
                conf_object_t *cpu, conf_object_t *connection,
                x86_mode_switch_cb_t cb,
                lang_void *user_data);
        cpu_cb_handle_t *(*register_illegal_instruction_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_instruction_decoder_cb_t cb,
                cpu_instruction_disassemble_cb_t disass_cb,
                lang_void *data);
};

#define X86_INSTRUMENTATION_SUBSCRIBE_V2_INTERFACE \
        "x86_instrumentation_subscribe_v2"

Execution Context
Global Context for all methods.

x86_memory_access

Description
The x86_memory_access interface is used to access memory from user decoder service routines. If an exception condition occurs, a longjmp is taken. The interface methods may only be invoked from user decoder service routines.

This interface is internal and may change without notice.

SIM_INTERFACE(x86_memory_access) {
        uint64 (*read_logical)(
                conf_object_t *cpu,
                logical_address_t offs,
                x86_seg_t seg,
                unsigned len,
                x86_processor_mode_t mode,
                x86_access_type_t access_type);
#if !defined(PYWRAP)
        void (*read_logical_buf)(
                conf_object_t *cpu, 
                logical_address_t offs,
                x86_seg_t seg,
                unsigned len,
                void *p,
                x86_processor_mode_t mode,
                x86_access_type_t access_type,
                x86_alignment_t alignment);
#endif
        void (*write_logical)(
                conf_object_t *cpu,
                logical_address_t offs,
                x86_seg_t seg,
                unsigned len,
                uint64 val,
                x86_processor_mode_t mode,
                x86_access_type_t access_type);
#if !defined(PYWRAP)
        void (*write_logical_buf)(
                conf_object_t *cpu,
                logical_address_t offs,
                x86_seg_t seg,
                unsigned len,
                const void *p,
                x86_processor_mode_t mode,
                x86_access_type_t access_type,
                x86_alignment_t alignment);
#endif
};
#define X86_MEMORY_ACCESS_INTERFACE "x86_memory_access"

Execution Context
The methods in this interface may only be called from user decoder service routines.

x86_memory_operation

Description
The x86_memory_operation interface is used to access memory from a user instruction. See the cpu_instrumentation_subscribe and cpu_instruction_decoder for more information. It is designed to be more efficient than the x86_memory_access. If an exception condition occurs, a longjmp is taken. The interface methods may only be invoked from user instruction.

SIM_INTERFACE(x86_memory_operation) {
        uint64 (*read_logical)(
                conf_object_t *cpu,
                x86_seg_t seg,
                logical_address_t offs,
                unsigned size,
                x86_processor_mode_t mode,
                x86_access_type_t access_type);
#if !defined(PYWRAP)
        void (*read_logical_buf)(
                conf_object_t *cpu,
                uint8 *dst,
                x86_seg_t seg,
                logical_address_t offs,
                unsigned size,
                x86_processor_mode_t mode,
                x86_access_type_t access_type);
#endif
        void (*write_logical)(
                conf_object_t *cpu,
                uint64 val,
                x86_seg_t seg,
                logical_address_t offs,
                unsigned size,
                x86_processor_mode_t mode,
                x86_access_type_t access_type);
#if !defined(PYWRAP)
        void (*write_logical_buf)(
                conf_object_t *cpu,
                const uint8 *src,
                x86_seg_t seg,
                logical_address_t offs,
                unsigned size,
                x86_processor_mode_t mode,
                x86_access_type_t access_type);
#endif
        x86_read_physical_ret_t (*read_physical)(
                conf_object_t *cpu,
                physical_address_t address,
                unsigned size,
                x86_access_type_t access_type);
#if !defined(PYWRAP)
        exception_type_t (*read_physical_buf)(
                conf_object_t *cpu,
                uint8 *dst,
                physical_address_t address,
                unsigned size,
                x86_access_type_t access_type);
#endif
        exception_type_t (*write_physical)(
                conf_object_t *cpu,
                uint64 val,
                physical_address_t address,
                unsigned size,
                x86_access_type_t access_type);
#if !defined(PYWRAP)  
        exception_type_t (*write_physical_buf)(
                conf_object_t *cpu,
                const uint8 *src,
                physical_address_t address,
                unsigned size,
                x86_access_type_t access_type);
#endif
};

#define X86_MEMORY_OPERATION_INTERFACE "x86_memory_operation"

Execution Context
Cell Context for all methods, but must be called from an invoke function set by the instrumentation_replace interface.

x86_memory_query

Description
The x86_memory_query interface is used to query additional information about an instruction for the x86 architecture and is a complement to the cpu_memory_query interface.

SIM_INTERFACE(x86_memory_query) {
        linear_address_t (*linear_address)(conf_object_t *cpu,
                                           memory_handle_t *handle);
        x86_seg_t (*segment)(conf_object_t *cpu, memory_handle_t *handle);
        x86_access_type_t (*access_type)(conf_object_t *obj,
                                         memory_handle_t *handle);
        x86_memory_type_t (*memory_type)(conf_object_t *obj,
                                         memory_handle_t *handle);
};

#define X86_MEMORY_QUERY_INTERFACE "x86_memory_query"        

The linear_address is used to get the linear address of the access.

The segment function is used to get the segment register used in the access.

The access_type returns the x86_access_type_t of the access and the memory_type returns the x86_memory_type_t of the access.

Execution Context
Cell Context for all methods, but must be called from a callback receiving a handle of type memory_handle_t.

x86_msr

Description
SIM_INTERFACE(x86_msr) {
        void (*register_handlers)(
                conf_object_t *cpu,
                int64 number,
                x86_msr_getter_func_t getter,
                lang_void *getter_data,
                x86_msr_setter_func_t setter,
                lang_void *setter_data,
                const char *name);
        void (*unregister_handlers)(
                conf_object_t *cpu,
                int64 number);
        x86_msr_getter_ret_t (*get)(
                conf_object_t *cpu,
                int64 number,
                x86_msr_access_type_t type);
        x86_msr_ret_t (*set)(
                conf_object_t *cpu,
                int64 number,
                uint64 value,
                x86_msr_access_type_t type);
        const char *(*get_name)(
                conf_object_t *cpu,
                int64 number);
        int64 (*get_number)(
                conf_object_t *cpu,
                const char *name);
        attr_value_t (*get_all_valid_numbers)(
                conf_object_t *cpu);
};
#define X86_MSR_INTERFACE "x86_msr"

The register_handlers function will register get and set functions that will be called every time a read or write access is made to the MSR with number msr.

typedef struct {
        x86_msr_ret_t status;
        uint64 value;
} x86_msr_getter_ret_t;

typedef enum {
        Sim_X86_Msr_Ok = Sim_Gen_Spr_Ok,        /* Access was OK */
        Sim_X86_Msr_GP_Fault,                   /* Raise #GP fault */
        Sim_X86_Msr_Not_Handled                 /* Pass on to next handler */
} x86_msr_ret_t;

typedef x86_msr_getter_ret_t (*x86_msr_getter_func_t)(
        conf_object_t *cpu,
        int64 number,
        x86_msr_access_type_t type,
        lang_void *user_data);

typedef x86_msr_ret_t (*x86_msr_setter_func_t)(
        conf_object_t *cpu,
        int64 spr_number,
        uint64 value,
        x86_msr_access_type_t type,
        lang_void *user_data);

The type parameter in the get and set functions is one of the following, depending on where from the access originated:

typedef enum {
        /* Access from a rdmsr/wrmsr instruction */
        Sim_X86_Msr_Instruction_Access = Sim_Gen_Spr_Instruction_Access,

        /* Access through attribute */
        Sim_X86_Msr_Attribute_Access = Sim_Gen_Spr_Attribute_Access,

        /* Access through int_register interface */
        Sim_X86_Msr_Int_Register_Access = Sim_Gen_Spr_Int_Register_Access,

        /* Access during VMX entry/exit */
        Sim_X86_Msr_VMX_Access,

        /* Architectural access without side effects within the CPU model, only
           reads or writes the register value. However, if it is sent to the
           platform as a non-inquiry access, that may cause side effects. */
        Sim_X86_Msr_Architectural_Access
} x86_msr_access_type_t;

The getter function returns the status just like the setter together with the read MSR value. A getter or setter may return the Sim_X86_MSR_Not_Handled return code, in which case the access will pass through to the earlier registered handler (or the default handler if there is no earlier registered handler).

The function unregister_handlers will remove any non-default handlers for a particular MSR.

The get and set functions get and set MSRs, using both model default MSR handlers and handlers installed through this interface.

The function get_name takes number as parameter and returns the name of the MSR.

The function get_number takes the name and returns the MSR number.

The function get_all_valid_numbers returns a list of integers corresponding to all the valid MSRs, including both model default MSRs and MSRs installed through this interface.

Execution Context
Cell Context for all methods.

x86_pkg_cstate

Description
The methods in this interface can be used to read or change the current power state the CPU is in. A state value of 0 corresponds to C0, a value of 1 corresponds to C1, etc. HLT will be reported as state 1, substate 0. MWAIT will reported based upon the eax hint, decoded as state = (eax[7:4] + 1) mod 16, substate = eax[3:0].

pkg_cstate_update will perform side-effects such as putting the processor to sleep or waking it up, and call the cstate notification listeners.

SIM_INTERFACE(x86_pkg_cstate) {
        x86_cstate_t (*get_pkg_cstate)(conf_object_t *cpu_obj);
        void (*set_pkg_cstate)(conf_object_t *cpu_obj,
                           uint32 state, uint32 sub_state);
        void (*pkg_cstate_update)(conf_object_t *cpu_obj,
                           bool notify);
};

#define X86_PKG_CSTATE_INTERFACE "x86_pkg_cstate"

Execution Context
Cell Context for all methods.

x86_reg_access

Description
The x86_reg_acc_access interface can be used to access x86 register state in an efficient manner. The interface is intended to be used from user decoder service routines.

This interface is internal and may change without notice.

SIM_INTERFACE(x86_reg_access) {
        uint64 (*get_gpr)(conf_object_t *cpu, unsigned index);
        void (*set_gpr)(conf_object_t *cpu, unsigned index, uint64 val);

        uint64 (*get_rip)(conf_object_t *cpu);
        void (*set_rip)(conf_object_t *cpu, uint64 rip);

        uint64 (*get_rflags)(conf_object_t *cpu);
        void (*set_rflags)(conf_object_t *cpu, uint64 rflags);

        /* Possibly faster method for setting only cf,pf,af,zf,sf,of */
        void (*set_status_flags)(conf_object_t *cpu, uint16 flags);

        /* Regular segment registers */
        x86_seg_reg_t (*get_seg)(conf_object_t *cpu, x86_seg_t n);
        void (*set_seg)(conf_object_t *cpu, x86_seg_t n, x86_seg_reg_t seg);

        /* IDTR and GDTR */
        x86_system_seg_reg_t (*get_system_seg)(conf_object_t *cpu,
                                               x86_system_seg_t n);
        void (*set_system_seg)(conf_object_t *cpu, x86_system_seg_t n,
                               x86_system_seg_reg_t seg);

        /* Control registers */
        uint64 (*get_cr)(conf_object_t *cpu, x86_cr_t n);
        void (*set_cr)(conf_object_t *cpu, x86_cr_t n, uint64 val);
        uint64 (*get_efer)(conf_object_t *cpu);
        void (*set_efer)(conf_object_t *cpu, uint64 efer);
        uint64 (*get_xcr)(conf_object_t *cpu, x86_xcr_t n);
        void (*set_xcr)(conf_object_t *cpu, x86_xcr_t n, uint64 val);

        /* x87 FPU */
        x86_fpu_reg_t (*get_freg)(conf_object_t *cpu, unsigned index);
        void (*set_freg)(conf_object_t *cpu, unsigned index, x86_fpu_reg_t freg);
        x86_fpu_env_t (*get_fpu_env)(conf_object_t *cpu);
        void (*set_fpu_env)(conf_object_t *cpu, x86_fpu_env_t state);

        /* SIMD */
        xmm_reg_t (*get_xmm)(conf_object_t *cpu, unsigned index);
        void (*set_xmm)(conf_object_t *cpu, unsigned index, xmm_reg_t val);
        ymm_reg_t (*get_ymm)(conf_object_t *cpu, unsigned index);
        void (*set_ymm)(conf_object_t *cpu, unsigned index, ymm_reg_t val);
        uint32 (*get_mxcsr)(conf_object_t *cpu);
        void (*set_mxcsr)(conf_object_t *cpu, uint32 mxcsr);

        /* Debug registers */
        uint64 (*get_dr)(conf_object_t *cpu, x86_dr_t n);
        void (*set_dr)(conf_object_t *cpu, x86_dr_t n, uint64 val);

        /* SMM */
        bool (*get_in_smm)(conf_object_t *cpu);
        void (*set_in_smm)(conf_object_t *cpu, bool val);
        uint64 (*get_smm_base)(conf_object_t *cpu);
        void (*set_smm_base)(conf_object_t *cpu, uint64 val);

        /* Monitor/Mwait */
        x86_monitor_info_t (*get_monitor_info)(conf_object_t *cpu);
        void (*set_monitor_info)(conf_object_t *cpu, x86_monitor_info_t val);
        x86_mwait_info_t (*get_mwait_info)(conf_object_t *cpu);
        void (*set_mwait_info)(conf_object_t *cpu, x86_mwait_info_t val);

        /* Non-register state */
        x86_activity_t (*get_activity_state)(conf_object_t *cpu);
        void (*set_activity_state)(conf_object_t *cpu, x86_activity_t val);
        x86_intstate_t (*get_interruptibility_state)(conf_object_t *cpu);
        void (*set_interruptibility_state)(conf_object_t *cpu,
                                           x86_intstate_t val);

        /* A debug exception is pending if triggered by the last instruction,
           but not yet taken. */
        x86_pending_debug_exc_t (*get_pending_debug_exc)(conf_object_t *cpu);
        void (*set_pending_debug_exc)(conf_object_t *cpu,
                                      x86_pending_debug_exc_t val);

        /* Derived state for fast/easy access */
        x86_xmode_info_t (*get_xmode_info)(conf_object_t *cpu);
        x86_exec_mode_t (*get_exec_mode)(conf_object_t *cpu);

        /* This is configuration info. No need for a set method. */
        uint32 (*get_mxcsr_mask)(conf_object_t *cpu);

        /* Extension state dirty bit modification (for XSAVE) */
        uint64 (*get_ext_state_dirty_bits)(conf_object_t *cpu);
        void (*or_ext_state_dirty_bits)(conf_object_t *cpu, uint64 dirty_bits);
        void (*and_ext_state_dirty_bits)(conf_object_t *cpu, uint64 dirty_bits);

        /* PDPTE registers used in PAE paging mode */
        uint64 (*get_pdpte)(conf_object_t *cpu, int num);
        void (*set_pdpte)(conf_object_t *cpu, int num, uint64 val);

        uint32 (*get_vmx_mode)(conf_object_t *cpu);
};
#define X86_REG_ACCESS_INTERFACE "x86_reg_access"

Execution Context
Cell Context for all methods.

x86_smm

Description
The smm interface is used to implement a custom SMRAM state save map.

The save_state method is invoked when SMM mode is entered before any cpu state has been modified. The method should save the current cpu state to the SMRAM state save map.

The restore_state method is invoked during execution of the rsm instruction. The method should restore the cpu state from the SMRAM state save map.

The x86_smm_state interface implemented by the cpu can be used to facilitate cpu state changes and SMRAM access.

This interface is internal and may change without notice.

SIM_INTERFACE(x86_smm) {
        void (*save_state)(conf_object_t *obj, conf_object_t *cpu);
        void (*restore_state)(conf_object_t *obj, conf_object_t *cpu);
};
#define X86_SMM_INTERFACE "x86_smm"

Execution Context
Cell Context for all methods.

x86_smm_state

Description
The smm state interface is implemented by the cpu and is typically used by objects implementing the x86_smm interface.

The get_state method saves the cpu state in the state struct. This method is intended to be used during SMM entry.

The set_state method restores the cpu state from the state struct. This method is intended to be used during SMM exit.

The smram_read and smram_write methods can be used to access the SMRAM during SMM entry/exit.

This interface is internal and may change without notice.

SIM_INTERFACE(x86_smm_state) {
        void (*get_state)(conf_object_t *cpu, smm_reg_state_t *state);
        void (*set_state)(conf_object_t *cpu, const smm_reg_state_t *state);

        uint64 (*smram_read)(conf_object_t *obj,
                             unsigned smram_offs, unsigned len);
        void (*smram_write)(conf_object_t *obj,
                            unsigned smram_offs, unsigned len, uint64 val);
};
#define X86_SMM_STATE_INTERFACE "x86_smm_state"

Execution Context
Cell Context for all methods.

x86_tlb

Description
The x86 tlb interface is used for communication between an x86 cpu and its TLB. The TLB is implemented as a separate class for greater flexibility. The TLB object does no memory operations itself.

typedef struct {
        int                  valid;
        physical_address_t   paddr;
} tagged_physical_address_t;

SIM_INTERFACE(x86_tlb) {
        void (*flush_all)(conf_object_t *obj,
                            int keep_global_entries);
        void (*flush_page)(conf_object_t *obj,
                           linear_address_t laddr);
        int (*lookup)(conf_object_t *obj,
                      x86_memory_transaction_t *mem_tr);
        void (*add)(conf_object_t *obj,
                    processor_mode_t mode,
                    read_or_write_t read_or_write,
                    data_or_instr_t data_or_instr,
                    int global_page,
                    x86_memory_type_t pat_type,
                    x86_memory_type_t mtrr_type,
                    linear_address_t laddr,
                    physical_address_t paddr,
                    int page_size);
        tagged_physical_address_t (*itlb_lookup)(conf_object_t *obj,
                                                 linear_address_t laddr,
                                                 processor_mode_t mode);
        void (*set_pae_mode)(conf_object_t *obj, bool pae_mode);
};

#define X86_TLB_INTERFACE "x86_tlb"

All functions in the interface get the object implementing the interface as their first parameter.

flush_all is called when all TLB entries should be flushed. If keep_global_entries is set, then TLB entries with their global bit set should not be flushed.

flush_page is invoked when pages containing laddr are to be removed from the TLB.

lookup is used by the CPU when a memory access misses the STC. It must return true (non-zero) if and only if the memory operation specified by mem_tr hits the TLB and does not raise an exception. The mode, linear_address are valid when the method is invoked. The other fields passed through mem_tr are undefined. If the method returns true, the s.physical_address, pat_type, and mtrr_type fields of mem_tr must be updated by lookup.

An access that misses in lookup but does not raise a fault is inserted into the TLB with add. The page_size encoding is 0 for 4 kb pages, 1 for 2 Mb pages, and 2 for 4 Mb pages.

itlb_lookup is a simplified version of lookup used only for instruction TLB lookups. If the lookup is successful valid and paddr should be set, otherwise valid should be cleared.

set_pae_mode is invoked when the cpu changes the PAE enable bit.

It class implementing the interface must make sure that only addresses mapped in the TLB are present in the STCs.

This interface may be changed or replaced with an architecture independent interface in future versions of Simics.

Execution Context
Cell Context for all methods.

x86_tlb_v2

Description
The x86_tlb_v2 interface is used for communication between an x86 cpu and its TLB. The TLB is implemented as a separate class for greater flexibility. The TLB object does no memory operations itself.

flush_all is called when all TLB entries should be flushed. If keep_global_entries is set, then TLB entries with their global bit set should not be flushed.

flush_page is invoked when pages containing laddr are to be removed from the TLB.

lookup is used by the CPU when a memory access misses the STC. It returns the matching TLB entry if the memory operation specified in mem_tr hits the TLB and does not raise an exception. Otherwise NULL is returned. The mode, linear_address, and type fields in mem_tr need to be valid when the method is invoked. The other fields passed through mem_tr are not to be used by the method and can carry any value. If the method returns true, the s.physical_address, pat_type, and mtrr_type fields of mem_tr must be updated by lookup.

Pages are added to the TLB with add. The supervisor_access field in attrs argument specifies the allowed access types in supervisor mode and user_access in attrs specifies the allowed access types in user mode.

itlb_lookup is a simplified version of lookup used only for instruction TLB lookups. If the lookup is successful valid and paddr should be set, otherwise valid should be cleared.

The class implementing the interface must make sure that only addresses mapped in the TLB are present in the STCs.

SIM_INTERFACE(x86_tlb_v2) {
        void (*flush_all)(conf_object_t *obj,
                          int keep_global_entries);
        void (*flush_page)(conf_object_t *obj,
                           linear_address_t laddr);
        const x86_tlb_entry_t *(*lookup)(conf_object_t *obj,
                                         x86_memory_transaction_t *mem_tr);
        void (*add)(conf_object_t *obj,
                    linear_address_t laddr,
                    physical_address_t paddr,
                    x86_tlb_attrs_t attrs);
        tagged_physical_address_t (*itlb_lookup)(conf_object_t *obj,
                                                 linear_address_t laddr,
                                                 processor_mode_t mode);
};

#define X86_TLB_V2_INTERFACE "x86_tlb_v2"

Execution Context
Cell Context for all methods.

x86_tlb_v3

Description
The x86_tlb_v3 interface is used for communication between an x86 cpu and its TLB. The TLB is implemented as a separate class for greater flexibility. The TLB object does no memory operations itself.

Pages are added to the TLB with add. Process context identifier, linear and physical address for translation specified using arguments hint, laddr and paddr correspondingly. The fields in attrs argument used for specification of allowed access types and additional page attributes.

lookup is used by the CPU when a memory access misses the STC. It returns the matching TLB entry if the memory operation specified in mem_tr hits the TLB and does not raise an exception. Otherwise NULL is returned. The hint argument specifies process context identifier. The mode, linear_address, and type fields in mem_tr need to be valid when the method is invoked. The other fields passed through mem_tr are not to be used by the method and can carry any value. If the method returns not NULL, the s.physical_address, pat_type, and mtrr_type fields of mem_tr must be updated by lookup.

itlb_lookup is a simplified version of lookup used only for instruction TLB lookups. If the lookup is successful valid and paddr should be set, otherwise valid should be cleared.

invalidate_page is used to remove from TLB page corresponding to given linear address specified by argument laddr in process context with identifier from argument hint.

invalidate is invoked when value of CR4.PCIDE bit set and CPU executes INVPCID instruction. Direct and indirect operands of instruction transferred in hint, la and type arguments. TLB entries flushed according to INVPCID instruction description. New invalidation type X86_Tlb_Invalidate_Address_Space added to implement flush_all function from previous interfaces. The method also can be used to flush required TLB entries in any required cases.

The class implementing the interface must make sure that only addresses mapped in the TLB are present in the STCs.

SIM_INTERFACE(x86_tlb_v3) {
        void (*add)(conf_object_t *obj,
                    uint64 hint,
                    linear_address_t laddr,
                    physical_address_t paddr,
                    x86_tlb_attrs_v3_t attrs);
        const x86_tlb_entry_v3_t *(*lookup)(conf_object_t *obj,
                                            uint64 hint,
                                            x86_memory_transaction_t *mem_tr);
        tagged_physical_address_t (*itlb_lookup)(conf_object_t *obj,
                                                 uint64 hint,
                                                 linear_address_t laddr,
                                                 processor_mode_t mode);
        void    (*invalidate_page)(conf_object_t *obj,
                                   uint64 hint,
                                   linear_address_t laddr);
        void    (*invalidate)(conf_object_t *obj,
                              uint32 type,
                              uint64 hint,
                              linear_address_t la);
};

#define X86_TLB_V3_INTERFACE "x86_tlb_v3"

Execution Context
Cell Context for all methods.

x86_vmp_control

Description
The x86_vmp_control interface can be used to prevent VMP from being used.

The set_block_count method sets the VMP block count. If the VMP block count is non-zero, VMP will not be used for simulation.

The get_block_count method returns VMP block count.

This interface is internal and may change without notice.

SIM_INTERFACE(x86_vmp_control) {
        unsigned (*get_block_count)(conf_object_t *cpu);
        void (*set_block_count)(conf_object_t *cpu, unsigned cnt);
};
#define X86_VMP_CONTROL_INTERFACE "x86_vmp_control"

Execution Context
Cell Context for all methods.

xed_access

Description
The xed_access interface is implemented by a processor model. The interface can be used to call Intel® X86 Encoder Decoder (Intel\reg; XED) library built into the processor model.

This interface is internal and may change at any time without notice.

SIM_INTERFACE(xed_access) {
        int (*get_last)(conf_object_t *obj, xed_data_type_t type);
        int (*decode)(conf_object_t *obj, xed_data_type_t type, bytes_t bytes);
        const char *(*to_string)(conf_object_t *obj, xed_data_type_t type,
                                 int value);
};

#define XED_ACCESS_INTERFACE "xed_access"

Execution Context
Cell Context for all methods.

xtensa_export_state

Description
OBSOLETE! External Xtensa TIE interface for the export state type. user_object is the user object to use in the export_state_func callback.

The type of the export_state_func is defined in the xtensa/tie/cstub-extif.h file in the Xtensa model build directory.

Execution Context
Cell Context for all methods.

xtensa_import_wire

Description
External Xtensa TIE interface for the import wire type. A callback should be registered in order to send data to the object obj that implements the interface, typically a processor. The callback is called when the wire is accessed. The user_object is the user object to use in the import_wire_func callback.

The type of the import_wire_func is defined in the xtensa/tie/cstub-extif.h file in the Xtensa model build directory.

Execution Context
Cell Context for all methods.

xtensa_input_queue

Description
OBSOLETE! External Xtensa TIE interface for the input queue type. Two callbacks should be registered in order to send data to the object obj that implements the interface, typically a processor. When the queue is accessed the callbacks are called. user_object is the user object to use in the empty_callback and data_callback callbacks.

The types of the empty_callback callback and data_callback are defined in the xtensa/tie/cstub-extif.h file in the Xtensa model build directory. The empty_callback should return 1 if the queue is empty, otherwise 0. The data_callback is used for sending the data.

Execution Context
Cell Context for all methods.

xtensa_internal_memories

Description
This interface is implemented by all Xtensa cores. The methods correspond to the iram, irom, dram and drom attributes, reporting where the internal memories are located, in the form of: [[paddr_start, paddr_stop]*]. This is static and will never change, but is differently configured for each Xtensa cores.
Execution Context
Cell Context for all methods.

xtensa_lookup

Description
OBSOLETE! External Xtensa TIE interface for the lookup type. user_object is the user object to use in the lookup_func callback.

The type of the lookup_func is defined in the xtensa/tie/cstub-extif.h file in the Xtensa model build directory.

Execution Context
Cell Context for all methods.

xtensa_mpu_lookup

Description
This interface is implemented by the Xtensa core which is configured with an MPU. The primary use of this interface, is the iDMA device which will need to do various protection checks for the DMA transfers.

The mpu_region returns region data that hits for the specified address. If the address hits in a background mapping, the end address will be when a foreground mapping overrides the background mapping.

typedef struct xtensa_mpu_lookup {
        bool background;                 /* If false, a foreground hit */
        uint16 region;                   /* The foreground/background region */
        uint32 start;
        uint32 end;
        /* Permissions */
        bool sr;                             /* supervisor-read */
        bool sw;                             /* supervisor-write */
        bool sx;                             /* supervisor-execute */
        bool ur;                             /* user-read */
        bool uw;                             /* user-write */
        bool ux;                             /* user-execute */
} xtensa_mpu_lookup_t;

SIM_INTERFACE(xtensa_mpu_lookup) {
        xtensa_mpu_lookup_t (*mpu_region)(conf_object_t *obj, uint32 address);
};
#define XTENSA_MPU_LOOKUP_INTERFACE "xtensa_mpu_lookup"

Execution Context
Cell Context for all methods.

xtensa_output_queue

Description
OBSOLETE! External Xtensa TIE interface for the output queue type. Two callbacks should be registered in order to receive data from the object obj that implements the interface, typically a processor. When the queue is accessed the callbacks are called. user_object is the user object to use in the full_callback and data_callback callbacks.

The types of the full_callback and data_callback are defined in the xtensa/tie/cstub-extif.h file in the Xtensa model build directory. The full_callback should return 1 if the queue is full, otherwise 0. The data_callback is used for receiving the data.

Execution Context
Cell Context for all methods.

xtensa_reset_configure

Description
This interface is implemented by the Xtensa core, allowing external devices to programmatically change some aspects of how the reset should be handled during run-time.

The set_reset_prid method sets the corresponding PRID register, which gets assigned during reset. The value is also exposed by the reset_prid attribute.

The set_alternative_reset_vector method sets the address from which the alternative reset starts executing after reset, when the reset_select pin is high. The value is also exposed in the alternative_reset_vector attribute.

Both methods return a bool, indicating if they were successful or not. A false return indicates that the associated Xtensa options are not included in the model.

SIM_INTERFACE(xtensa_reset_configure) {
        bool (*set_reset_prid)(conf_object_t *obj, uint16 prid_value);
        bool (*set_alternative_reset_vector)(conf_object_t *obj, uint32 vector_address);
};
#define XTENSA_RESET_CONFIGURE_INTERFACE "xtensa_reset_configure"

Execution Context
Threaded Context for all methods.

xtensa_tie_export_state

Description
An export_state is a way for the Xtensa core to push data to a device implementing this interface.

The data method contains the transferred data out from the Xtensa CPU. The out_data pointer holds the data that can be read, but only bit_width bits should be examined.

Execution Context
Cell Context for all methods.

xtensa_tie_import_wire

Description
The import_wire supports reading data from a device implementing this interface.

The data method requests a in_data pointer to be filled with bit_width of data by the device.

Execution Context
Cell Context for all methods.

xtensa_tie_input_queue

Description
The input_queue represents a way for the Xtensa CPU to read data from a queue implemented in a device.

The empty method indicates if there is anything to read in the queue or not.

The data method is used to read data from the input queue implemented in the device, the device should write the next data in queue to the in_data pointer and fill it with bit_width bits of data.

If is_peek is true, the data should be returned, but not removed from the queue.

Execution Context
Cell Context for all methods.

xtensa_tie_lookup

Description
A lookup is a bidirectional communication between the Xtensa and the device implementing this interface. When the data method is received by the device, the out_data pointer contains out_width bits of data (from the Xtensa core) that the device should read and take action upon. As a response, the device should fill in in_width of bits in the in_data buffer, providing the result of the lookup back to the Xtensa instruction.
Execution Context
Cell Context for all methods.

xtensa_tie_output_queue

Description
The output_queue allows the Xtensa to push data on a queue which the device needs to implement.

With the full method the Xtensa CPU might ask if the queue is currently full or not.

To data method is used to push data on the output queue of the device. out_data is a pointer to the pushed data and bit_width how many bits that is pushed on the queue. If reserve_only is true, no data is present but the device should just allocate space for the data.

Execution Context
Cell Context for all methods.

xtensa_wwdt_config

Description
This interface is implemented by the Xtensa core which holds the configuration of the Windowed Watchdog Timer. The device itself is not part of the core, but implemented as an external device which fetches these values for correct device simulation, making the wwdt device generic for all configurations.

The has_wwdt method reports if the wwdt option is included in the core at all. The rest of the member functions extract configuration details from the core, if the core does not have wwdt enabled, all are zeros.

Execution Context
Cell Context for all methods.

xtensa_wwdt_faultinfo

Description
This interface is implemented by the wwdt timer allowing the SoC device to read out the status register. On real hardware the Wwdt_faultInfo is an eight bit output towards the device. However, in a simulator it makes more sense to allow the SoC-device to read the status when needed, instead of pushing out the new contents when bits changes. The uint8 value returned is a bitmask with the bits defined in xtensa_wwdt_fault_info_t.
typedef enum {
        Wwdt_Info_Derr_Inj_Dis = 1 << 7,
        Wwdt_Info_Tfv_Err      = 1 << 6,
        Wwdt_Info_Err_Inj      = 1 << 5,
        Wwdt_Info_Oor_Exp      = 1 << 4,
        Wwdt_Info_Oor_Kick     = 1 << 3,
        Wwdt_Info_Ill_Kick     = 1 << 2,
        Wwdt_Info_Cnt_Exp      = 1 << 1,
        Wwdt_Fault_Asserted    = 1 << 0,
} xtensa_wwdt_faultinfo_t;

Execution Context
Cell Context for all methods.

5 Model-to-Simulator Interfaces

abs_pointer

Description
Interface implemented by tablet devices. Used by consoles to send touchpad events to the controller. The set_state function is called when something changes in the console. The coordinates are given as scaled absolute scaled values, where (0, 0) is the upper-left corner and (0xffff, 0xffff) is the lower-right corner.

typedef enum {
        Abs_Pointer_Button_Left   = 0x20,
        Abs_Pointer_Button_Right  = 0x10,
        Abs_Pointer_Button_Middle = 0x08
} abs_pointer_buttons_t;

typedef struct {
        abs_pointer_buttons_t buttons;
        uint16 x;
        uint16 y;
        uint16 z;
} abs_pointer_state_t;

SIM_INTERFACE(abs_pointer) {
        void (*set_state)(conf_object_t *obj, abs_pointer_state_t state);
};

#define ABS_POINTER_INTERFACE "abs_pointer"

Execution Context
Cell Context for all methods.

abs_pointer_activate

Description
Interface used by tablet controllers to temporary turn off and on the tracking of absolute pointer locations. Implemented by consoles. When disabled, no calls will be made to the controller's abs_pointer interface.

SIM_INTERFACE(abs_pointer_activate) {
        void (*enable)(conf_object_t *obj);
        void (*disable)(conf_object_t *obj);
};

#define ABS_POINTER_ACTIVATE_INTERFACE "abs_pointer_activate"

Execution Context
Cell Context for all methods.

apic_bus_v2

Description
The interface is used to handle extended 32-bit addressing mode supported by x2APIC. See apic_bus documentation.
SIM_INTERFACE(apic_bus_v2) {
        apic_bus_status_t (*interrupt)(conf_object_t *obj,
                apic_destination_mode_t dest_mode,
                apic_delivery_mode_t delivery_mode,
                int level_assert,
                apic_trigger_mode_t trigger_mode,
                uint8 vector,
                uint32 destination);
};
#define APIC_BUS_V2_INTERFACE "apic_bus_v2"

Execution Context
Cell Context.

bank_after_read

Description
The bank_after_read interface is used to monitor and modify the state of read accesses from the after_read_callback_t callback.

SIM_INTERFACE(bank_after_read) {
        physical_address_t (*offset)(bank_access_t *handle);
        physical_address_t (*size)(bank_access_t *handle);
        bool (*missed)(bank_access_t *handle);
        uint64 (*value)(bank_access_t *handle);

        void (*set_missed)(bank_access_t *handle, bool missed);
        void (*set_value)(bank_access_t *handle, uint64 value);
        conf_object_t *(*initiator)(bank_access_t *handle);
};
#define BANK_AFTER_READ_INTERFACE "bank_after_read"

offset retrieves the address of the access.

size gets the size of the access.

missed tells you whether or not the access succeeded.

value provides the read value. May not be invoked if missed is true.

set_missed can be used to inject or forgive an access miss.

set_value can change the read value.

initiator returns the initiator of the access. This method may be NULL, although this is deprecated. If the interface was implemented by a DML/C/C++ bank, then the method may only be accessed if the bank was compiled with Simics Base 6.0.129 or newer.

Execution Context
Cell Context for all methods, but must be called from an after_read_callback_t callback with a valid handle of type bank_access_t.

bank_after_write

Description
The bank_after_write interface is used to monitor and modify the state of write accesses from the after_write_callback_t callback.

SIM_INTERFACE(bank_after_write) {
        physical_address_t (*offset)(bank_access_t *handle);
        physical_address_t (*size)(bank_access_t *handle);
        bool (*missed)(bank_access_t *handle);

        void (*set_missed)(bank_access_t *handle, bool missed);
        conf_object_t *(*initiator)(bank_access_t *handle);
};
#define BANK_AFTER_WRITE_INTERFACE "bank_after_write"

offset retrieves the address of the access.

size gets the size of the access.

missed tells you whether or not the access succeeded.

set_missed can be used to inject or forgive an access miss.

initiator returns the initiator of the access. This method may be NULL, although this is deprecated. If the interface was implemented by a DML/C/C++ bank, then the method may only be accessed if the bank was compiled with Simics Base 6.0.129 or newer.

Execution Context
Cell Context for all methods, but must be called from an after_write_callback_t callback with a valid handle of type bank_access_t.

bank_before_read

Description
The bank_before_read interface is used to monitor and modify the state of read accesses from the before_read_callback_t callback.

SIM_INTERFACE(bank_before_read) {
        physical_address_t (*offset)(bank_access_t *handle);
        physical_address_t (*size)(bank_access_t *handle);

        void (*set_offset)(bank_access_t *handle, physical_address_t offset);
        void (*inquire)(bank_access_t *handle);
        conf_object_t *(*initiator)(bank_access_t *handle);
};
#define BANK_BEFORE_READ_INTERFACE "bank_before_read"

offset retrieves the address of the access.

size gets the size of the access.

set_offset can be used to redirect the access to another address.

inquire can turn the access into an inquiry access. Subsequent and corresponding after_read callbacks are invoked regardless.

initiator returns the initiator of the access. This method may be NULL, although this is deprecated. If the interface was implemented by a DML/C/C++ bank, then the method may only be accessed if the bank was compiled with Simics Base 6.0.129 or newer.

Execution Context
Cell Context for all methods, but must be called from a before_read_callback_t callback with a valid handle of type bank_access_t.

bank_before_write

Description
The bank_before_write interface is used to monitor and modify the state of write accesses from the before_write_callback_t callback.

SIM_INTERFACE(bank_before_write) {
        physical_address_t (*offset)(bank_access_t *handle);
        physical_address_t (*size)(bank_access_t *handle);
        uint64 (*value)(bank_access_t *handle);

        void (*suppress)(bank_access_t *handle);
        void (*set_offset)(bank_access_t *handle, physical_address_t offset);
        void (*set_value)(bank_access_t *handle, uint64 value);
        conf_object_t *(*initiator)(bank_access_t *handle);
};
#define BANK_BEFORE_WRITE_INTERFACE "bank_before_write"

offset retrieves the address of the access.

size gets the size of the access.

value provides the write value.

suppress may be used to prevent the write. Subsequent and corresponding after_write callbacks are invoked regardless.

set_offset can be used to redirect the write to an another address.

set_value can change the write value.

initiator returns the initiator of the access. This method may be NULL, although this is deprecated. If the interface was implemented by a DML/C/C++ bank, then the method may only be accessed if the bank was compiled with Simics Base 6.0.129 or newer.

Execution Context
Cell Context for all methods, but must be called from a before_write_callback_t callback with a valid handle of type bank_access_t.

bank_instrumentation_subscribe

Description
The bank_instrumentation_subscribe interface is implemented by non-anonymous register banks. The interface may be used to monitor and modify register accesses using callbacks.

Similar to the CPU instrumentation framework, a bank that implements the interface is considered an instrumentation provider and is typically used by an instrumentation tool. The tool registers callbacks using this interface and performs its actions once they are called. Using this interface, tools may also group registered callbacks using connection objects. This can be useful to enforce a certain evaluation order of grouped callbacks.

The bank argument in all methods is the register bank object implementing this interface.

The connection can be used to group registered callbacks together, so that their order may be changed or their registered callbacks be enabled, disabled, or removed collectively. If connection is NULL when registering a callback, the callback is considered anonymous. Anonymous callbacks are evaluated before any other callbacks in the order of creation. See instrumentation_order interface for more details on the callback order.

Each registration method installs a callback which is called at a particular time, before or after, read and write register accesses. Callbacks are not invoked during inquiry accesses. Using the offset and size arguments, a user may install the callback only for a particular range. If offset and size are 0 the callback is installed for the entire bank.

The user_data is used to associate user defined data with every callback. Every time the callback is invoked the data is provided as an argument to the callback.

SIM_INTERFACE(bank_instrumentation_subscribe) {
        bank_callback_handle_t (*register_before_read)(
                conf_object_t *NOTNULL bank,
                conf_object_t *connection,
                uint64 offset,
                uint64 size,
                before_read_callback_t before_read,
                lang_void *user_data);
        bank_callback_handle_t (*register_after_read)(
                conf_object_t *NOTNULL bank,
                conf_object_t *connection,
                uint64 offset,
                uint64 size,
                after_read_callback_t after_read,
                lang_void *user_data);

        bank_callback_handle_t (*register_before_write)(
                conf_object_t *NOTNULL bank,
                conf_object_t *connection,
                uint64 offset,
                uint64 size,
                before_write_callback_t before_write,
                lang_void *user_data);
        bank_callback_handle_t (*register_after_write)(
                conf_object_t *NOTNULL bank,
                conf_object_t *connection,
                uint64 offset,
                uint64 size,
                after_write_callback_t after_write,
                lang_void *user_data);

        void (*remove_callback)(conf_object_t *NOTNULL bank,
                                bank_callback_handle_t callback);

        void (*remove_connection_callbacks)(conf_object_t *NOTNULL bank,
                                            conf_object_t *NOTNULL connection);
        void (*enable_connection_callbacks)(conf_object_t *NOTNULL bank,
                                            conf_object_t *NOTNULL connection);
        void (*disable_connection_callbacks)(conf_object_t *NOTNULL bank,
                                             conf_object_t *NOTNULL connection);

};
#define BANK_INSTRUMENTATION_SUBSCRIBE_INTERFACE \
        "bank_instrumentation_subscribe"

Every function that registers a callback returns a unique handle of type bank_callback_handle_t. The remove_callback method uninstalls the callback associated with the handle. The remove_connection_callbacks uninstalls all callbacks associated with a connection object. Similarly, the enable_connection_callbacks and disable_connection_callbacks methods are used to temporarily enable or disable a group of callbacks.

Callback functions registered through the bank_instrumentation_subscribe interface are called before or after read and write accesses, like so:

typedef void (*before_read_callback_t)(conf_object_t *connection,
                                       bank_before_read_interface_t *access,
                                       bank_access_t *handle,
                                       lang_void *user_data);

typedef void (*after_read_callback_t)(conf_object_t *connection,
                                      bank_after_read_interface_t *access,
                                      bank_access_t *handle,
                                      lang_void *user_data);

typedef void (*before_write_callback_t)(conf_object_t *connection,
                                        bank_before_write_interface_t *access,
                                        bank_access_t *handle,
                                        lang_void *user_data);

typedef void (*after_write_callback_t)(conf_object_t *connection,
                                       bank_after_write_interface_t *access,
                                       bank_access_t *handle,
                                       lang_void *user_data);

The connection is the object used to group the callback with any other callbacks, which may be NULL. The access object provides a number of methods which may be used along with the handle to perform a certain set of actions at the particular point of the access. The user_data is the custom data which was associated with the callback at registration.

For every callback, additional information may be accessed using a specific interface which is passed as a parameter to the callback. See bank_before_read, bank_after_read, bank_before_write, and bank_after_write for details.

Execution Context
Cell Context for all methods.

branch_recorder_handler

Description
An internal interface. Can be changed at any time.
Execution Context
Internal.

breakpoint

Description
The breakpoint interface is implemented by any object that supports breaking on an address range.

SIM_INTERFACE(breakpoint) {
        void (*insert_breakpoint)(conf_object_t *object,
                                  conf_object_t *caller,
                                  breakpoint_handle_t handle,
                                  access_t access,
                                  generic_address_t start,
                                  generic_address_t end);
        void (*remove_breakpoint)(conf_object_t *object,
                                  breakpoint_handle_t handle);
        breakpoint_info_t (*get_breakpoint)(conf_object_t *obj,
                                            breakpoint_handle_t handle);
};

#define BREAKPOINT_INTERFACE "breakpoint"

The insert_breakpoint function is called when adding a breakpoint on object. The handle identified the breakpoint and is to be used when triggering the breakpoint and when breakpoints are removed. The access parameter specifies the types of accesses that the breakpoint is set for. The breakpoint range is from start to end and includes both ends.

The implementer of this interface should call caller through the breakpoint_trigger interface to trigger the breakpoint.

remove_breakpoint should remove the breakpoint and further accesses to the address range should not trigger that breakpoint.

This interface is only to be used by the Simics core. Other uses of breakpoints should go through the available breakpoint API calls such as SIM_breakpoint.

Execution Context
Cell Context for all methods.

breakpoint_change

Description
The breakpoint_change interface is implemented by objects that wish to get notified when breakpoints are added, removed, or changed in some way.

The object that wants to get notified of changes to breakpoints in a another object would use the simple_dispatcher in the breakpoint_change port of that other object. The other object will then lookup the breakpoint_change interface in the object to notify and use that when breakpoint updates occur.

The breakpoint_change port is implemented by objects of the cell class, and a listener that registers on a cell with get notified on any breakpoint changes in that cell.

SIM_INTERFACE(breakpoint_change) {
        void (*breakpoint_added)(conf_object_t *obj,
                                 conf_object_t *bp_obj,
                                 breakpoint_handle_t handle);
        void (*breakpoint_removed)(conf_object_t *obj,
                                   conf_object_t *bp_obj,
                                   breakpoint_handle_t handle);
};

#define BREAKPOINT_CHANGE_INTERFACE "breakpoint_change"

Execution Context
Cell Context for all methods.

breakpoint_query_v2

Description
Objects of the context and memory-space classes implement the breakpoint_query_v2 interface. It is used by processors to check for breakpoints.

Implementors of this interface should use SIM_register_compatible_interfaces after SIM_register_interface to also register earlier versions of the interface.

The get_breakpoints function returns a set of breakpoints that intersect the range given in start and end, including both start and end in the range. Only breakpoints set on access types with bits set in read_write_execute will be returned.

When information from get_breakpoints has been processed, the breakpoints array in the breakpoint_set_t structure should be freed with MM_FREE.

SIM_INTERFACE(breakpoint_query_v2) {
        breakpoint_set_t (*get_breakpoints)(conf_object_t *obj,
                                            access_t read_write_execute,
                                            generic_address_t start,
                                            generic_address_t end);
};

#define BREAKPOINT_QUERY_V2_INTERFACE "breakpoint_query_v2"

Execution Context
Cell Context for all methods.

breakpoint_trigger

Description
Objects implementing the breakpoint interface typically also implement the breakpoint_trigger interface. Processors call the trigger_breakpoint function to signal that a memory access intersects a breakpoint. The trigger_breakpoint function will raise the appropriate haps and the currently scheduled execute object may receive a stop call during the call to trigger_breakpoint.

The obj argument is the object that holds the breakpoint, typically a memory space or a context object. initiator_obj is the source of the memory operation that triggers the breakpoint. The handle argument identifies the breakpoint to trigger. A value of BREAKPOINT_HANDLE_ANY can be passed as handle, in which case all the breakpoints that match the given address, size, and access will be triggered. The address, size, and access arguments specify information about the access that triggers the breakpoint. The data argument points to a buffer where the data for the access is kept.

If a stop is received during a call to trigger_breakpoint, then it is recommended that any software visible actions carried out after the breakpoint are logged. That could for example be to notify the user if the entire instruction that triggers a breakpoint will complete, and that the instruction will then not be re-executed when the simulation restarts.

SIM_INTERFACE(breakpoint_trigger) {
        void (*trigger_breakpoint)(conf_object_t *obj,
                                   conf_object_t *initiator_obj,
                                   breakpoint_handle_t handle,
                                   generic_address_t address,
                                   generic_address_t size,
                                   access_t access,
                                   uint8 *data);
};

#define BREAKPOINT_TRIGGER_INTERFACE "breakpoint_trigger"

Execution Context
Cell Context for all methods.

callback_info

Description
This interface can be implemented by any object that can issue callbacks. The get_callbacks method returns a attr_value_t list of type [[(o|n)sss*]] where o is the object that installed the callback (if applicable, otherwise NIL). The sss strings are:

  • A one liner description about the callback. Could for example contain the interface method that installed the callback, if such one exist.
  • The function name.
  • A string describing the user data.

SIM_INTERFACE(callback_info) {
        attr_value_t (*get_callbacks)(conf_object_t *obj);
};
#define CALLBACK_INFO_INTERFACE "callback_info"

Execution Context
Cell Context for all methods, but must be called from a callback receiving a handle of type instruction_handle_t.

cell_inspection

Description
The cell_inspection interface is implemented by objects of the cell class. It is used by objects implementing the execute interface to update the currently executing objects when control is transferred outside of the execute object.

The current object implementing processor_info is set with set_current_processor_obj(). Similarly, the current object implementing step is set with set_current_step_obj().

SIM_INTERFACE(cell_inspection) {
        void (*set_current_processor_obj)(conf_object_t *obj,
                                          conf_object_t *cpu_obj);
        void (*set_current_step_obj)(conf_object_t *obj,
                                     conf_object_t *step_obj);
};

#define CELL_INSPECTION_INTERFACE "cell_inspection"

Execution Context
Cell Context for all methods.

co_execute

Description
Experimental, may change without notice.

SIM_INTERFACE(co_execute) {
        void (*start_thread)(conf_object_t *NOTNULL obj,
                             void (*entry)(lang_void *arg), lang_void *arg);
        void (*yield)(conf_object_t *NOTNULL obj);
};
#define CO_EXECUTE_INTERFACE "co_execute"

Execution Context
Cell Context

component

Description
All component classes must implement the component interface. All functions in the interface must be implemented.

The pre_instantiate function is called before the component is instantiated. The function returns true if the component can be instantiated, or false if not.

The component might need to do some extra work after the component has been instantiated. This should be done when called via the post_instantiate function.

The create_cell function returns true if the configuration system can create a default cell object for the component, or false if not. Both pre_instantiate and create_cell typically return true.

Component has slots. A slot has key and value. The key is the slot name as a string. The value is a conf object, a pre conf object, or None, or nested lists of such types.

Slots are either defined in the component or added after the component has been created. Slots defined in the component are static slots which can not be deleted, but the slot value can be changed. Slots added to the component after creation are dynamic slots and they can be removed when wanted.

The get_slots function returns a dictionary with slot names as dictionary keys and slot values as dictionary values.

The get_slot_objects function returns a list of all conf objects and pre conf objects extracted from all slot values.

The get_slot_value returns the slot value. The slot name is passed as slot argument. A slot value is set using the set_slot_value function. The value argument should be a conf object, pre conf object, or None, or nested lists of such types. The get function returns NULL on failure. The set function does not return anything to indicate failure.

The has_slot function returns true if the slot exists, otherwise false. The slot can either be a static slot or a dynamic slot. The add_slot function adds the slot named slot. Adding a slot can fail if the slot already exist. The added slot will be a dynamic slot. A dynamic slot can be deleted. The del_slot function deletes a dynamic slot. Deleting a slot will fail if the slot does not exist or if the slot is static. Both add_slot and del_slot returns true on success or false on failure.

SIM_INTERFACE(component) {
        bool (*pre_instantiate)(conf_object_t *obj);
        void (*post_instantiate)(conf_object_t *obj);
        bool (*create_cell)(conf_object_t *obj);

        attr_value_t (*get_slots)(conf_object_t *obj);
        attr_value_t (*get_slot_objects)(conf_object_t *obj);

        attr_value_t (*get_slot_value)(conf_object_t *obj,
                                 const char *NOTNULL slot);
        void (*set_slot_value)(conf_object_t *obj,
                         const char *NOTNULL slot,
                         attr_value_t value);

        bool (*has_slot)(conf_object_t *obj,
                         const char *NOTNULL slot);
        bool (*add_slot)(conf_object_t *obj,
                         const char *NOTNULL slot);
        bool (*del_slot)(conf_object_t *obj,
                         const char *NOTNULL slot);
};
#define COMPONENT_INTERFACE "component"

Execution Context
post_instantiateGlobal Context
pre_instantiateGlobal Context
create_cellGlobal Context
get_slotsCell Context
get_objectsCell Context
get_slot_valueGlobal Context
set_slot_valueGlobal Context
add_slotGlobal Context
del_slotGlobal Context

component_connector

Description
The component_connector is implemented by components that use connector objects for handling connections between components.

The connection setup is made in two stages, the check stage and the connect stage. The check stage is often not needed, but it can be used to make sure that the later connect step will not fail. Each connection is handled by a connector object. The connector object will both handle the connection in both direction, i.e. sending connect information and receiving connector information. Two components that should be connected must implement one connector object each.

The get_check_data and get_connect_data will be called from the connector object to get connection data to send to the other part of the connection, i.e. to the destination. The data sent must be an attr_value_t type.

The check, connect, and disconnect functions are called from the connector object when another connector wants to connect to this connection. The connection data is passed as the attr argument.

SIM_INTERFACE(component_connector) {
        attr_value_t (*get_check_data)(conf_object_t *obj,
                                       conf_object_t *NOTNULL connector);
        attr_value_t (*get_connect_data)(conf_object_t *obj,
                                         conf_object_t *NOTNULL connector);
        bool (*check)(conf_object_t *obj, conf_object_t *NOTNULL connector,
                      attr_value_t attr);
        void (*connect)(conf_object_t *obj, conf_object_t *NOTNULL connector,
                        attr_value_t attr);
        void (*disconnect)(conf_object_t *obj,
                           conf_object_t *NOTNULL connector);
};

#define COMPONENT_CONNECTOR_INTERFACE "component_connector"

Execution Context
Global Context for all methods.

concurrency_group

Description
The concurrency_group interface is used to ensure that groups of objects are placed in the same thread domain.

The serialized_memory_group method returns a list with objects that should be placed in the same thread domain when the models run in Sim_Concurrency_Mode_Serialized_Memory.

The execution_group method returns a list with objects that should always be placed in the same thread domain.

Both methods take a group_index argument, allowing multiple lists to be returned. The index argument is 0-based, and a nil attribute for the first unsupported index. Note that returned lists do not necessarily contain the object implementing the interface; the interface can be used to group other objects.

When Simics forms the thread domain groups, all objects implementing the concurrency_group are queried, and the constraints are combined. For instance, the groups [A, B] and [A, C] are combined into the group [A, B, C]. That is, the objects A, B and C will be put in the same thread domain.

Refer to the threading chapter in the API Reference Manual for more details.

SIM_INTERFACE(concurrency_group) {
        attr_value_t (*serialized_memory_group)(conf_object_t *NOTNULL obj,
                                                unsigned group_index);
        attr_value_t (*execution_group)(conf_object_t *NOTNULL obj,
                                        unsigned group_index);
};
#define CONCURRENCY_GROUP_INTERFACE "concurrency_group"

Execution Context
Global Context for all methods.

concurrency_mode

Description

The concurrency_mode interface allows a model to support a concurrency mode other than the default Sim_Concurrency_Mode_Serialized.

The supported_modes method returns a bitmask with all the supported modes.

The current_mode method returns the currently active mode. Note that the model should normally checkpoint this setting.

The switch_mode method is invoked by Simics to notify a model that a different concurrency mode has been selected by the user. This typically happens when the user switches threading mode using the set-threading-mode command. The object will typically be placed in a different thread domain shortly after the call to this method.

A model will be placed in the cell thread domain if it uses the Sim_Concurrency_Mode_Serialized mode and in a separate thread domain otherwise. The concurrency_group interface can be used to ensure that multiple objects are placed in the same thread domain.

Refer to the chapter about threading in the API Reference Manual for details about thread domains, the Standard Device Model and the Threaded Device Model.

typedef enum {
        /* Model uses the Standard Device Model */
        Sim_Concurrency_Mode_Serialized = 1,

        /* Model uses the Threaded Device Model.
           Direct memory pages are protected against concurrency. */
        Sim_Concurrency_Mode_Serialized_Memory = 2,

        /* Model uses the Threaded Device Model.
           Concurrency can be observed on direct memory pages */
        Sim_Concurrency_Mode_Full = 4,
} concurrency_mode_t;

SIM_INTERFACE(concurrency_mode) {
        concurrency_mode_t (*supported_modes)(conf_object_t *NOTNULL obj);
        concurrency_mode_t (*current_mode)(conf_object_t *NOTNULL obj);
        void (*switch_mode)(conf_object_t *NOTNULL obj,
                            concurrency_mode_t mode);
};
#define CONCURRENCY_MODE_INTERFACE "concurrency_mode"

Execution Context
Global Context for all methods.

connector

Description
The connector interface must be implemented by connector objects. The interface describes the connector and how it can be connected to other connectors. A connector is used for connecting component objects. The connector is just a proxy for the connection, the connector uses the component_connector interface in the components to setup the connection.

The type function returns the connector type as a string. Two connectors can only be connected if the type is identical.

A hotpluggable connector returns true when calling the hotpluggable function, otherwise false. A hotpluggable connector can be connected before or after the component is instantiated, an non hotpluggable connector must be connected before the component is instantiated.

The required function returns true if the connector must be connected before instantiated, otherwise false.

A connector can be connected to many connectors, but it is only supported if the multi function return true. It is not recommended that a connector support multi connections. A component can instead dynamically create connectors when needed.

A connector has a direction; up, down or any. The direction decides in which order the connectors in a component tree are connected and the structure of the tree.

Connections are setup in two steps. The first step is to add the connection, which is done using the add_destination function. Adding a connection can fail for several reasons and it is implementation dependent how the connection can fail. A connection can for instance fail because the destination object requires something that the source component did not pass when checking the connection. Just adding a connection does not mean that the components actually connect. The components have to save the data given with the add_destination function. The actual setup of the connection is made in the second step when the update function is called, which finalizes the connection.

The add_destination and remove_destination functions sets the state of the connection. It is first when the update function is called when the connection is finalized. Both add_destination and remove_destination returns true if the call was successful otherwise they return false.

Parameters to the add_destination function are the own object obj and the destination object dst_obj. The destination object must be a port object and it must implement the connector interface.

The update function is called when the component should update its current connection status. The status of the connection has previously been set using the add_destination or/and remove_destination functions.

The destination function returns a list of port objects that the its connected to. The destination function returns the state of the connection not the finalized state, i.e. the state of the connection before update functional call.

The check, connect, and disconnect functions initiates a connection setup via the connector object. The connector will forward the setup to the components affected by the connection via the component_connector interface.

The deletion_requested function is called after disconnecting components. A dynamic connector might want to return True in order to be deleted just after the disconnection.

typedef enum {
        Sim_Connector_Direction_Up,
        Sim_Connector_Direction_Down,
        Sim_Connector_Direction_Any
} connector_direction_t;

SIM_INTERFACE(connector) {
        char *(*type)(conf_object_t *obj);
        bool (*hotpluggable)(conf_object_t *obj);
        bool (*required)(conf_object_t *obj);
        bool (*multi)(conf_object_t *obj);
        connector_direction_t (*direction)(conf_object_t *obj);

        bool (*add_destination)(conf_object_t *obj, conf_object_t *connector);
        bool (*remove_destination)(conf_object_t *obj,
                                   conf_object_t *connector);
        attr_value_t (*destination)(conf_object_t *obj); /* list of
                                                            connector objects */
        void (*update)(conf_object_t *obj);

        bool (*check)(conf_object_t *obj, attr_value_t attr);
        void (*connect)(conf_object_t *obj, attr_value_t attr);
        void (*disconnect)(conf_object_t *obj);
        bool (*deletion_requested)(conf_object_t *obj);
};
#define CONNECTOR_INTERFACE "connector"

Execution Context
Global Context for all methods.

cpu_cached_instruction

Description
This interface allows registration of callbacks for individual instructions, i.e., instructions at a specific address. This interface can only be used inside a cpu_cached_instruction_cb_t callback where there is a valid ci_handle. The callback is installed by calling the register_cached_instruction_cb method in the cpu_instrumentation_subscribe interface. The signature of the callback function looks like this:

typedef void (*cpu_cached_instruction_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        cached_instruction_handle_t *ci_handle,
        instruction_handle_t *iq_handle,
        lang_void *user_data);

When the callback is installed Simics will call it every time an instruction is put into the internal instruction cache, which might have different entries for different execution modes. For example, in an unlikely case where the same instruction is executed in 32-bit mode and later in 64-bit mode (running an x86 processor for instance), this callback will be called twice, one time for each mode. This allows the user to install specific callbacks for this specific instruction and apply filtering based on instruction types, etc. This approach is more efficient than doing dynamic filtering in the instruction and read/write callbacks installed by the cpu_instrumentation_subscribe interface.

The iq_handle together with the cpu_instruction_query interface let a user examine instruction properties. The user_data is the user data for the callback.

SIM_INTERFACE(cpu_cached_instruction) {
        void (*register_instruction_before_cb)(
                conf_object_t *cpu,
                cached_instruction_handle_t *ci_handle,
                cpu_instruction_cb_t cb,
                lang_void *user_data,
                cpu_callback_free_user_data_cb_t free_cb);
        void (*register_instruction_after_cb)(
                conf_object_t *obj,
                cached_instruction_handle_t *ci_handle,
                cpu_instruction_cb_t cb,
                lang_void *user_data,
                cpu_callback_free_user_data_cb_t free_cb);
        void (*register_read_before_cb)(
                conf_object_t *obj,
                cached_instruction_handle_t *ci_handle,
                cpu_memory_cb_t cb,
                lang_void *user_data,
                cpu_callback_free_user_data_cb_t free_cb);
        void (*register_read_after_cb)(
                conf_object_t *obj,
                cached_instruction_handle_t *ci_handle,
                cpu_memory_cb_t cb,
                lang_void *user_data,
                cpu_callback_free_user_data_cb_t free_cb);
        void (*register_write_before_cb)(
                conf_object_t *obj,
                cached_instruction_handle_t *ci_handle,
                cpu_memory_cb_t cb,
                lang_void *user_data,
                cpu_callback_free_user_data_cb_t free_cb);
        void (*register_write_after_cb)(
                conf_object_t *obj,
                cached_instruction_handle_t *ci_handle,
                cpu_memory_cb_t cb,
                lang_void *user_data,
                cpu_callback_free_user_data_cb_t free_cb);
#ifndef PYWRAP
        void (*add_counter)(
                conf_object_t *obj,
                cached_instruction_handle_t *ci_handle,
                uint64 *counter,
                bool use_atomic_increment);
#endif
};

#define CPU_CACHED_INSTRUCTION_INTERFACE "cpu_cached_instruction"

The method register_instruction_before_cb installs a callback that is called before the cached instruction is executed. The ci_handle is used to bind the callback to the cached instruction. The user_data is the callback's user data, and a callback for freeing the data is also available. The free_cb looks like this:

typedef void (*cpu_callback_free_user_data_cb_t)(
        conf_object_t *obj, conf_object_t *cpu, lang_void *user_data);

It is called when Simics wants to free cached instructions, which can happen in various situations. obj is the connection object that should free the data. The callback may be NULL if not needed.

The cb callback type is the same as used for instructions in the cpu_instrumentation_subscribe interface:

typedef void (*cpu_instruction_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        instruction_handle_t *handle,
        lang_void *user_data);

The object obj is the user object that registers the callback and cpu is the processor object executing the instruction. The handle can be used to query more data about the instruction. See the cpu_instruction_query interface for more information. The user_data is the user data associated with the callback.

The user data is a convenient location for storing information about the instruction, such as user specific decode information, etc. The user data is private for each installed callback.

The cached information about the instruction is bound to its physical address so the logical address cannot typically be saved since it may vary between calls (if the MMU-mapping has changed).

register_instruction_after_cb installs a callback that is called after a cached instruction is executed. Otherwise it works in the same as the before variant. However, reading the program counter register for a control flow instruction in this callback will reflect the new location, whereas using the cpu_instruction_query for reading out the instruction address will still return the address of the control flow instruction.

register_read_before_cb installs a callback that is called before each read operation in the cached instruction. The callback is the same as used for read and writes in the cpu_instrumentation_subscribe interface:

typedef void (*cpu_memory_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        memory_handle_t *handle,
        lang_void *user_data);

As for instructions, obj is the object that registered the callback and cpu is the processor doing the access. The handle can be used to further operate on the access by using the cpu_memory_query interface. The user_data and the free_cb arguments to register_read_before_cb can be used to store user data for the read operations in the cached instruction. The user data is private for each installed callback but is shared between all read before operations in the instruction.

register_read_after_cb installs a callback that is called after each read operation in the cached instruction. The user data is private for each installed callback but is shared between all read after operations in the instruction. Otherwise it works in the same way as the before variant.

register_write_before_cb and register_write_after_cb installs callbacks that is called before and after each write operation in the cached instructions. Otherwise they work in the same way as the read variants.

Note that installing a read or write callback on an instruction without any memory operations will be useless.

The add_counter method can be used to add simple counters for this particular instruction. The counter argument is a pointer to a 64 bit counter value that will be incremented each time the instruction is executed. This is the same thing (but more efficient) as registering a callback through the register_instruction_before_cb method and increasing the counter each time it is called.

Passing true for the argument use_atomic_increment makes the increment of the counter atomic, which may be useful if the tool cannot have an instrumentation connection per processor. This will however be slower due to the nature of atomic instructions.

The location of the counter value can only be removed/deallocated after a call to either the remove_callback method (passing the cpu_cb_handle_t returned by register_cached_instruction_cb), or to the remove_connection_callbacks method (with the connection object as the argument) in the cpu_instrumentation_subscribe interface.

This method is not available in Python.

The instrumentation_order interface cannot be used to reorder callbacks installed with the cpu_cached_instruction interface. The cached callbacks are always called in same order as the cpu_cached_instruction_cb_t callback that installed them, and before any callback installed by the corresponding methods in the cpu_instrumentation_subscribe.

Execution Context
Threaded Context for all methods, but must be called from a callback registered by the register_cached_instruction_cb method in the cpu_instrumentation_subscribe interface.

cpu_cached_instruction_once

Description
This interface extends the cpu_cached_instruction interface and allows callbacks to be installed that trigger only once, i.e., after the first time they have been invoked they are automatically removed. Otherwise they are identical to the corresponding methods in the cpu_cached_instruction interface.

SIM_INTERFACE(cpu_cached_instruction_once) {
        void (*register_instruction_before_once_cb)(
                conf_object_t *cpu,
                cached_instruction_handle_t *ci_handle,
                cpu_instruction_cb_t cb,
                lang_void *user_data,
                cpu_callback_free_user_data_cb_t free_cb);
        void (*register_instruction_after_once_cb)(
                conf_object_t *cpu,
                cached_instruction_handle_t *ci_handle,
                cpu_instruction_cb_t cb,
                lang_void *user_data,
                cpu_callback_free_user_data_cb_t free_cb);
};

#define CPU_CACHED_INSTRUCTION_ONCE_INTERFACE "cpu_cached_instruction_once"

Execution Context
Threaded Context for all methods, but must be called from a callback registered by the register_cached_instruction_cb method in the cpu_instrumentation_subscribe interface.

cpu_cached_stream

Description
This interface is internal.
Execution Context
Threaded Context for all methods, but must be called from a callback registered by the register_cached_instruction_cb method in the cpu_instrumentation_subscribe interface.

cpu_exception_query

Description
The cpu_exception_query interface is used to query information about an exception for the a generic cpu architecture and should be used from a cpu_exception_cb_t callback.

SIM_INTERFACE(cpu_exception_query) {
        int (*exception_number)(conf_object_t *cpu, exception_handle_t *handle);
        logical_address_t (*fault_pc)(conf_object_t *cpu,
                                      exception_handle_t *handle);
};
#define CPU_EXCEPTION_QUERY_INTERFACE "cpu_exception_query"

exception_number is used to get the vector for the exception.

Execution Context
Threaded Context for all methods, but must be called from a callback receiving a handle of type exception_handle_t.

cpu_instruction_decoder

Description
This interface is used to replace an existing instruction with a user defined one or add new instructions to the simulation. The interface can only be used from a cpu_instruction_decoder_cb_t callback registered by the register_instruction_decoder_cb method in the cpu_instrumentation_subscribe interface.

The interface consist of just one method and looks like this:

SIM_INTERFACE(cpu_instruction_decoder) {
        void (*register_emulation_cb)(conf_object_t *cpu,
                                      cpu_emulation_cb_t cb,
                                      decoder_handle_t *handle,
                                      lang_void *user_data,
                                      cpu_callback_free_user_data_cb_t free_cb);
};

#define CPU_INSTRUCTION_DECODER_INTERFACE "cpu_instruction_decoder"

register_emulation_cb is used to set a callback function that implements the semantics of the new or changed instruction. Every time the instructions is executed on the cpu this function will be called instead of the build-in implementation. The handle is the decoder_handle_t handle passed to the cpu_instruction_decoder_cb_t callback. The user_data argument is user data for the callback. The free_cb is a clean-up callback function that Simics calls when the instruction is overwritten or if Simics wants to flush decoding caches. This function should deallocate any the user data if present. Can be NULL if not used.

The signature of the emulation callback looks like this:

typedef cpu_emulation_t (*cpu_emulation_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        lang_void *user_data);

obj is the connection object, the same object as passed to the cpu_instruction_decoder_cb_t callback. cpu is the processor executing the replaced instruction. user_data is user data for the emulation callback. This is a useful place for storing immediate or register values for the new instruction. In the emulation function the whole Cell Context API is available for use.

CPU_Emulation_Fall_Through should be returned from the emulation callback if replaced one is a fall through instruction. The program counter does not need to be updated. If the replaced instruction is doing any control flow then CPU_Emulation_Control_Flow should be returned and the program counter should be set to the destination address. This can be done for fall through instruction as well but is less efficient.

CPU_Emulation_Default_Semantics can also be returned to indicate that the default semantics should be used instead of the user defined. This can be useful if the instruction only should be replaced under certain circumstances.

Execution Context
Threaded Context for all methods, but must be called from a callback registered by the register_instruction_decoder_cb method in the cpu_instrumentation_subscribe interface.

cpu_instruction_query

Description
The cpu_instruction_query interface can be used in functions of the following types:

  • cpu_instruction_cb_t
  • cpu_cached_instruction_cb_t
  • cpu_instruction_decoder_cb_t

where an instruction_handle_t pointer is available. The handle is only valid in the callback. The interface is used to request information about the instruction being executed by the processor cpu.

SIM_INTERFACE(cpu_instruction_query) {
        logical_address_t (*logical_address)(
                conf_object_t *cpu, instruction_handle_t *handle);
        physical_address_t (*physical_address)(
                conf_object_t *cpu, instruction_handle_t *handle);
        cpu_bytes_t (*get_instruction_bytes)(
                conf_object_t *cpu, instruction_handle_t *handle);
        bool (*is_existing_instruction)(
                conf_object_t *cpu, instruction_handle_t *handle);
};

#define CPU_INSTRUCTION_QUERY_INTERFACE "cpu_instruction_query"

The logical_address and physical_address is used to get the different addresses of the instruction being executed.

Note that if the instruction crosses a page boundary the last part of the instruction will have a different mapping for the physical address than returned by physical_address. To get hold of the physical address on the second page, use the logical_to_physical method of the processor_info(_v2) and provide the logical address of the first byte on the second page.

The get_instruction_bytes method is used to read the instruction bytes. The returned data is of a cpu_bytes_t type that contains the data and the size. The data member is only available during the execution of the callback. The data cannot be changed. Corresponding type in Python is a string of bytes.

typedef struct cpu_bytes {
        size_t size;
#ifndef PYWRAP
        const uint8 *data;
#endif
} cpu_bytes_t;

The is_existing_instruction method is used to determine if Simics managed to decode the instruction bytes. Note that despite this method returning false could imply that the instruction is implemented using a user supplied implementation through the x86_instrumentation_subscribe interface.

Additional information can be read out with an architectural specific query interface, see x86_instruction_query for details.

Execution Context
Threaded Context for all methods, but must be called from a callback receiving a handle of type instruction_handle_t.

cpu_instrumentation_subscribe

Description
The cpu_instrumentation_subscribe interface is implemented by processor classes that support CPU instrumentation. The interface can be used to monitor and instrument various actions through callbacks. It is designed for being more efficient than haps and will not synchronize any threads. This means that any user of the interface must assume that registered callbacks can be called in parallel by multiple threads if any of the multi-threaded execution modes are used in Simics.

A processor implementing the interface is regarded as a provider of instrumentation and is typically used by an instrumentation tool object. The tool object is supposed to register callbacks in this interface and act when they are called. To handle different threads it is recommended that the tools uses a connection object (a sub-object created by the tool) that registers these callbacks for each processor that it monitors. Then, any data collected can be stored in these connection objects and will thus not be subject to concurrent access from different threads that hosts the processors. The data can than be aggregated by the tool when appropriate. This approach needs no synchronization locks and allows for efficient simulation.

See instrumentation_order interface for more details on the callback order.

The cpu argument in all methods below is the processor object implementing this interface.

The connection argument is the "user" object of this interface, typically a connection object as described above. However, it can be any object and even NULL if there is no suitable object to pass. For instance, if the callback is registered by a Python script. In this case synchronization will be handled by the Python layer.

All registration methods in the interface install at least one callback, the cb argument, that will be called at a particular instrumentation point in the processor object. The Simics Cell Context API is available for use in these callbacks. The callbacks have different signatures depending on their use case. The data argument is user defined data that can be associated with each callback. Every time the callback is called this data will be passed as an argument to the callback. The data can be unique for each registration, even though the same callback pointer is used.

Note: Note, not all CPU models implement all parts of the instrumentation API. Register methods not implemented in this interface will be NULL.
SIM_INTERFACE(cpu_instrumentation_subscribe) {
        /* Callback specific methods */
        void (*remove_callback)(
                conf_object_t *NOTNULL cpu,
                cpu_cb_handle_t *handle);
        void (*enable_callback)(
                conf_object_t *NOTNULL cpu,
                cpu_cb_handle_t *handle);
        void (*disable_callback)(
                conf_object_t *NOTNULL cpu,
                cpu_cb_handle_t *handle);

        /* Callback groups methods, operating on several callbacks 
           associated to a connection. */
        void (*remove_connection_callbacks)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *NOTNULL connection);
        void (*enable_connection_callbacks)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *NOTNULL connection);
        void (*disable_connection_callbacks)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *NOTNULL connection);

        /* Subscribe methods */
        cpu_cb_handle_t *(*register_instruction_before_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_instruction_cb_t cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_instruction_after_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_instruction_cb_t cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_read_before_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_access_scope_t scope,
                cpu_memory_cb_t cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_read_after_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_access_scope_t scope,
                cpu_memory_cb_t cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_write_before_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_access_scope_t scope,
                cpu_memory_cb_t cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_write_after_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_access_scope_t scope,
                cpu_memory_cb_t cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_address_before_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_address_cb_t cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_cached_instruction_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_cached_instruction_cb_t cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_instruction_decoder_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_instruction_decoder_cb_t cb,
                cpu_instruction_disassemble_cb_t disass_cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_exception_before_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                int exception_number,
                cpu_exception_cb_t cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_exception_after_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                int exception_number,
                cpu_exception_cb_t cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_exception_return_before_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_exception_return_cb_t cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_exception_return_after_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_exception_return_cb_t cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_mode_change_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                cpu_mode_change_cb_t cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_control_register_read_before_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                int register_number,
                cpu_control_register_read_cb_t cb,
                lang_void *data);
        cpu_cb_handle_t *(*register_control_register_write_before_cb)(
                conf_object_t *NOTNULL cpu,
                conf_object_t *connection,
                int register_number,
                cpu_control_register_write_cb_t cb,
                lang_void *data);
};
        
#define CPU_INSTRUMENTATION_SUBSCRIBE_INTERFACE \
        "cpu_instrumentation_subscribe"

Callback Related Methods

Every function in this interface that registers a callback returns a unique handle of type cpu_cb_handle_t. The remove_callback method removes the callback associated with the handle. The enable_callback and disable_callback methods can be used to temporarily enable and disable a callback.

The remove_connection_callbacks removes all callbacks associated with a connection object, i.e., all the callbacks that was registered with the same connection object. The enable_connection_callbacks and disable_connection_callbacks enables and disables all callbacks associated with a connection object. NULL cannot be passed to these methods to handle callbacks installed without any connection object.

The design philosophy is that registering and removing a callback can be relatively expensive, whereas enable and disable a callback should be cheap. On the other hand, a disabled callback can slow down the simulation speed a bit more compared to running without callbacks.

Instruction Related Methods

The method register_instruction_before_cb installs a callback that is called before an instruction is executed. The callback type is as follows:

typedef void (*cpu_instruction_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        instruction_handle_t *handle,
        lang_void *user_data);

The object obj is the connection or the user object that registers the callback (or NULL if there is no object) and cpu is the processor object executing the instruction. If a dedicated connection object associated with each processor is used, the object's private data can store the interface pointers needed to access processor state. This is a useful trick to speed up the simulation speed. Otherwise such interface pointers need to be acquired each time the callback is called. If no connection object is used the pointers can be saved in the callback's user data. The handle can be used to query more data about the instruction, using the cpu_instruction_query interface. The user_data is the user data associated with the callback.

The registered callback is called for every instruction type. Use the register_cached_instruction_cb method to control which type of instructions that should be instrumented.

register_instruction_after_cb installs a callback that is called after an instruction is executed. The callback is of the same type as for the before variant and is called for every instruction type. Use the register_cached_instruction_cb method to control which type of instructions that should be instrumented. Reading the program counter register for a control flow instruction in this callback will reflect the new location, whereas using the cpu_instruction_query for reading out the instruction address will still return the address of the control flow instruction.

None: When an exception occurs the instruction is aborted and any installed callbacks by the register_instruction_after_cb method are not called.


Memory Related Methods

register_read_before_cb installs a callback that is called before a memory read operation is performed. The callback type is as follows:

typedef void (*cpu_memory_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        memory_handle_t *handle,
        lang_void *user_data);

As for instructions, obj is the object that registered the callback and cpu is the processor doing the access. The handle can be used to further operate on the access by using the cpu_memory_query interface. The interface can for instance be used to read the data of the memory operation. For more information, see the documentation for the cpu_memory_query interface.

The scope argument defines the access scope for the callback. There are two defined scopes: CPU_Access_Scope_Explicit and CPU_Access_Scope_Implicit. The explicit scope installs a callback for every operation done explicitly by an instruction, such as loading or storing a value. The implicit scope installs a callback for every implicit access, such as table walks or memory accesses performed by exception and interrupt handling. If all accesses are requested the same callback function can be registered for both scopes by registering the callback twice, one for each scope.

If a memory access crosses a page boundary the access will be split into two separate calls, one for the first part covering the first page, and one for the second part covering the second page. See the get_page_crossing_info method in the cpu_memory_query interface for a way to distinguish the different cases.

The user_data is the data associated with the callback.

Similar to register_read_before_cb, the following three methods work in the same way:

register_read_after_cb installs a callback that is called after a memory read operation is performed.

register_write_before_cb installs a callback that is called before a memory write operation is performed.

register_write_after_cb installs a callback that is called after a memory write operation is performed.

Memory accesses of prefetch types or any other control operation calls the read callbacks. To distinguish them from reads an architecture specific interface can be used to lookup the access type. See the x86_memory_query interface for example.

None: When an exception occurs the instruction is aborted and any installed memory callbacks after this point are not called.


Addresses

Note: Only available on x86 targets.
register_address_before_cb can be used to register a callback that will be called each time a logical address is generated by an instruction for an explicit read or a write operation. This occurs before the actual memory operation takes place. This allows a user to inspect and change the target address for the operation. The callback has the following signature:

typedef logical_address_t (*cpu_address_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        logical_address_t address,
        address_handle_t *handle,
        lang_void *user_data);

The argument obj is the object installing the callback and the cpu is the processor generating the logical address. The handle can be used to extract more information about the address by using an architecture specific interface. See the x86_address_query for details.

The new logical address should be returned by the callback.


Cached Instructions

register_cached_instruction_cb is used for installing a callback that is called every time Simics inserts the instruction into an internal instruction cache, i.e., executing from a specific address with a specific execution mode for the first time. Executing the instruction again will typically not invoke the callback since the instruction is already placed in the instruction cache. However, if the cache is flushed and the instruction is executed again the callback will once again be called. The callback has the following signature:

typedef void (*cpu_cached_instruction_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        cached_instruction_handle_t *ci_handle,
        instruction_handle_t *iq_handle,
        lang_void *user_data);

From this callback one can use the cpu_cached_instruction interface and ci_handle to register instrumentation callbacks for this specific instruction alone. The installed callbacks will be called every time the instruction is executed (even the first time just after the cpu_cached_instruction_cb_t callback has returned). This means that the user can filter out certain instructions of interest and instrument only those. The iq_handle and the cpu_instruction_query interface can be use to do the filtering by examining the instruction. The user_data is the callback user data for the callback.

For callbacks registered for memory operations only those in the explicit scope issued by the instruction will be instrumented, e.g., hardware table walks and exceptions will not be considered by this method. To instrument these operations use the register_(read/write)_(before/after)_cb with the implicit scope instead.

If no callbacks are registered by calling the cpu_cached_instruction interface, the instruction will not be instrumented.


Instruction Set Augmentation

register_instruction_decoder_cb lets the user redefine instruction semantics in Simics, or implement new instructions. The cb argument is a callback function that will be called every time Simics decodes an instruction. From this callback the user can accept the instruction or deny it. In most cases this only happens once per instruction address since Simics usually caches decoding results in the internal instruction cache. If the cache is flushed the callback may be called again.

The callback signature looks like this:

typedef int (*cpu_instruction_decoder_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        decoder_handle_t *decoder_handle,
        instruction_handle_t *iq_handle,
        lang_void *user_data);

The instruction bytes are read by using the get_instruction_bytes method of the cpu_instruction_query interface together with the iq_handle. The returned value is of a cpu_bytes_t type. To access the bytes use the data and the size members in the returned value.

If the decoder requires more bytes (i.e., because the new instruction is longer), a negative integer value should be returned by the cb function, indicating the number of bytes needed. For example, if the available bytes are 3 but the decoder need at least 4 bytes, -4 should be returned. The callback will then be called again with more available bytes (this can be repeated if the new instruction requires even more bytes at this point). Note that requesting more data than actual needed can cause spurious page faults if the data crosses a page boundary.

If the instruction is accepted by the callback a positive integer number should be returned corresponding to the length of the instruction. In this case the register_emulation_cb method of the cpu_instruction_decoder interface should be called to set the actual (user) function that Simics will call each time the instruction is executed.

If the cb callback should ignore the instruction the number 0 should be returned. This means that any other registered decoder will have a chance to decode the instruction. If no decoder accepts it, Simics' default implementation will be used.

The register_emulation_cb method also needs the decoder_handle which is available in the dedoder callback. For more information, see the documentation of the cpu_instruction_decoder interface.

A disass_cb argument should also be passed to the register_instruction_decoder_cb method. This function is called every time Simics wants to disassemble an instruction. For every accepted instruction a corresponding disassembly string should be returned by this function. It has the following signature:

typedef tuple_int_string_t (*cpu_instruction_disassemble_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        generic_address_t addr,
        cpu_bytes_t bytes);

obj is the object registering the register_instruction_decoder_cb and cpu is the processor disassembling the instruction. addr is the address of the instruction in a generic form. This means that it is typically a physical address or a logical address depending on the context of the disassembling. The address can be used for offset calculations, i.e., displaying an absolute address instead of a relative one, for example in a branch instruction. The bytes argument should be used to read instruction bytes. The return value is of type tuple_int_string_t and should be filled with the instruction length and an allocated (e.g., malloc) string representing the disassembly of the instruction. The ownership of the string is transferred to the calling environment which will free it when it is no longer needed.

If too few bytes are passed for the instruction to be disassembled a negative value should be returned for the length indicating the needed bytes. The disass_cb is then called again with more bytes. If the instruction is rejected a length of 0 should be returned and the string should be set to NULL.


Exception Related Methods

register_exception_before_cb is used to register a callback that will be called before an exception or interrupt is taken. The exception_number can be used to select a callback on a specific exception, with the same number as used in the exception interface. If all exceptions should be subscribed to, the CPU_Exception_All constant can be used. The callback signature looks like this:

typedef void (*cpu_exception_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        exception_handle_t *exception_handle,
        lang_void *user_data);

The obj is the object registering the callback and cpu is the processor that takes the exception or receives the interrupt. The handle is used to get more architectural information about the exception, for example, see the x86_exception_query for details. The user_data is the callback user data.

No architectural state has been changed in this callback to reflect the exception or interrupt, e.g., the program counter will still be at the faulting instruction. Since an exception can occur while handling an exception it is not always the case that this callback corresponds to the final taken exception. Recursive exception will result in another call to this callback.

register_exception_after_cb is used to register a callback that will be called after an exception was taken. It takes the same arguments as register_exception_before_cb. In this callback the architectural state has been updated, e.g., the program counter points to the first instruction of the exception handler. The callback is of the same type as for the before variant.

register_exception_return_before_cb is used to register a callback that will be called just before an exception handler is done and resumes execution of the normal program code. The callback signature looks like this:

typedef void (*cpu_exception_return_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        exception_return_handle_t *exception_handle,
        lang_void *user_data);

The obj is the object registering the callback and cpu is the processor that takes the exception or receives an interrupt. The handle is used to get more architectural information about the exception. Currently there is no interface available for this.

register_exception_return_after_cb is used to register a callback that will be called after an exception has been executed, e.g., the program counter points to the normal program where execution will continue.


Execution Mode

register_mode_change_cb is used to register a callback that will be called every time the processor changes mode. The supported modes are: user, supervisor, and hypervisor.

The callback signature looks lite this:

typedef void (*cpu_mode_change_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        processor_mode_t old_mode, processor_mode_t new_mode,
        lang_void *user_data);

The obj is the object registering the callback and cpu is the processor that changes mode. The old_mode is the mode before the change and new_mode is the mode after the change.


Control Registers

register_control_register_read_before_cb is used to register a callback that will be called before every control register read. The register_number is the control register number to install the callback on. It is the same number which is used in the int_register interface. The constant CPU_Control_Register_All can be used to subscribe to all control registers.

The callback signature looks like this:

typedef void (*cpu_control_register_read_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        int register_number,
        lang_void *user_data);

The obj is the object registering the callback and cpu is the processor that reads the control register register_number. The user_data is the user data for the callback.

register_control_register_write_before_cb is used to register a callback that will be called before every control register write. The register_number is the control register number to install the callback on. It is the same number which is used in the int_register interface. The constant CPU_Control_Register_All can be used to subscribe to all control registers.

The callback signature looks like this:

typedef void (*cpu_control_register_write_cb_t)(
        conf_object_t *obj, conf_object_t *cpu,
        int register_number,
        uint64 value,
        lang_void *user_data);

The obj is the object registering the callback and cpu is the processor that writes to the control register register_number. The value is the value that will be written. The user_data is the user data for the callback.

Execution Context
Global Context for all methods.

cpu_memory_query

Description
The cpu_memory_query interface is used by callbacks of the cpu_memory_cb_t type and requires a valid memory_handle_t handle. The handle is only valid during the call of the callback. It is used to request information about the memory operation being issued by the processor cpu.

SIM_INTERFACE(cpu_memory_query) {
        logical_address_t (*logical_address)(
                conf_object_t *cpu, memory_handle_t *handle);
        physical_address_t (*physical_address)(
                conf_object_t *cpu, memory_handle_t *handle);
#ifndef PYWRAP
        void (*set_host_ptr)(
                conf_object_t *cpu, memory_handle_t *handle,
                void *p);
#endif
        cpu_bytes_t (*get_bytes)(conf_object_t *cpu,
                                 memory_handle_t *handle);

        void (*set_bytes)(
                conf_object_t *cpu, memory_handle_t *handle,
                cpu_bytes_t bytes);

        bool (*atomic)(
                conf_object_t *obj, memory_handle_t *handle);
        ini_type_t (*arch)(
                conf_object_t *obj, memory_handle_t *handle);
        page_crossing_info_t (*get_page_crossing_info)(
                conf_object_t *obj, memory_handle_t *handle);
        buffer_t (*get_surrounding_bytes)(
                conf_object_t *cpu, memory_handle_t *handle,
                unsigned granularity_log2);
        
};

#define CPU_MEMORY_QUERY_INTERFACE "cpu_memory_query"        

The logical_address and physical_address methods are used to get the different addresses of the memory operation.

Below, callbacks registered by the register_read_before_cb or the register_write_before_cb in the cpu_instrumentation_subscribe interface or in the cpu_cached_instruction interface are referred to as being in before context. Callbacks registered by the register_read_after_cb or the register_write_after_cb in the cpu_instrumentation_subscribe interface or in the cpu_cached_instruction interface are referred to as being in after context.

The set_host_ptr method can be used to redirect where data should be read from or written to depending on if it is a read or a write operation. The method is only useful for callbacks registered in before context. The data pointer p needs to be valid during the execution of the instruction and must point to enough space to carry out the operation. This method is not available in Python.

The get_bytes method is used to retrieve the bytes that is going to be read/written if called in a before context and is used to read out value that was read/written in after context. The value is returned as cpu_bytes_t:

typedef struct cpu_bytes {
        size_t size;
#ifndef PYWRAP
        const uint8 *data;
#endif
} cpu_bytes_t;

The member data contains the data pointer, and the member size contains tha size of the data. It is illegal to access beyond the limit. For such access, see the get_surrounding_bytes below.

The read value in before context may not be available (a device access for example) and in this case the data member will be NULL.

The set_bytes method is used to override the bytes to be read or written. The method is only valid in the before context. This method can be used instead of the set_host_ptr to change the value of the operation. The value is passed as cpu_bytes_t and the supplied data in the data member need not to be valid after the callback returns since the data is copied. The length of the data cannot be changes and must be the same as returned by the get_bytes method.

The atomic method returned true if the operation is considered atomic, false otherwise.

The arch method returns the ini_type_t of the memory operation.

Accesses that cross a page boundary are split into two subsequent accesses, one for the first page and one for the second page. The get_page_crossing_info method can be used to distinguish the different cases from each other. The returned value from the method is of type page_crossing_info_t and can be one of: Sim_Page_Crossing_None (no crossing access), Sim_Page_Crossing_First (first part of a crossing access), or Sim_Page_Crossing_Second (second part of a crossing access).

The get_surrounding_bytes method provides quick access to the data surrounding the access. The granularity_log2 specifies the size and alignment of the buffer being returned. For example using 6 for granularity_log2, will fetch 64 aligned bytes around the address of the access. Typically, the largest supported granularity_log2 size is 12, meaning a 4 KiB page. The returned value is of type buffer_t and is only valid in the cpu_memory_cb_t callback. The data can be accessed by using the buffer_t.data member in the returned value. Data can only be read up to the size of the buffer, which is stored in the buffer_t.len member. Valid memory is only returned if the access terminates in simulator cached memory. If not, the buffer_t.len will be is 0, buffer_t.data cannot be used.

Additional information can be read out with an architectural specific query interface, see x86_memory_query interface for details.

Execution Context
Threaded Context for all methods, but must be called from a callback receiving a handle of type memory_handle_t.

cycle

Description
Interface Methods
The cycle interface is typically implemented by processors, but can be implemented by other objects as well. Its purpose is to handle events based on time. The cycle queue has a cycle as the smallest time unit. The cycle queue also has an associated frequency which makes it possible to define events based on seconds or picoseconds.

The get_frequency function returns the frequency in Hertz for the queue. Most objects implementing cycle also have a notification mechanism for frequency changes through the simple_dispatcher interface in the cpu_frequency port. It is recommended that such a notification mechanism is used to get updates rather than polling with get_frequency.

The current number of cycles executed by the queue is returned by get_cycle_count. Time elapsed since the queue was created is returned by get_time (in seconds) and get_time_in_ps (in picoseconds); this will be equal to the value returned by get_cycle_count divided by the value returned by get_frequency if the frequency has been constant since time zero.

The cycles_delta function returns the highest number of cycles obj can run before it passes the absolute local time when, assuming no frequency change occurs in the meantime. Note that cycles_delta can raise an exception if when was too far ahead in the future. The cycles_delta_from_ps function performs the same function, for an absolute local time expressed in picoseconds.

The post_cycle function will schedule an event that will occur after cycles counted from local current time at queue. The post_time function is similar but takes seconds as argument, while post_time_in_ps takes a number of picoseconds. The arguments cycles, seconds and picoseconds must be nonnegative.

An event previously posted can be removed by calling cancel. The cancel function takes a function pred as argument which is called when a matching event is found. The event is only removed if pred returns 1.

The find_next_cycle, find_next_time and find_next_time_as_ps functions take the same arguments as cancel but only return the number of cycles, seconds or picoseconds before the event occur. The evclass is the event class, obj is the object posting the event, and user_data is pointer to data used as a parameter when calling the callback function defined in the evclass. If no matching event was found, find_next_cycle and find_next_time return −1; find_next_time_as_ps returns ILLEGAL_DURATION.

The events method returns a list of all pending events in expiration order. Each element is a four-element list containing the event object, the event class name, the expiration time counted in cycles as an integer and the event description as given by the event class describe method, or NIL for events whose event class does not define that method.

What happens to already posted events when a frequency change occurs is implementation dependent. Simics processors will scale the cycle queue to keep the time left before triggering events equal across the frequency change. Note that the new times will be rounded to entire cycles during the scaling, so approximations may occur when switching between high and low frequencies.

Implementation
It is implementation dependent how the queue is implemented, whether cycles or seconds are used as underlying time unit, and what happens when the frequency is changed.

Objects implementing the cycle interface are usually meant to be scheduled by Simics itself. For this to happen, a number of conditions must be fulfilled:

  • Each schedulable object implementing the cycle interface must be controlled by an object implementing the execute interface. It can be the same object that implements the execute interface. The object implementing the execute interface points to the object implementing the cycle interface via its queue attribute.
  • Any schedulable object implementing the cycle interface must inform Simics about changes in frequency by calling the VT_clock_frequency_change function. That also applies to the initial frequency set when the object is created.
  • For schedulable objects, the cycle interface must be registered with SIM_register_clock, which will also add some Simics specific attributes to the corresponding class. Beyond those, the implementor of the cycle can use any checkpoint representation. The name field in the event class data structure is unique, and the attribute setter function for checkpoint restore can use SIM_get_event_class to get the event class structure corresponding to an event class name.

SIM_INTERFACE(cycle) {

        cycles_t (*get_cycle_count)(conf_object_t *queue);
        double (*get_time)(conf_object_t *queue);
        cycles_t (*cycles_delta)(conf_object_t *NOTNULL clock,
                                 double when);

        uint64 (*get_frequency)(conf_object_t *queue);

        void (*post_cycle)(
                conf_object_t *NOTNULL queue,
                event_class_t *NOTNULL evclass,
                conf_object_t *NOTNULL obj,
                cycles_t cycles,
                lang_void *user_data);
        void (*post_time)(
                conf_object_t *NOTNULL queue,
                event_class_t *NOTNULL evclass,
                conf_object_t *NOTNULL obj,
                double seconds,
                lang_void *user_data);

        void (*cancel)(
                conf_object_t *NOTNULL queue,
                event_class_t *NOTNULL evclass,
                conf_object_t *NOTNULL obj,
                int (*pred)(lang_void *data, lang_void *match_data),
                lang_void *match_data);

        cycles_t (*find_next_cycle)(
                conf_object_t *NOTNULL queue,
                event_class_t *NOTNULL evclass,
                conf_object_t *NOTNULL obj,
                int (*pred)(lang_void *data, lang_void *match_data),
                lang_void *match_data);

        double (*find_next_time)(
                conf_object_t *NOTNULL queue,
                event_class_t *NOTNULL evclass,
                conf_object_t *NOTNULL obj,
                int (*pred)(lang_void *data, lang_void *match_data),
                lang_void *match_data);

        attr_value_t (*events)(conf_object_t *NOTNULL obj);

        /* new picoseconds based functions */
        local_time_t (*get_time_in_ps)(conf_object_t *queue);
        cycles_t (*cycles_delta_from_ps)(conf_object_t *NOTNULL clock,
                                         local_time_t when);
        void (*post_time_in_ps)(
                conf_object_t *NOTNULL queue,
                event_class_t *NOTNULL evclass,
                conf_object_t *NOTNULL obj,
                duration_t picoseconds,
                lang_void *user_data);

        duration_t (*find_next_time_in_ps)(
                conf_object_t *NOTNULL queue,
                event_class_t *NOTNULL evclass,
                conf_object_t *NOTNULL obj,
                int (*pred)(lang_void *data, lang_void *match_data),
                lang_void *match_data);
};

#define CYCLE_INTERFACE "cycle"

Execution Context
Cell Context for all methods.

cycle_control

Description
The cycle_control interface is typically for controlling a cycle counter with event posting capabilities.

The initiator object should call start or stop to start/stop the counting of cycles. And use set_cycle_count is used to configure the current cycle count at the target object.

SIM_INTERFACE(cycle_control) {
        void (*stop)(conf_object_t *NOTNULL obj);
        void (*start)(conf_object_t *NOTNULL obj);
        void (*set_cycle_count)(conf_object_t *NOTNULL obj,
                                cycles_t cycle_count);
};
#define CYCLE_CONTROL_INTERFACE "cycle_control"

Execution Context
Cell Context for all methods.

cycle_event

Description
TODO: document the cycle_event interface.

SIM_INTERFACE(cycle_event) {
        cycles_t (*cycles)(conf_object_t *NOTNULL obj);
        void (*post)(conf_object_t *NOTNULL obj,
                     const event_class_t *NOTNULL evclass,
                     conf_object_t *NOTNULL ev_obj,
                     cycles_t cycles,
                     lang_void *param);

        void (*cancel)(conf_object_t *NOTNULL obj,
                       const event_class_t *NOTNULL evclass,
                       conf_object_t *NOTNULL ev_obj,
                       int (*pred)(lang_void *data, lang_void *match_data),
                       lang_void *match_data);

        cycles_t (*lookup)(conf_object_t *NOTNULL obj,
                           const event_class_t *NOTNULL evclass,
                           conf_object_t *NOTNULL ev_obj,
                           int (*pred)(lang_void *data, lang_void *match_data),
                           lang_void *match_data);

        attr_value_t (*events)(conf_object_t *NOTNULL obj);
};
#define CYCLE_EVENT_INTERFACE "cycle_event"

Execution Context
Cell Context for all methods.

cycle_event_instrumentation

Description
This interface is internal.
Execution Context
Global Context.

decoder

Description

SIM_INTERFACE(decoder) {
        void (*register_decoder)(conf_object_t *obj, 
                                 decoder_t *NOTNULL decoder);
        void (*unregister_decoder)(conf_object_t *obj, 
                                   decoder_t *NOTNULL decoder);
};

The decoder interface is implemented by processors that allows connecting user decoders. This allows a user to implement the semantics of instructions that are not available in the standard Simics model or change the semantics of instructions implemented by Simics. This interface replaces SIM_register_arch_decoder and SIM_unregister_arch_decoder functions.

The register_decoder function adds a decoder and unregister_decoder removes a decoder.

The decoder is installed/removed for every object of the same class as the obj argument which must be the same object from which the interface was fetched.

When Simics decodes an instruction, it will first see if any instruction decoders are registered for the current CPU class. For any decoders it finds, Simics will let it try to decode the instruction. The decoders are called in order, starting with the last registered decoder, and if one decoder accepts the instruction, the rest of the decoders will not be called.

The decoder is specified by the decoder_t data structure that the user supplies:

typedef struct {
        void *user_data;
        int (*NOTNULL decode)(uint8 *code,
                              int valid_bytes,
                              conf_object_t *cpu,
                              instruction_info_t *ii,
                              void *user_data);
        tuple_int_string_t (*NOTNULL disassemble)(uint8 *code,
                                                  int valid_bytes,
                                                  conf_object_t *cpu,
                                                  void *user_data);
        int (*NOTNULL flush)(instruction_info_t *ii,
                             void *user_data);
} decoder_t;

The decode function is called to decode an instruction pointed to by code. The first byte corresponds to the lowest address of the instruction in the simulated memory. valid_bytes tells how many bytes can be read. The CPU is given in the cpu parameter. When the decoder has successfully decoded an instruction, it should set the ii_ServiceRoutine, the ii_Arg, and the ii_Type members of the ii structure (see below), and returns the number of bytes used in the decoding. If it does not apply to the given instruction, it should return zero. If the decoder needs more data than valid_bytes it should return a negative number corresponding to the total number of bytes it will need to continue the decoding. The underlying architecture limits the number of bytes that can be requested, e.g. no more than 4 bytes can be requested on most RISC architectures. Simics will call the decoder again when more bytes are available. This process is repeated until the decoder accepts or rejects the instruction. A decoder should never request more data than it needs. For example, if an instructions can be rejected by looking at the first byte, the decoder should never ask for more bytes.

The instruction_info_t is defined as follows:

typedef struct instruction_info {
        service_routine_t  ii_ServiceRoutine;
        uint64             ii_Arg;
        unsigned int       ii_Type;
        lang_void         *ii_UserData;
        logical_address_t  ii_LogicalAddress;
        physical_address_t ii_PhysicalAddress;
} instruction_info_t;

ii_ServiceRoutine is a pointer to a function that will be called by Simics every time the instruction is executed. It has the following prototype:

typedef exception_type_t (*service_routine_t)(conf_object_t *cpu, 
                                              uint64 arg,
                                              lang_void *user_data);

The service routine function should return an exception when it is finished to signal its status. If no exception occurs Sim_PE_No_Exception should be returned.

See exception_type_t in src/include/simics/base/memory.h for the different exceptions available.

A special return value, Sim_PE_Default_Semantics, can be returned; this signals Simics to run the default semantics for the instruction. This is useful if the semantics of an instruction should be changed but the user routine does not want to handle it all the time.

Note that in a shared memory multiprocessor, the CPU used in decoding may differ from the CPU that executes the instruction, since the decoded instructions may be cached.

ii_Arg is the argument arg that will be passed on to the service routine function. Op code bit-fields for the instruction such as register numbers or intermediate values can be stored here. The ii_UserData field can also be used to pass information to the service routine if more data is needed.

ii_Type is either UD_IT_SEQUENTIAL or UD_IT_CONTROL_FLOW. A sequential type means that the instruction does not perform any branches and the update of the program counter(s) is handled by Simics. In a control flow instruction on the other hand it is up to the user to set the program counter(s).

ii_LogicalAddress and ii_PhysicalAddress holds the logical and physical addresses of the instruction to be decoded.

The disassemble function is called to disassemble an instruction. It uses the same code, valid_bytes, and cpu parameters as the decode function. If the disassembly is valid, then the string part of the returned tuple_int_string_t struct should be a MALLOCed string with the disassembly and the integer part should be its length in bytes. The caller is responsible for freeing the disassembly string. The string member should be NULL and the integer part should be zero if the disassembly is not valid. If the disassemble function needs more data than valid_bytes it should return a negative number in the integer part in the same way as the decode function, and set the string part to NULL.

The flush function is called to free any memory allocated when decoding an instruction and any user data associated with the instruction. It should return zero if it does not recognize the instruction, and non-zero if it has accepted it. Usually, the way to recognize if a decoded instruction is the right one to flush is to compare ii->ii_ServiceRoutine with the function that was set in the decode function. Note that the cpu parameter is the processor that caused the flush. It is more or less an arbitrary processor and should be ignored.

In addition to the function pointers, the decoder_t structure contains a user_data pointer that is passed to all the functions. This can be used for passing any data to the decoder functions.

Execution Context
Cell Context for all methods.

describe_registers

Description
This interface is used by the Simics debugger to get certain information from a processor.

The first_child function returns the first description in the sequence of child descriptions of parent or NULL if parent has no children. Groups can have both registers and groups as children, registers can only have fields as children and fields cannot have any children. If parent is NULL, return the first description in the sequence of top-level descriptions.

Use next_description to deallocate the previous description and return the next description in the sequence or NULL if there are no more descriptions in the current sequence.

The free_description function is used to free the description without returning the next one in the sequence.

The first_named_value function returns the first named value in the sequence of named values for parent or NULL if there are no named values for parent. Only fields and registers can have named values.

Use next_named_value to deallocate the previous named value and return the next named value or NULL if there are no more named values in this sequence.

Use free_named_value to free the named value without returning the next one in the sequence.

The get and set functions are used to get and set the value of the register. To set the value pass in a bytes_t for the value. The value passed in must be long enough to contain the full value of the register. If the bytes_t is too long it will be truncated. To get the value pass in a buffer_t which is long enough to contain the register's value. The value is encoded in little endian byte order.

typedef enum {
        Description_Type_Group,

        Description_Type_Int_Reg,
        Description_Type_Float_Reg,
        Description_Type_Fields_Reg,

        Description_Type_Int_Field,
        Description_Type_Float_Field,
} description_type_t;

typedef enum {
        Reg_Role_None, /* No special role for the register. */
        Reg_Role_Program_Counter /* The register is the program counter. */
} reg_role_t;

typedef enum {
        Reg_Bitorder_Little_Endian,
        Reg_Bitorder_Big_Endian
} reg_bitorder_t;

typedef struct {
        const char *name;
        const char *description;
        const bytes_t value; /* Little endian byte order */
} named_value_t;

typedef struct {
        /* Common fields */
        description_type_t type;
        const char *name;
        const char *description;

        /* Register and field fields */
        int16 dwarf_id;            /* id used by dwarf for this register
                                      or -1 if no such id is defined. This
                                      is ABI specific, but the CPU will
                                      give the ids for the most common ABI
                                      for that architecture. */
        reg_bitorder_t bitorder;   /* Bitorder convention used in the
                                      documentation for this register or
                                      field. */
        reg_role_t role;           /* Role of this register in the ABI/HW. */
        bool memory_mapped;        /* True if the register is memory mapped. */
        uint64 offset;             /* Offset into the bank for memory mapped
                                      registers. */
        bool catchable;            /* True if Core_Control_Register_Write and
                                      Core_Control_Register_Read are triggered
                                      when this register is written or read. */
        int msb, lsb;              /* Most and least significant bit of the
                                      register or field. Always given in le
                                      bitorder. For groups msb == -1 and
                                      lsb == 0. */
        int regsize;               /* Number of bits in the register, or the
                                      register this field is a part of. */
        int reg_id;                /* For registers and fields the id to pass
                                      to the get and set methods to access the
                                      register's value. Fields have the same
                                      reg_id as the register they are a part
                                      of. Not valid for groups.*/
} description_t;

SIM_INTERFACE(describe_registers) {
        const description_t *(*first_child)(
                conf_object_t *NOTNULL obj, const description_t *parent);
        const description_t *(*next_description)(
                conf_object_t *NOTNULL obj, const description_t *prev);
        void (*free_description)(conf_object_t *NOTNULL obj,
                                 const description_t *desc);
        const named_value_t *(*first_named_value)(
                conf_object_t *NOTNULL obj, const description_t *parent);
        const named_value_t *(*next_named_value)(
                conf_object_t *NOTNULL obj, const named_value_t *prev);
        void (*free_named_value)(conf_object_t *NOTNULL obj,
                                 const named_value_t *nv);
        void (*get)(conf_object_t *NOTNULL obj, int reg_id, buffer_t dest);
        void (*set)(conf_object_t *NOTNULL obj, int reg_id, bytes_t value);
};

#define DESCRIBE_REGISTERS_INTERFACE "describe_registers"

Execution Context
Cell Context for all methods.

device_identification

Description
The device_identification interface is used to identify device type such as product, stepping etc.

get_id returns the identifier for the given key. Existing keys can be retrieved using the get_key function. All existing keys should return a valid identifier string. For unknown keys the returned value is NULL.

get_key returns the key at the specified index or NULL starting at 0, to get the key at that index. At the index where NULL is returned there are no more keys.

get_key returns the key at the specified index, or NULL if the index does not correspond to a key. To get the complete list of keys, call get_key using an index starting at zero, and increase the index for each call until get_key returns NULL.

SIM_INTERFACE(device_identification) {
        const char *(*get_id)(conf_object_t *NOTNULL obj, const char *key);
        const char *(*get_key)(conf_object_t *NOTNULL obj, unsigned int index);
};

#define DEVICE_IDENTIFICATION_INTERFACE "device_identification"

Execution Context
Cell Context for all methods.

direct_memory

Description

The direct_memory interface is implemented by objects that model memory, such as RAM and ROM objects. These are called direct-memory objects. A user of the interface is called a memory user and is typically a processor that wants to do fast accesses to memory. The direct-memory object corresponding to a particular physical address can be obtained using the lookup method of the direct_memory_lookup interface. See the documentation for the direct_memory_lookup interface for more information.

A memory user using the direct_memory interface must implement the direct_memory_update interface.

The get_handle method is used by a memory user to create or retrieve a handle to the memory region starting at offset offs with size size. The handle is typically used later on to request access permissions and to retrieve a direct pointer to the region. The handle returned by get_handle is private to the memory user specified in the requester parameter.

If get_handle is invoked multiple times for the same range, and with identical requester and subsystem arguments, then the same handle will be returned each time, assuming the original handle is still valid. Note that the original handle is only returned if the range matches exactly. A single memory user can obtain multiple distinct handles for the same memory range by using different values for the subsystem parameter.

For RAM and ROM, offs and size must specify a region which does not intersect a naturally aligned 8192 byte boundary, or the request will fail with a NULL return value. Other direct-memory objects might have different requirements.

The request method is used to request a host pointer to simulated memory. This pointer can be used to carry out fast memory operations without having to involve the Simics API. The handle argument is the handle obtained using get_handle.

Both the permission argument and the inhibit argument are access_t type bit fields. The permission argument is used to specify what kind of memory operations the memory user will perform. For example, if a memory user wants to read memory, the permission argument must include the Sim_Access_Read value. The inhibit argument specifies what other memory users are not allowed to do. For example, if inhibit is set to Sim_Access_Write other memory users are not allowed to write to the memory range. This protection mechanism can be used to create caches of simulated memory, request exclusive permissions to a memory range in order to carry out atomic operations, and similar. When a memory user is requesting permission to a memory range that another memory user has protected with conflicting inhibit bits, the direct-memory object will inform the other memory user of the lost permissions and protection through the direct_memory_update interface. A user can lose both the permission and protection for a memory range in this way. When this happens, a memory user may re-request permissions and inhibit protection.

Note: if a memory user has multiple handles which overlaps, then each handle is considered to be a distinct memory user. For example, if a memory user holds two handles, and requests write inhibit on one of them, then write permission will be revoked from the second handle (if such permission had been granted).

The request method returns a direct_memory_t value with information about the retrieved permissions and inhibit bits. These bits can be a super set of the bits that actually were requested. The returned data pointer can be used to access the memory range. Accesses are valid from the data pointer and up to the end of the range, i.e., addresses up to data pointer + size - 1, where size is the size valid for the handle. A call to request always succeeds and the corresponding memory range is valid until the permissions or the handle are revoked by the direct_memory_update interface. Note that the data pointer may change each time request is called (with the same handle) since Simics may move simulated memory. If the pointer changes, then the old pointer must not be used.

With set_user_data, a memory user can associate a user-defined pointer with a specific handle. The pointer can be retrieved using the get_user_data method, which takes a handle as an argument.

A memory user can use the release function to notify the direct-memory object when it is no longer interested in the memory region corresponding to handle. The handle is invalid and must not be used for anything after being released.

The ack method is used by a memory user to inform the direct-memory object that it has given up the corresponding permission and inhibit rights for a memory range when called by a method in the direct_memory_update interface.

Permissions can be revoked from all memory users by invoking the revoke method. The permission parameter specifies the permissions which will be revoked from all memory users. Similarly, inhibit specifies the inhibit privileges which will be revoked. For instance, calling revoke with permission set to Sim_Access_Write will ensure that nobody has write permissions to the direct-memory object.

typedef granted_mem_t *direct_memory_handle_t;

typedef struct {
#ifndef PYWRAP
        uint8                 *data;
#endif
        access_t               permission;
        access_t               inhibit;
} direct_memory_t;

typedef uint64 direct_memory_ack_id_t;

SIM_INTERFACE(direct_memory) {
        direct_memory_handle_t (*get_handle)(conf_object_t *NOTNULL obj,
                                             conf_object_t *NOTNULL requester,
                                             uint64 subsystem,
                                             uint64 offs,
                                             unsigned size);
        direct_memory_t (*request)(conf_object_t *NOTNULL obj,
                                   direct_memory_handle_t handle,
                                   access_t permission,
                                   access_t inhibit);
        void (*revoke)(conf_object_t *NOTNULL obj,
                       access_t access,
                       access_t permission,
                       access_t inhibit);
#ifndef PYWRAP
        void *(*get_user_data)(conf_object_t *NOTNULL obj,
                                    direct_memory_handle_t handle);
        void (*set_user_data)(conf_object_t *NOTNULL obj,
                              direct_memory_handle_t handle,
                              void *user_data);
#endif
        void (*release)(conf_object_t *NOTNULL obj,
                        direct_memory_handle_t handle);
        void (*ack)(conf_object_t *NOTNULL obj,
                    direct_memory_ack_id_t id);
};

#define DIRECT_MEMORY_INTERFACE "direct_memory"

Execution Context
Cell Context for all methods.

direct_memory_flush

Description
The direct_memory_flush interface is implemented by objects that model memory, such as RAM and ROM objects, and is used for flushing granted rights and for managing access rights.

The revoke method revokes granted access, permissions and inhibit rights from memory-user regions intersecting [base, base + size).

The set_access_bits method grants access rights access for the region [base, base + size) to the memory user requester. If requester is NULL, then access rights are granted to all memory users. If the set succeeds, true is returned, otherwise false.

SIM_INTERFACE(direct_memory_flush) {
        void (*revoke)(conf_object_t *NOTNULL obj,
                       uint64 base, uint64 size,
                       access_t access, access_t perm, access_t inhibit);
        bool (*set_access_bits)(conf_object_t *NOTNULL obj,
                                conf_object_t *requester,
                                uint64 base, uint64 size,
                                access_t access);
};
#define DIRECT_MEMORY_FLUSH_INTERFACE "direct_memory_flush"

Execution Context
Cell Context for all methods.

direct_memory_lookup

Description

The direct_memory_lookup interface is implemented by Simics memory-spaces. The interface is used by simulator objects that want to do fast accesses to memory and/or want to build up a cached representation of memory. These objects are referred to as memory users, e.g., processors. Fast accesses are done via host pointers to simulated memory. The direct_memory_lookup interface is used in conjunction with the direct_memory interface which is implemented by objects that own the actual data storage, e.g., RAM/ROM objects. These objects are called direct-memory objects.

To access data, a memory-user object first calls the lookup method on the memory space obj. The requester is the memory-user doing the lookup. The lookup method traces the range specified by addr and size through memory spaces and translators until a direct-memory object is reached. The direct-memory object is returned in the target field and the offset into this object corresponding to addr is returned in the offs field.

The call to lookup fails if the specified range does not map continuously to a direct-memory object. A lookup failure is indicated by returning NULL in the target field.

The access argument is a bit field of at least one access_t value specifying what kind of accesses the memory user is interested in. All specified access types must reach the same direct-memory object and range for the lookup to succeed. If the memory space, for example, redirects reads and writes to different memory ranges or direct-memory objects, a lookup would fail if access specified both read and write. Note that the actual access permissions needed to access the real data must be requested from the direct-memory object using the request method of the direct_memory interface. The access argument is only used to locate the direct-memory object.

The return field access contains at least the access bits requested used in the lookup request, but may as an optimization contain a superset, indicating that the lookup result is valid for this superset. However, there is no guarantee that this optimization takes place.

Once a direct-memory object has been found, the direct_memory interface can be used to obtain a direct pointer to the contents of the direct-memory object.

The tracers and breakpoints fields in the return value contain information about installed tracers and breakpoints that intersect the range. Examples of tracers are timing models and snoop objects. In order to trigger breakpoints and invoke any tracers, the memory user should perform memory operations using the memory_space interface. Only breakpoints and tracers that overlap (binary and) with the provided access argument need to be considered.

typedef struct {
        conf_object_t     *target;
        uint64             offs;

        access_t           breakpoints;      // conflicting breakpoints
        access_t           tracers;          // conflicting tracers
        access_t           access;           // handle valid for access
} direct_memory_lookup_t;

SIM_INTERFACE(direct_memory_lookup) {
        direct_memory_lookup_t (*lookup)(conf_object_t *NOTNULL obj,
                                         conf_object_t *requester,
                                         physical_address_t addr,
                                         unsigned size,
                                         access_t access);
};

#define DIRECT_MEMORY_LOOKUP_INTERFACE "direct_memory_lookup"

The direct_memory_lookup and direct_memory interfaces replace the memory_page interface of Simics 4.8.

Execution Context
Cell Context for all methods.

direct_memory_lookup_v2

Description

The direct_memory_lookup_v2 interface is implemented by Simics memory-spaces. Its functionality is identical to the direct_memory_lookup interface except that it takes a transaction_t argument instead of a requester object and size. It must be used instead of direct_memory_lookup in cases when memory mappings may depend on atoms of the transaction in addition to the physical address.

SIM_INTERFACE(direct_memory_lookup_v2) {
        direct_memory_lookup_t (*lookup)(conf_object_t *NOTNULL obj,
                                         transaction_t *NOTNULL transaction,
                                         physical_address_t addr,
                                         access_t access);
};

#define DIRECT_MEMORY_LOOKUP_V2_INTERFACE "direct_memory_lookup_v2"

Execution Context
Cell Context for all methods.

direct_memory_tags

Description

The direct_memory_tags interface is implemented by objects that model RAM memory with support for auxiliary RAM bits.

The get_tags_data method returns a direct_memory_tags_t value which contains a direct pointer to the memory used to store the tags bits. The handle argument should be a handle for a region of memory previously obtained from the get_handle method of the direct_memory interface.

NOTE: The memory region specified indirectly by the handle argument will be enlarged, if necessary, to have a natural 128-byte alignment. This is done to ensure that the tags mapping is unambiguous.

The returned data pointer points to tag bits for the region specified by handle. The least significant bit of the first byte corresponds to the first 16 bytes of the (aligned) region.

The len field is set to the number of bytes holding tags data that may be accessed and it equals the size of the (aligned) region divided by 128.

The augmented memory bits may be read or modified using the returned pointer, provided that the user has corresponding read or write permissions to the region specified by handle.

The returned pointer will remain valid until the corresponding permissions to the direct memory region are lost, which usually happens through a call to the update_permission method of the direct_memory_update interface. The returned pointer must also be considered invalid when additional permissions for the region are requested using the request method of the direct_memory interface. This is necessary since e.g. a write request could trigger copy-on-write behavior and reallocation of the underlying storage.

typedef struct {
#ifndef PYWRAP
        uint8 *data;
#endif
        unsigned len;
} direct_memory_tags_t;

SIM_INTERFACE(direct_memory_tags) {
        direct_memory_tags_t (*get_tags_data)(conf_object_t *NOTNULL obj,
                                              direct_memory_handle_t handle);
};
#define DIRECT_MEMORY_TAGS_INTERFACE "direct_memory_tags"        

Execution Context
Cell Context for all methods.

direct_memory_update

Description
The direct_memory_update interface must be implemented by memory-user objects that use the direct_memory interface.

The direct_memory_update interface replaces the memory_page_update interface from Simics 4.8.

Accesses to memory are controlled by a handle that the memory-user object requests by calling the get_handle method of the direct_memory interface. The object implementing the direct_memory interface through which the handle was established is passed to the functions in direct_memory_update as target.

If the release method is called, the corresponding handle and all the permissions and inhibit protections are recalled. The memory-user object must stop using the handle and associated data pointers and then call the acknowledge method ack in the direct_memory interface from which the handle was granted.

A call to the update_permission method revokes earlier requested rights for a handle. The lost_access argument recalls rights to use the handle for the given access bits. This means that the handle needs to be re-fetched (by a call to the lookup method of the direct_memory_lookup interface followed by a call to the get_handle method of the direct_memory interface) before the handle can be used again for the particular access. This typically happens if a new breakpoint is inserted or a remap of the memory system is done. In case of a remap it is possible that the same handle will never be returned again which means that any user data associated with the handle should be reclaimed.

The lost_permission and the lost_inhibit arguments describe which permission rights and inhibit protection that are revoked. However, in contrast to the lost_access, the handle is still valid and can be used to re-request permission rights and inhibit protection.

A call to the conflicting_access method informs a memory-user object that a conflicting memory operation will be performed. Hence, if the memory-user object have some protected representation of memory (such as decoded instructions in an internal cache), that representation of memory has to be flushed (or written back to memory in case of dirty data). Note however that the memory-user object does not lose any permission rights or any inhibit protection.

There is no mechanism for locking simulated memory in host memory.

All methods in this interface receive a direct_memory_ack_id_t value as an argument. The ack method of the direct_memory interface must be called with this id as an argument when the corresponding operation has been carried out. The ack method may be called after the direct_memory_update interface function has returned, which allows for queueing of update requests. This may be valuable if multiple simulator threads are used.

An exception to the allowed queueing of update requests is for update requests that are received while calling request in the direct_memory interface. Such requests must be handled immediately with ack being called before the return of the direct_memory_update interface function. This requirement avoids a dead-lock that would otherwise happen if request would wait for ack before returning, but ack is queued to be handled at some time after request has returned.

SIM_INTERFACE(direct_memory_update) {
        void (*release)(conf_object_t *NOTNULL obj,
                        conf_object_t *NOTNULL target,
                        direct_memory_handle_t handle,
                        direct_memory_ack_id_t id);
        void (*update_permission)(conf_object_t *NOTNULL obj,
                                  conf_object_t *NOTNULL target,
                                  direct_memory_handle_t handle,
                                  access_t lost_access,
                                  access_t lost_permission,
                                  access_t lost_inhibit,
                                  direct_memory_ack_id_t id);
        void (*conflicting_access)(conf_object_t *NOTNULL obj,
                                   conf_object_t *NOTNULL target,
                                   direct_memory_handle_t handle,
                                   access_t conflicting_permission,
                                   direct_memory_ack_id_t id);
};

#define DIRECT_MEMORY_UPDATE_INTERFACE "direct_memory_update"

Execution Context
Cell Context for all methods.

disk_component

Description
The disk_component interface is implemented by components that provide disk storage. The size() member function should return the total disk size provided by the component, once configured.

SIM_INTERFACE(disk_component) {
        uint64 (*size)(conf_object_t *obj);
};
#define DISK_COMPONENT_INTERFACE "disk_component"

Execution Context
Global Context for all methods.

event_delta

Description
The event_delta interface is implemented by CPUs and clocks that advance time.

The set_delta method notifies the CPU about the number of cycles the CPU should run before the next event should be dispatched by a call to the handle_event method of the event_handler interface.

The get_delta queries the CPU for the current count of remaning cycles to the next event. The returned number should always be smaller or equal to the number of cycles established by a previous call to set_delta.

SIM_INTERFACE(event_delta) {
        uint64 (*set_delta)(conf_object_t *NOTNULL obj,
                            conf_object_t *NOTNULL event_handler_obj,
                            const event_class_t *next_event_ec,
                            uint64 delta);
        uint64 (*get_delta)(conf_object_t *NOTNULL obj,
                            conf_object_t *NOTNULL event_handler_obj);
};
#define EVENT_DELTA_INTERFACE "event_delta"

Execution Context
Cell Context for all methods.

event_handler

Description
The event_handler interface is implemented by the vtime port object and is invoked by clocks or CPUs implementing the event_delta interface.

The handle_event method should be called when the number of cycles to the next event has reached zero. The method invokes the next event and notifies the CPU or clock about the cycle count to the next pending event by invoking the set_delta method.

The stop method should be called if a dispatched event requests the simulation to be stopped. The method is typically called from the stop method of the execute interface. If the stop method is not called, then time may be advanced by a fraction of a cycle after an event has been dispatched.

SIM_INTERFACE(event_handler) {
        bool (*handle_event)(conf_object_t *NOTNULL obj);
        void (*stop)(conf_object_t *NOTNULL obj);
};
#define EVENT_HANDLER_INTERFACE "event_handler"

Execution Context
Cell Context for all methods.

event_provider

Description
=============================================

TECH-PREVIEW

This interface may change without notice.

=============================================

The event_provider interface is used internally in between ISIM modules.

The method event_name returns name of event with index n or NULL if there is no event with that index.

The method event_value returns accumulated value for event with index n. Output is undefined if there is no event with that index.

Events must de indexed from 0 to last without gaps.

To use the event-provider add the following EXTRA_MODULE_VPATH := event-provider-interface to the modules Makefile.


SIM_INTERFACE(event_provider) {
        const char *(*event_name)(conf_object_t *obj, unsigned n);
        uint64 (*event_value)(conf_object_t *obj, unsigned n);
};

#define EVENT_PROVIDER_INTERFACE "event_provider"

Execution Context
Called from performance models.

exception

Description
The exception interface is used to translate exception numbers, as received by the Core_Exception hap, to names, and vice versa.

The get_number function returns the number associated with an exception name, or -1 if the no exception with the given name exist. The get_name returns the name associated with an exception number. The get_source function is only used on X86 targets and returns the source for an exception, as an exception number can be raised from different sources. The all_exceptions function returns a list of all exceptions numbers.

The exception numbers are architecturally defined, while their names are defined by the model.

SIM_INTERFACE(exception) {
        int (*get_number)(conf_object_t *NOTNULL obj,
                          const char *NOTNULL name);
        const char *(*get_name)(conf_object_t *NOTNULL obj, int exc);
        int (*get_source)(conf_object_t *NOTNULL obj, int exc);
        attr_value_t (*all_exceptions)(conf_object_t *NOTNULL obj);
};

#define EXCEPTION_INTERFACE "exception"

Execution Context
Cell Context for all methods.

exec_trace

Description
The exec_trace interface is implemented by processor models that support tracing. A trace listener registers itself with the register_tracer call. The tracer callback will be called by the processor model when each instruction is just about to be executed, passing the tracer_data as passed to the register_tracer function in addition to information about the instruction that is executed. Invoke unregister_tracer with the same two pointers to deregister the listener.

typedef void (*instruction_trace_callback_t)(lang_void *tracer_data,
                                             conf_object_t *cpu,
                                             linear_address_t la,
                                             logical_address_t va,
                                             physical_address_t pa,
                                             byte_string_t opcode);

The pa parameter to the callback will always be valid, but some CPU architectures may not support la or va. The la argument is typically only valid for x86 CPUs. Lastly, the opcode of the instruction is passed in opcode. The opcode is passed without endian conversion, meaning that byte X in opcode corresponds to the byte at pa + X.

SIM_INTERFACE(exec_trace) {
        void (*register_tracer)(conf_object_t *NOTNULL cpu_obj,
                                instruction_trace_callback_t tracer,
                                lang_void *tracer_data);
        void (*unregister_tracer)(conf_object_t *NOTNULL cpu_obj,
                                  instruction_trace_callback_t tracer,
                                  lang_void *tracer_data);
};

#define EXEC_TRACE_INTERFACE "exec_trace"

Execution Context
Global Context for both methods. Cell Context for the callback.

execute

Description
The execute interface is implemented by objects that drive a simulation, which is often processor models. The object does not have to implement cycle or step.

An object implementing the execute interface must be coupled with one object implementing the cycle interface. It can be the same object that implements the cycle interface.

The run function is called when the simulator starts or restarts the execution.

By default the Simics scheduler will assume that the object being called in with the execute interface also implements the corresponding processor_info and step interfaces. If this assumption is incorrect, the implementation of the run function is responsible for maintaining the simulators view of the current objects implementing the processor_info and step interfaces. It does that by using the appropriate functions in the cell_inspection interface. The current objects must always be correctly set when either the run function returns, when any API method is called, or when any other object is called through an interface. Several Simics features, such as CLI commands, device logging, and hap handling make use of the current objects.

To handle asynchronous events, and thus allow for reasonable interactive performance, the implementor of execute needs to either make sure that run returns after not having run for too long, or preferably regularly call the VT_check_async_events method. In the Simics library CPU models, VT_check_async_events is called after servicing events from the cycle or step interfaces.

The simulator core will call stop when it detects a condition that should interrupt the simulation. The callee should stop as soon as possible when in a stable state, typically when the current executing instruction is finished after getting a request to stop. In some cases the callee might receive multiple stop requests in a rapid sequence. Conditions leading to a stop request include SIM_break_simulation being called from a device or hap-handler, breakpoint triggered, low-memory situations, the user interrupting the simulation with Ctrl-C, and the Simics core halting the object when it is at the end of the allowed time window in temporal decoupled simulation. It is forbidden to do anything in the stop function that can lead to a new stop request, this includes posting events, printing SIM_log-messages, etc. Before returning from the run method, the VT_stop_event_processing function should be called. The requirement to call VT_stop_event_processing is likely to be lifted in future versions of Simics.

The switch_in function is called whenever the execute object is about to gain control of the simulation from some other execute object in the cell. Similarly, switch_out is invoked before control is relinquished. It should be noted that these functions are called in a deterministic manner which is not true for run.

The switch_in and switch_out functions are not called at simulation start (or checkpoint load), in general.

SIM_INTERFACE(execute) {
        void (*run)(conf_object_t *obj);
        void (*stop)(conf_object_t *obj);

        void (*switch_in)(conf_object_t *obj);
        void (*switch_out)(conf_object_t *obj);
};

#define EXECUTE_INTERFACE "execute"

Execution Context
Cell Context for all methods.

execute_control

Description
The execute_control interface is implemented by CPUs and devices that support threading.

Warning: This interface is currently considered tech-preview and can be changed at any time.

SIM_INTERFACE(execute_control) {
        void (*message_pending)(conf_object_t *obj);
        void (*yield_request)(conf_object_t *obj);
};
#define EXECUTE_CONTROL_INTERFACE "execute_control"

Execution Context
Threaded Context

freerun

Description
The freerun interface is provided by the freerun-extension extension class. The extension class augments CPU models with support for freerunning mode. The freerun interface is used by CPU models to interface with the extension class.

The enabled member returns true if freerunning mode is enabled and false otherwise. The notifier Sim_Notifier_Freerunning_Mode_Change is triggered for the object whenever freerunning mode is enabled or disabled.

The advance_clock is used by the CPU model to calculate how much its virtual time should be advanced in freerunning mode. The ps_limit argument is the maximal number of pico-seconds virtual time can be advanced. The next CPU event typically occurs at this time. The steps argument should be set to the number of elapsed instructions since the last call to advance_clock. The idle parameter should be set to true if the CPU is idle. The function returns the number of pico-seconds the virtual time of the CPU should be advanced. The returned value is proportional to the time spent simulating the model, but is also subject to configurable freerunning restrictions which ensures that the instruction rate is kept in an acceptable range.

The start_clock function should be called when the CPU model starts instruction simulation. It is used to measure the amount of time used to simulate the model.

The stop_clock function should be called when the CPU model stops instruction simulation.

The current_itime function returns a prediction of the amount of time needed to simulate an instruction, in pico-seconds. The estimate is based on historic data and will always be in an interval which does not conflict with configured freerunning restrictions. The value can be used to estimate how many instructions can be executed until the next time event.

Note: The freerun interface is experimental and may change without notice.
SIM_INTERFACE(freerun) {
        bool (*enabled)(conf_object_t *NOTNULL obj);

        int64 (*advance_clock)(conf_object_t *NOTNULL obj,
                               int64 ps_limit, int64 steps, bool idle);
        void (*start_clock)(conf_object_t *NOTNULL obj);
        void (*stop_clock)(conf_object_t *NOTNULL obj);

        uint64 (*current_itime)(conf_object_t *NOTNULL obj);
};
#define FREERUN_INTERFACE "freerun"

Execution Context
Cell Context for all methods.

gfx_con

Description
The gfx_con is implemented by graphics consoles of class graphcon and is used by attached video devices to update the screen.

The set_color method sets the specified indexed palette color. The return value has no meaning.

The set_size method sets the size of the displayed screen.

The put_pixelmethod sets the pixel at (x, y) to the specified palette color. The change will only be visible after the next call to redraw.

The put_pixel_rgb method sets the pixel at (x, y) to the color rgb, which should be in GFX_xRGB_8888 format. The change will only be visible after the next call to redraw.

The put_pixel_col method sets the pixel at (x, y) to the color defined by r, g and b. The change will only be visible after the next call to redraw.

The put_block method draws pixels from a memory block to the screen rectangle described by (minx, miny, maxx, maxy); the upper bounds are inclusive. The block parameter refers to the source memory block, whose rows should be src_stride bytes long. Memory on each row outside the rectangle is not accessed. The src_fmt parameter specifies the pixel format in block. The change will only be visible after the next call to redraw.

The redraw method updates the changed parts of the console screen window, so should typically be called at the end of every frame update.

The update_keyboard_leds method changes the keyboard LEDs. The led_change parameter must be one of the KBD_ constants from simics/model-iface/sim-keys.h.

SIM_INTERFACE(gfx_con) {
        int (*set_color)(conf_object_t *obj,
                         uint8 index, uint8 r, uint8 g, uint8 b);
        void (*set_size)(conf_object_t *obj, int width, int height);
        void (*put_pixel)(conf_object_t *obj, int x, int y, uint8 index);
        void (*put_pixel_rgb)(conf_object_t *obj, int x, int y, uint32 rgb);
#ifndef PYWRAP
        void (*put_block_old)(conf_object_t *obj,
                              uint8 *src, int minx, int miny,
                              int maxx, int maxy, int src_fmt,
                              int src_stride, int unused);
#endif
        void (*redraw)(conf_object_t *obj);
        void (*update_keyboard_leds)(conf_object_t *obj, int led_change);
        void (*put_pixel_col)(conf_object_t *obj, int x, int y,
                              int r, int g, int b);
        void (*put_block)(conf_object_t *obj, bytes_t block, int minx, int miny,
                          int maxx, int maxy, gfx_con_pixel_fmt_t src_fmt,
                          int src_stride);
};

#define GFX_CON_INTERFACE "gfx_con"

Execution Context
Cell Context for all methods

hap_listen

Description
With the hap_listen interface, objects can pick up haps and process then as they wish, including re-raising the haps.

SIM_INTERFACE(hap_listen) {
        void (*occurred)(conf_object_t *obj, conf_object_t *origin,
                         hap_type_t hap, int64 value, va_list ap, bool always);
};
#define HAP_LISTEN_INTERFACE "hap_listen"

Execution Context
occurredCell Context

image

Description
This interface is used for handling big data images.

read and write access a chunk of data at a time. Only accesses within the bounds of the image are allowed.

clear_range fills an interval with null bytes, fill with any byte value.

size returns the image size.

get and set work like read and write but pass the data using a bytes_t instead, and can be used from Python.

flush_writable writes out all unwritten changes to a writable backing file if one exists; otherwise, does nothing.

Other methods are not currently for public use.

SIM_INTERFACE(image) {
#if !defined(PYWRAP)
        void (*read)(conf_object_t *img, void *NOTNULL to_buf, uint64 start,
                     size_t length);
        void (*write)(conf_object_t *img, const void *NOTNULL from_buf,
                      uint64 start, size_t length);
        int (*for_all_spages)(conf_object_t *img,
                              int (*NOTNULL f)(image_spage_t *NOTNULL p,
                                               uint64 ofs, void *arg),
                              void *arg);
#endif /* not PYWRAP */
        void (*set_persistent)(conf_object_t *obj);
        void (*save_to_file)(conf_object_t *NOTNULL obj,
                             const char *NOTNULL file,
                             uint64 start, uint64 length, save_flags_t flags);
        void (*save_diff)(conf_object_t *NOTNULL obj,
                          const char *NOTNULL file, save_flags_t flags);
        void (*clear_range)(conf_object_t *NOTNULL obj,
                            uint64 start, uint64 length);
        void (*fill)(conf_object_t *NOTNULL obj,
                     uint64 start, uint64 length, uint8 value);
        uint64 (*size)(conf_object_t *NOTNULL obj);
        void (*set)(conf_object_t *NOTNULL obj, uint64 ofs, bytes_t b);
        bytes_t (*get)(conf_object_t *NOTNULL obj, uint64 ofs, size_t size);
        void (*flush_writable)(conf_object_t *NOTNULL obj);
};

#define IMAGE_INTERFACE "image"

Execution Context
readCell Context
writeCell Context
for_all_spagesCell Context
set_persistentCell Context
save_to_fileCell Context
save_diffCell Context
clear_rangeCell Context
fillCell Context
sizeCell Context
setCell Context
getCell Context
flush_writableCell Context

image_snoop

Description
The image snoop interface is used to get information about when image pages are written to. Note that with the addition of inhibit bits in the direct_memory interface, the image snoop interface is rarely needed for model functionality.

The page_modified function is always called the first time a page is written to. It may also be called additional times even if a page has already been written to. A user of the image snoop interface can at any time reset this mechanism so that all pages are considered not written to and therefore the page_modified function will be called again on future writes. The reset can be accomplished either through the memory page update interface or through the pool protect interface.

The image snoop interface can, for example, be used by frame buffer devices to efficiently keep track of areas of the frame buffer to redraw, or for a CPU module that builds cached representations of code pages to invalidate such caches when memory is modified.

Listeners using this interface are installed with the image_snoop_devices attribute in the image class.

SIM_INTERFACE(image_snoop) {
        void (*page_modified)(conf_object_t *obj, conf_object_t *img,
                              uint64 offset, uint8 *page_data,
                              image_spage_t *spage);
};
#define IMAGE_SNOOP_INTERFACE "image_snoop"

Execution Context
Cell Context for all methods.

instruction_fetch

Description
The instruction_fetch interface is implemented by processors. The interface controls how instruction fetches should be modeled.

The get_mode and set_mode functions get and set the instruction fetch mode. There are three available modes. All modes are not supported by all processor types. The instruction_fetch_none mode is the least accurate but the fastest mode. The other modes are more accurate but slower.

The get_line_size and set_line_size functions get and set the fetch size on each instruction fetch. This is often related to cache line size or similar. The line size must be power of 2.

typedef enum {
        /* No instruction fetch sent to memory hierarchy */
        Instruction_Fetch_None = 0,

        /* Memory hierarchy gets fetch for each cache line access */
        Instruction_Fetch_Cache_Access_Trace = 1,

        /* Memory hierarchy gets fetch for each instruction fetch. Only
           x86/x86-64 */
        Instruction_Fetch_Trace = 2
} instruction_fetch_mode_t;

SIM_INTERFACE(instruction_fetch) {
        instruction_fetch_mode_t (*get_mode)(conf_object_t *obj);
        void (*set_mode)(conf_object_t *obj, instruction_fetch_mode_t mode);
        int (*get_line_size)(conf_object_t *obj);
        void (*set_line_size)(conf_object_t *obj, int size);
};
#define INSTRUCTION_FETCH_INTERFACE "instruction_fetch"

Execution Context
get_modeCell Context
set_modeGlobal Context
get_line_sizeCell Context
set_line_sizeGlobal Context

instrumentation_order

Description
This interface is used to control the dispatch order of connected instrumentation. It is implemented by instrumentation providers that have the ability to change the order in which instrumentation events occur. This works by associating every instrumentation event with a connection object. It is up to the provider to supply a way to do this. See the cpu_instrumentation_subscribe interface for an example. Most users of any instrumentation will only be observing the state of the provider, in which case the order is unimportant. However, if users of instrumentation may change the behavior of the provider, this interface may be useful.

The default order for callbacks that should be honored by all providers, where possible, regardless if they implement the instrumentation_order interface or not is:

  1. all anonymous connections, i.e. NULL connections, in registration order
  2. connection order, which if not re-ordered will be the connection registration order
  3. callback registration order

The get_connections method should return an attr_value_t list with connection objects that represent the current order. The first element in the list is the first object in the dispatch order, etc.

The move_before method moves the connection given by the connection argument before the connection given by the anchor argument. If the anchor is NULL the connection will be moved last. The given connection objects must be present in the current dispatch order for this to succeed.

SIM_INTERFACE(instrumentation_order) {
        // Returns an object list in the connection order
        attr_value_t (*get_connections)(conf_object_t *obj);
        
        bool (*move_before)(conf_object_t *self, conf_object_t *connection,
                            conf_object_t *before); 
};
#define INSTRUMENTATION_ORDER_INTERFACE "instrumentation_order"

Execution Context
Global Context for all methods, but must be called from a callback receiving a handle of type instruction_handle_t.

int_register

Description
The int_register interface is used for access to registers in a processor. It can be used to access any kind of integer register, not only the "normal" registers. This includes all kinds of control registers, hidden registers and anything else that might be useful to access as a register. The only limitation is that the register value should be representable as a 64-bit unsigned integer.

This interface can be implemented by other classes than processors, but it is likely to be found mostly in processors.

Registers are identified by a number, and there are two functions to translate from register names to register numbers and back. The translation need not be one-to-one, which means that one register can have several names. A register name can, however, only translate to a single register number.

Often, registers are grouped in register banks, where registers in the bank are numbered from 0 up. Registers in a bank should have consecutive numbers (unless their numbering is very sparse). This allows a user to deduce register numbers by calling get_number for the first register only. The first register numbers should be used for the general-purpose integer registers, if possible (so that integer register rN has number N).

Using this interface to read or write registers does not cause any side effects, such as triggering interrupts or signalling haps.

get_number translates a register name to its number. Returns -1 if the register does not exist.

get_name translates a register number to its canonical name.

read reads a register value.

write writes a new register value.

all_registers returns a list of all register numbers that can be used for this object.

register_info returns information about a single register. The information return depends on the info parameter.

Sim_RegInfo_Catchable
Return 1 if Core_Control_Register_Write and Core_Control_Register_Read are triggered when this register is written or read.
Return 0 otherwise.

typedef enum {
        Sim_RegInfo_Catchable
} ireg_info_t;

SIM_INTERFACE(int_register) {
        int (*get_number)(conf_object_t *NOTNULL obj,
                          const char *NOTNULL name);
        const char *(*get_name)(conf_object_t *NOTNULL obj, int reg);
        uint64 (*read)(conf_object_t *NOTNULL obj, int reg);
        void (*write)(conf_object_t *NOTNULL obj, int reg, uint64 val);
        attr_value_t (*all_registers)(conf_object_t *NOTNULL obj);
        int (*register_info)(conf_object_t *NOTNULL obj, int reg,
                             ireg_info_t info);
};

#define INT_REGISTER_INTERFACE "int_register"

Execution Context
Cell Context for all methods, except for write where the register is a program counter; Global Context in that case.

keyboard

Description
Interface implemented by keyboard controllers. Used by consoles to send keyboard events to the controller.

The function keyboard_event() takes the keyboard controller as its first argument obj. The key_up argument specifies whether the event is a key release (1) or a key press (0). The key argument is the Simics internal keycode, as defined in the sim_key_t enum.

If the return value is 1 the keyboard controller accepted the event. If return value is 0 the keyboard controller did not accept the event, and the console should buffer the event until it gets a keyboard_ready() call from the keyboard controller.

SIM_INTERFACE(keyboard) {
        int (*keyboard_event)(conf_object_t *obj, int key_up, uint8 key);
};

#define KEYBOARD_INTERFACE "keyboard"

Execution Context
Cell Context for all methods.

keyboard_console

Description
Interface implemented by consoles, to receive notifications from keyboard controllers.

The function keyboard_ready(), which takes the console as its first argument obj, must be called by the keyboard controller when it is ready to receive keyboard events again after having rejected a keyboard event. Note that this function may be called even though no keyboard event has been rejected, and that the console must not assume that keyboard controller will accept an event just because the keyboard_ready() function has been called.

keyboard_ready must not be called while the keyboard controller is handling a keyboard_event() call.

SIM_INTERFACE(keyboard_console) {
        void (*keyboard_ready)(conf_object_t *obj);
};

#define KEYBOARD_CONSOLE_INTERFACE "keyboard_console"

Execution Context
Cell Context for all methods.

linear_image

Description
Note: This interface is an experimental feature. It is excluded from the standard support program, and is subject to change or removal without notice.
The linear_image interface permits direct access to the data in image objects by requesting a linear allocation for the contents. Doing so is not recommended for very large images, since there must be space for all data in memory as a contiguous block.

get_base returns the linear allocation block if one has already been set. Otherwise, a block of the correct size is allocated, set and returned. In the latter case, the block is owned by the image object and should not be freed by the user. If retsize is non-null, it is used to return the size of the image.

set_base specifies an existing memory block to be used for the image contents. The block must be at least the size of the image, and should be aligned to a multiple of 4096 bytes. The caller is responsible for the allocation of the block, which must remain allocated for the remaining lifetime of the image object.

prepare_range must be called, with the matching access type, before any direct access to data in a linear block by user code. It is then permitted to access bytes in the range [offs, offs + size) . For type = Sim_RW_Write, the permission to modify data in that range only extends until any other objects using the image have the opportunity to do so (typically, when the modelling function returns control to the simulator).

set_base and get_base cannot be called after image data has been accessed (read or written) for the first time.

SIM_INTERFACE(linear_image) {
#if !defined(PYWRAP)
        uint8 *(*get_base)(conf_object_t *obj, size_t *retsize);
        void (*set_base)(conf_object_t *obj, uint8 *NOTNULL base);
#endif /* not PYWRAP */
        void (*prepare_range)(conf_object_t *NOTNULL obj,
                              read_or_write_t type, size_t offs, size_t size);
};
#define LINEAR_IMAGE_INTERFACE "linear_image"

Execution Context
set_base Global Context
get_base Global Context
prepare_range Cell Context

magic_pipe_reader

Description
An interface for reading received data from a magic pipe application running in the target system. This interface is called by a simics extension running in the host system communicating with a target application via a magic pipe. The communication is identified by a magic number. These numbers are acquired or reserved in the magic_pipe_setup_interface.

The magic pipe library on the target system allocates a page-locked pipe buffer for the target application, which uses the buffer to communicate data to and from the host system. That buffer is fragmented when read by the host system and therefore copied into a new unfragmented buffer, which is used for all read accesses in this interface. All C-code readewr callback functions are allowed direct access to this memory area, while Python reader callback functions require another copy for ownership reasons.

This interface does not modify the pipe buffer data in any way, and the callers are not allowed to do that neither. It is therefore safe for several readers to subscribe to the same data.

Note: This interface is an experimental feature. It is excluded from the standard support program, and is subject to change or removal without notice.
SIM_INTERFACE(magic_pipe_reader) {
        /* Query whether the byte-order of the simulated target system differs
           from that of the simulator host system. */
        bool (*is_byte_swap_needed)(conf_object_t *obj, uintptr_t buf);

        /* Query the amount of used pipe buffer space. This value is always
           less than the allocated buffer size because it does not count the
           internal pipe buffer header. */
        size_t (*read_buffer_size)(conf_object_t *obj, uintptr_t buf);

#ifndef PYWRAP
        /* Get direct read-only access to the incoming pipe buffer data, at the
           desired offset. The function returns a pointer to, and the remaining
           used size from, the specified offset.

           This function gives a direct pointer into internal memory and
           therefore cannot be used by Python code. */
        bytes_t (*read_data_direct)(conf_object_t *obj, uintptr_t buf,
                                    size_t offs);
#endif

        /* Get a copy the pipe buffer data, at the specified offset with the
           specified length. If the length argument is zero, then the length of
           the remaining space from the offset is assumed.

           This function will allocate a new data buffer to hold the desired
           amount of data and return it to the caller, who is responsible to
           deallocating it once it has served its purpose. */
        bytes_t (*read_data_copy)(conf_object_t *obj, uintptr_t buf,
                                  size_t offs, size_t len);
};

#define MAGIC_PIPE_READER_INTERFACE "magic_pipe_reader"

Execution Context
Cell Context for all methods.

magic_pipe_setup

Description
The magic pipe setup interface is used to establish connections between an application running in the simulated target system and a Simics extension executing on the simulator host.

Magic numbers are used to identify and isolate connections, called pipes. Typically a well-known value is used to perform a handshake and then assign a new and unique value, which is used in all successive correspondence between the end-points.

The Simics extension is responsible for assigning these new and unique magic numbers, and to subscribe to them. This interface provides the necessary facilities to either get a new random number or reserve a range for the service to distribute on its own.

An example of a common communication flow can be divided into two phases, first the initial handshake phase where some information about each other is exchanged, followed by the duty phase where the target system application is communicating back and forth with the host system Simics extension to fulfill their purpose.

The handshake is initiated from the target application, which sends a handshake request to the host system extension containing some information about itself. The host system extension receives the request and replies with a new magic number and some information about itself. The new magic number is to be used in all further communication between the parties, to isolate the communications pipe from other users of the magic pipe.

In the duty phase the common communication flow may look like this. The target system application starts by allocating a pipe buffer from the magic pipe library. Then writes its data to the buffer and sends it to the host system extension. The extension handles the data and reuses the same buffer to write something back to the application. This means that the buffer size is fixed and limits the amount of data that can be returned. Because of this it is common for the application to allocate more space than needed for its sent data. Once the application returns from its send call, the same buffer it allocated earlier is filled with data coming from the extension. This data is handled by the application and then the buffer is freed. This duty cycle is then repeated as many times as needed.

Each magic number may have more than one subscribers, therefore reading and writing is divided into two phases, where all readers are allowed access first. Then comes the writer phase and the subscribers are called in the order they registered. This also means that later writer subscribers are limited to writing only the remaining amount of data to the buffer.

There is no on or off setting for a pipe to enable or disable the communication. The only option is to unregister from the magic number to suspend the communication and then to register again to resume.

The registered subscribers should unregister when they are no longer interested in receiving any data. This will also allow the magic pipe to stop listening to haps when there is no one to receive them. The magic pipe will automatically resume listening once there are subscribers again.

Note: This interface is an experimental feature. It is excluded from the standard support program, and is subject to change or removal without notice.
SIM_INTERFACE(magic_pipe_setup) {
        /* Register a subscriber for a new magic number, which is returned by
           this function. The number is guaranteed to be unused and unreserved.

           The reader and writer call-backs will be called in turn for each
           message with the new magic number. Unless they are NULL or None. */
        uint64 (*register_new_pipe)(
                conf_object_t *obj, conf_object_t *cpu, conf_object_t *user,
                pipe_func_t reader, pipe_func_t writer);

        /* Register a subscriber for a range of reserved magic numbers.

           The min_magic argument must be greater than zero and max_magic equal
           to or greater than that. */
        void (*register_pipe_range)(conf_object_t *obj, conf_object_t *user,
                                    uint64 min_magic, uint64 max_magic,
                                    pipe_func_t rd, pipe_func_t wr);

        /* Register a subscriber for a reserved magic number.

           The reader and writer call-backs will be called in turn for each
           message with the reserved magic number, unless NULL or None.

           The magic number zero is reserved for a catch-all handler,
           where any message that is unsubscribed will trigger the
           call-backs. */
        void (*register_reserved_pipe)(
                conf_object_t *obj, conf_object_t *user, uint64 magic,
                pipe_func_t reader, pipe_func_t writer);

        /* Unregister the subscription of a magic number for this user. This
           will unregister both the reader and writer callback functions. If
           the user registered a whole range, then any number in the range will
           do, to unsubscribe to the whole range. */
        void (*unregister_pipe)(conf_object_t *obj, conf_object_t *user,
                                uint64 magic);

        /* Get a list of the subscribers for a magic number. The list can be
           filtered to include only readers or writers or both. If neither is
           specified only reservations are listed. */
        attr_value_t (*get_pipe_subscribers)(conf_object_t *obj, uint64 magic,
                                             bool readers, bool writers);

        /* Get a list of the used or reserved magic numbers. Each entry is a
           list of 5 items: minimum magic number, maximum magic number,
           registered subscriber object, reader callback present and writer
           callback present.

           EXAMPLE:
           [[0, 0, "fault_handler", TRUE, FALSE],
            [1, 1, "handshake", TRUE, TRUE],
            [0x10, 0x20, "my_magics", FALSE, FALSE],
            [0x4711, 0x4711, "cool_user", TRUE, TRUE]]

            The exact same information is available in the map attribute of the
            magic-pipe object. Most of the same information is also printed by
            the status command. */
        attr_value_t (*get_magic_map)(conf_object_t *obj);
};

#define MAGIC_PIPE_SETUP_INTERFACE "magic_pipe_setup"

Execution Context
Cell Context for all methods.

magic_pipe_writer

Description
An interface for writing transmit data to a magic pipe application running in the target system. This interface is called by a simics extension running in the host system which communicates with a target application through a magic pipe. The communication is identified by a magic number. These numbers are acquired or reserved in the magic_pipe_setup_interface.

The write functions operate on an unfragmented host system buffer. All C-code writer callback functions are allowed direct access to the unfragmented host buffer, while Python callback functions require the data to be copied from a Python owned data buffer.

The target system pipe buffer is not modified until all writer callbacks for its magic number have returned. Then the pipe buffer header is updated and the whole unfragmented host buffer is copied into the target pipe buffer fragments.

Note: This interface is an experimental feature. It is excluded from the standard support program, and is subject to change or removal without notice.
SIM_INTERFACE(magic_pipe_writer) {
        /* Query whether the simulated target system has a different byte-order
           than the simulator host system. */
        bool (*is_byte_swap_needed)(conf_object_t *obj, uintptr_t buf);

        /* Query how much unused space is available in the pipe buffer.  This
           value is decreased by each call to either write_data_add or
           write_data_copy. */
        size_t (*write_buffer_left)(conf_object_t *obj, uintptr_t buf);

        /* Query the allocated pipe buffer size. This value includes both the
           pipe buffer header and payload data. */
        size_t (*write_buffer_size)(conf_object_t *obj, uintptr_t buf);

#ifndef PYWRAP
        /* Get direct write access to the outgoing pipe buffer data. This call
           returns a pointer to the write position in the pipe buffer and its
           remaining unused size.

           If the caller writes to the pipe buffer, then the write_data_add
           function must be called also to update the amount of used data in
           the pipe buffer and advance the write position.

           The write position is also advanced by calls to the write_data_copy
           function. In case neither write_data_add nor write_data_copy
           function is called, this function will return the exact same pointer
           address and size all the time.

           This function gives a direct pointer into internal memory and
           therefore cannot be used by Python code. */
        buffer_t (*write_data_direct)(conf_object_t *obj, uintptr_t buf);

        /* Increase the amount of used data in the pipe buffer. When a caller
           to the write_data_direct function has written to the pipe buffer,
           the caller must also call this function to declare the amount of
           data written to the fragment. This will cause the write position to
           be moved to the next available space in the pipe buffer.

           If the length argument exceeds the available unused space. It is
           assumed that all the remaining space is used. */
        void (*write_data_add)(conf_object_t *obj, uintptr_t buf, size_t len);
#endif

        /* Append the data from the caller buffer to the outgoing pipe
           buffer. This function will copy as much of the data contents from
           the supplied buffer argument to the end of the pipe buffer as fits.

           The function will return the amount of data from the caller buffer
           that does not fit in the pipe buffer. If the return value is zero,
           then all data was copied. Otherwise the copied data was truncated
           and the remaining uncopied size is returned.

           Be sure to use the write_buffer_left function to determine the
           amount of remaining space, unless truncated data is desired and
           properly handled.

           This call will automatically advance the write position to the next
           unused space. */
        size_t (*write_data_copy)(conf_object_t *obj, uintptr_t buf,
                                  bytes_t data);

        /* Change the magic number in the pipe buffer. This is used to assign a
           new magic number to the target magic pipe application. Typically
           this is done only on the first exchange with a new target
           application, to give it a unique identifier, which is then
           subscribed to by the simics extension, and used throughout all
           further communication.

           The magic number to pick is typically returned by the
           register_new_pipe function in the setup interface. However, the
           simics extension may choose to reserve a range of magic numbers and
           provide its own scheme for assigning these to new target
           applications. */
        void (*write_buffer_magic)(conf_object_t *obj, uintptr_t buf,
                                   uint64 magic);
};

#define MAGIC_PIPE_WRITER_INTERFACE "magic_pipe_writer"

Execution Context
Cell Context for all methods.

memory_profiler

Description
The memory_profiler interface is implemented by processors that support memory profiling. The get function returns the active profiler for the type of access specified in the access argument. NULL or None is returned if there is no active profiler for that type of access.

The set function installs prof as a profiler for the accesses of type access. The set functions returns true if the setting was successful, and false otherwise.

The get_granularity_log2 gets the 2 logarithm of the profiling granularity in bytes, for example it returns 10 if the granularity for profiling is 1 KiB.

SIM_INTERFACE(memory_profiler) {
        conf_object_t *(*get)(conf_object_t *obj, read_or_write_t access);
        bool (*set)(conf_object_t *obj, read_or_write_t access,
                    conf_object_t *prof);
        int (*get_granularity_log2)(conf_object_t *obj);
};

#define MEMORY_PROFILER_INTERFACE "memory_profiler"

Execution Context
Cell Context for all methods.

mmc

Description
#define MMC_INTERFACE "mmc"
SIM_INTERFACE(mmc) {
#if !defined(PYWRAP)
        int (*send_command)(conf_object_t *obj, uint8 cmd, uint32 args,
                            buffer_t response);
        int (*read_data)(conf_object_t *obj, buffer_t data);
#endif
        int (*write_data)(conf_object_t *obj, bytes_t data);
};

Interface that should be implemented by all MMC/SD/SDHC/SDIO card models.

send_command: sends a 5-byte command to the card (1-byte command index and 4 bytes command arguments). Caller provides the response length. Card fills in actual response data. The response data is 0, 6 or 17 bytes, in big-endian (see the MMC/SD specification for details). Return value: number of response bytes, -1 if the command wasn't accepted (e.g. command is not supported or illegal in current state, or command is not supported or illegal for current card type).

read_data: reads data. Caller provides the length. Return value: the card fills in the provided buffer, and returns the number of bytes actually read, which might be less than the buffer length in case of error.

write_data: writes data. Caller provides in both length and data. Return value: number of bytes actually written, which might be less than the provided data length in case of error.

Execution Context
Cell Context for all methods.

mouse

Description
Interface used to send mouse events to a mouse device. The function mouse_event() takes the destination device as first argument in obj. The xmicro and ymicro arguments specified the relative mouse movement in micro-meters. If the mouse supports a wheel, the wheel movement is supplied in z, as number of steps up or down. The last argument buttons is a bit-mask with the state of the mouse buttons. The mapping of mouse buttons to bits is defined in the header file <simics/model-iface/sim-keys.h>.

SIM_INTERFACE(mouse) {
        void (*mouse_event)(conf_object_t *obj,
                            int xmicro,
                            int ymicro,
                            int z,
                            int buttons);
};

#define MOUSE_INTERFACE "mouse"

Execution Context
Cell Context for all methods.

opcode_info

Description
The opcode_info interface is implemented by processors that need to communicate information about the encoding of instructions to the GUI.

The get_opcode_length function returns information about instruction encoding in the current operating mode of the processor. The min_alignment field indicates the smallest allowed alignment of instructions, typically 4 for regular RISC architectures. The max_length field specifies the maximum instruction length in bytes. The avg_length is an approximation of the average instruction size.

typedef struct {
        int min_alignment;
        int max_length;
        int avg_length;
} opcode_length_info_t;

SIM_INTERFACE(opcode_info) {
        opcode_length_info_t (*get_opcode_length_info)(conf_object_t *obj);
};

#define OPCODE_INFO_INTERFACE "opcode_info"

Execution Context
Cell Context for all methods.

pre_decoder

Description
This interface extends the cpu_instrumentation_subscribe interface and allows a user to observe and change the bytes in the instruction stream before the target processor tries to decode them. This can be used to model data encryption of memory or instruction caches with different content than the memory.

It is currently offered as a separate interface for backwards compatibility, and only available for C/C++ development, i.e., no Python mapping exists. The interface is only implemented for x86 target processors.

The register_pre_decoder_cb method registers a callback, cb of type pre_decoder_cb_t, which is called before an instruction is decoded an put into Simics internal decode cache. This means that this callback is called only the first time an instruction is executed (unless it is evicted from the decode cache).

The cpu is the processor that decodes the instructions, and connection is the instrumentation connect object that receives the callback. The connection can be NULL, if no connection is available. The data is the callback data for the callback.

See the documentation for the pre_decoder_cb_t for more information.

To remove the callback use either remove_callback or remove_connection_callbacks methods in the cpu_instrumentation_subscribe interface. To identify the callback to remove, pass the return value, a cpu_cb_handle_t handle, from the register method or the connection object used. The callback cannot be disabled.

SIM_INTERFACE(pre_decoder) {
        cpu_cb_handle_t *(*register_pre_decoder_cb)(
                conf_object_t *cpu,
                conf_object_t *connection,
                pre_decoder_cb_t cb,
                lang_void *data);
};
#endif

#define PRE_DECODER_INTERFACE "pre_decoder"

Execution Context
Global context.

processor_cli

Description
Some commands and features in the CLI use the processor_cli interface. Those commands will have limited functionality if the interface is not fully implemented.

The first argument to each function is the object to act on. This object should implement both the processor_info interface and the processor_cli interface.

The get_disassembly function is used for the disassemble command as well as to disassemble the next instruction to be executed, when control is returned to the CLI prompt. For most architectures, get_disassembly can be set to NULL, in which case the command will use other interfaces to provide a generic disassembly. The get_disassembly function should return a tuple with the length of the instruction in bytes and the disassembly string. The addr_prefix parameter selects the address type of the address parameter, whether it is a physical address ("p"), a linear address ("l") or a virtual address ("v"), just as returned from get_address_prefix. The address parameter is the program counter for the instruction to disassemble. If print_cpu is non-zero, then the name of the processor should be included first in the disassembly line. If mnemonic is not NULL, then it should be output instead of the instruction disassemble. The mnemonic is used to print exception or interrupt information as returned by the get_pending_exception_string function.

get_pregs returns the string to output in the CLI for the print-processor-registers command. The all parameter is a boolean corresponding to the -all switch to the print-processor-registers command.

The diff_regs function is used by the stepi command when the -r flag is used. The diff_regs function returns a list of register names, where each register in that list will be read through the int_register interface before and after an instruction.

When returning to the CLI prompt, information about the next instruction or step to execute is printed. Normally, that is the disassemble of the instruction at the current program counter. The get_pending_exception_string function is called before the disassembly to find out if the next step will not be an instruction, but rather a taken exception or interrupt. The function should inspect the given cpu (an object implementing processor_info and processor_cli) and return NULL if the next step will be the execution of the instruction at the current program counter. If the next step will instead be the handling of an exception or interrupt, then a string saying that should be returned.

The get_address_prefix function returns a string with the default address prefix for memory related commands. Simics defines the generic prefixes "v" for virtual addresses, "l" for linear addresses, and "p" for physical addresses. The default if get_address_prefix is NULL is "v" for virtual addresses.

translate_to_physical translates an address to a physical address. If translate_to_physical is NULL, then the only allowed address prefixes are "v" (virtual) and "p" (physical), and the logical_to_physical function in the processor_info interface will be used to translate virtual addresses.

SIM_INTERFACE(processor_cli) {
	tuple_int_string_t (*get_disassembly)(conf_object_t *obj,
                                              const char *addr_prefix,
                                              generic_address_t address,
                                              bool print_cpu,
                                              const char *mnemonic);
	char *(*get_pregs)(conf_object_t *cpu,
                           bool all);
	attr_value_t (*get_diff_regs)(conf_object_t *obj);
	char *(*get_pending_exception_string)(conf_object_t *obj);
	char *(*get_address_prefix)(conf_object_t *obj);
	physical_block_t (*translate_to_physical)(conf_object_t *obj,
                                                  const char *prefix,
                                                  generic_address_t address);
};

#define PROCESSOR_CLI_INTERFACE "processor_cli"

Execution Context
Cell Context for all methods.

processor_endian

Description
This interface is used for retrieving endianness and amends to the processor_info_v2 interface.

Many modern processors support mixed endian as well as separate data and instruction endianness. This interface reports endianness separately for data and instructions dynamically, not just the default as for the processor_info_v2. Previously endianness has been static, with only one endianness. With newer ARM processors this may cause issues for some Big Endian use cases since Little Endian is assumed throughout. Primarily due to the fact that they can have separate data and instruction endianness. Modifying the existing processor_info_v2 easily gets complicated due to dependencies, so a new interface processor_endian was created.

The processor_endian_interface_t interface can be implemented by processors models and returns the current endianness of the system.

The function get_instruction_endian returns the active instruction endianness of the processor.

The function get_data_endian returns endianness of data.

SIM_INTERFACE(processor_endian) {
        cpu_endian_t (*get_instruction_endian)(conf_object_t *obj);
        cpu_endian_t (*get_data_endian)(conf_object_t *obj);
};

#define PROCESSOR_ENDIAN_INTERFACE "processor_endian"

Execution Context
get_instruction_endianCell Context
get_data_endianCell Context

processor_gui

Description
The processor_gui interface is implemented by processors that support displays in the Simics native GUI. It is only registered to indicate support for the displays, and does not contain any actual functionality.

SIM_INTERFACE(processor_gui) {
        void (*dummy)(conf_object_t *obj);
};

#define PROCESSOR_GUI_INTERFACE "processor_gui"

Execution Context
There are no methods in this interface.

processor_info

Description
An older version of the processor_info_v2 interface. See processor_info_v2 for more information.

SIM_INTERFACE(processor_info) {
        tuple_int_string_t (*disassemble)(conf_object_t *obj,
                                          generic_address_t address,
                                          attr_value_t instruction_data,
                                          int sub_operation);
        void (*set_program_counter)(conf_object_t *obj,
                                    logical_address_t pc);
        logical_address_t (*get_program_counter)(conf_object_t *obj);

        physical_block_t (*logical_to_physical)(conf_object_t *obj,
                                                logical_address_t address,
                                                access_t access_type);
        int (*enable_processor)(conf_object_t *obj);
        int (*disable_processor)(conf_object_t *obj);
        int (*get_enabled)(conf_object_t *obj);

        cpu_endian_t (*get_endian)(conf_object_t *obj);
        conf_object_t *(*get_physical_memory)(conf_object_t *obj);

        int (*get_logical_address_width)(conf_object_t *obj);
        int (*get_physical_address_width)(conf_object_t *obj);

        const char *(*architecture)(conf_object_t *obj);
};

#define PROCESSOR_INFO_INTERFACE "processor_info"

Execution Context
Cell Context for all methods.

processor_info_v2

Description
The processor_info_v2 interface is implemented by processors models. The interface has processor generic functions that are architecture independent.

The disassemble function returns the disassemble string for an instruction at address with opcode according to instruction_data. The instruction_data is an attr_value_t value of data type with the bytes of the opcode. The bytes are in the same order as they are stored in memory. For VLIW architectures, sub_operation is used to select which sub-operation to disassemble. The sub-operations start at zero, and a request for the entire unit including all sub-operations is encoded with sub-operation -1. A request for a sub-operation that is not present (for example when sub-operation is neither 0 nor -1 for non-VLIW architectures) results in the integer part of the return tuple being set to zero. If successful, the function should return a tuple with the size of the instruction in bytes and the disassembly string. The disassembly string should be allocated with MM_MALLOC or similar and is to be freed by the caller. If more bytes are needed, then the function should indicate that by returning a negative number in the tuple where the absolute value of the number is the required number of bytes. The string should be NULL if more bytes are needed. The implementor of processor_info_v2 is allowed to request one additional byte at a time until enough bytes are passed to determine what the instruction is. Illegal instructions should still result in a valid returned tuple, where the integer part will be used by the disassemble command to skip that many bytes before disassembling the next instruction. The address can be used to display absolute destinations of program counter relative branches.

The set_program_counter function sets the program counter in the processor. The get_program_counter function returns the current program counter.

The logical_to_physical function translates a logical address to a physical address of the type defined by access_type. The function returns a physical_block_t struct with valid bit and the address. The address is valid when the valid bit is not 0. The logical_to_physical function also returns block_start and block_end. The start and end of a block has the same logical to physical transformation as the translated address. The range is inclusive, so block_end should be the address of the last byte of the block. This information can be used to figure out how often the logical_to_physical function needs to be called. An implementation would typically return the page start and end here, but it is free to return any power of 2 sized block as long as it includes the translated address.

The current operating mode of the processor is returned with get_processor_mode.

The processor can be enabled or disabled with the enable_processor or disable_processor functions. The functions should return 0 if the processor changed from enabled to disabled or from disabled to enabled, and 1 if the processor did not change state. The current state is returned by the get_enabled function. Enabled or disabled here refers to the state that the user of the model has put the processor into. In particular, it is independent of the power mode of the processor. A processor that has powered down does not count as disabled in this sense, nor does the enable_processor wake up a processor that is in a power-saving sleep state.

The endianness of the processor is returned by the get_endian function.

The physical memory object is returned by the get_physical_memory function. The object returned by get_physical_memory is used to set breakpoints by the global break command, and to read and write physical memory through set, get, load-binary, load-file, and the default implementation of disassemble. The object returned implements the memory_space and breakpoint interfaces. The memory_space interface for the returned object is only be used in inquiry mode corresponding to actions by the simulator itself rather than by the simulated software. An implementation may return NULL from this method, which will lead to the command listed above not being supported when such a processor is selected.

The get_logical_address_width function returns the number of logical/virtual address bits and the get_physical_address_width function returns the number of physical address bits.

The processor architecture is returned by calling the architecture function. The architecture should be one of arm, mips32, mips64, ppc32, ppc64, sparc-v8, sparc-v9, x86, x86-64, or something else if none of the listed is a good match.

All functions in the interface are optional. Each function can be set to NULL if it is not supported.

SIM_INTERFACE(processor_info_v2) {
        tuple_int_string_t (*disassemble)(conf_object_t *obj,
                                          generic_address_t address,
                                          attr_value_t instruction_data,
                                          int sub_operation);
        void (*set_program_counter)(conf_object_t *obj,
                                    logical_address_t pc);
        logical_address_t (*get_program_counter)(conf_object_t *obj);
        physical_block_t (*logical_to_physical)(conf_object_t *obj,
                                                logical_address_t address,
                                                access_t access_type);
        processor_mode_t (*get_processor_mode)(conf_object_t *obj);
        int (*enable_processor)(conf_object_t *obj);
        int (*disable_processor)(conf_object_t *obj);
        int (*get_enabled)(conf_object_t *obj);

        cpu_endian_t (*get_endian)(conf_object_t *obj);
        conf_object_t *(*get_physical_memory)(conf_object_t *obj);

        int (*get_logical_address_width)(conf_object_t *obj);
        int (*get_physical_address_width)(conf_object_t *obj);

        const char *(*architecture)(conf_object_t *obj);
};

#define PROCESSOR_INFO_V2_INTERFACE "processor_info_v2"

Note that the original version of this interface (processor_info) must also be implemented. The only difference between the two interfaces is that the original version lacks the get_processor_mode function.

Execution Context
disassembleCell Context
set_program_counter Global Context (with some additions; see below)
get_program_counterCell Context
logical_to_physicalCell Context
get_processor_modeCell Context
enable_processorCell Context
disable_processorCell Context
get_enabledCell Context
get_endianCell Context
get_physical_memoryCell Context
get_logical_address_width Cell Context
get_physical_address_width Cell Context
architectureCell Context

It is explicitly permitted to call set_program_counter from inside an execution breakpoint handler.

ram_access_subscribe

Description

This interface is used to register callbacks to instrument ram/rom accesses.

The register_access_before_cb method registers a callback that is called before any memory access reached the backing storage in a ram/rom image. This makes it possible to modify the transaction before it reaches its destination. See the documentation of the ram_access_cb_t type for more information. A ram_cb_handle_t pointer is returned as a reference to the callback.

The register_access_after_cb method registers a callback that is called after any memory access has reached the backing storage in a ram/rom image. This makes it possible to modify the transaction after the access is completed. See the documentation of the ram_access_cb_t type for more information. A ram_cb_handle_t pointer is returned as a reference to the callback.

Both of these register callbacks above will receive all types of accesses, read, write, or execute, from any initiator hitting any address range. It is up to the callback to filter the information if needed, e.g., to only trace read accesses. Normally, ram/rom pages can be cached in object using them by using the direct_memory_lookup interface. This caching must be blocked by this interface to allow the callbacks to be called. This has severe impact on simulation speed. However, the following method should be used to allow caching for accesses that the callbacks have no interest in.

The register_access_filter_cb method can be used to register a function callback that allows ram/rom pages to be cached by a user of the direct_memory_lookup interface. If caching is allowed the access may be invisible to the callbacks installed by register_access_before_cb and register_access_after_cb methods above. Even if an access is allowed to be cached it does not mean that it will be, which means that the callbacks can be called anyway.

See the documentation of the access_filter_cb_t type for more information about the callback and how to allow caching. A ram_cb_handle_t pointer is returned as a reference to the callback.

The remove_callback method removes an earlier installed callback. The handle is used to identify the callback to be removed. All register function above returns such handle.

The enable_callback and disable_callback methods temporarily enables and disables a previously installed callback. The handle is used to identify the callback. All register function above returns such handle.

SIM_INTERFACE(ram_access_subscribe) {
        void (*remove_callback)(conf_object_t *NOTNULL obj,
                                ram_cb_handle_t *handle);
        void (*enable_callback)(conf_object_t *NOTNULL obj,
                                ram_cb_handle_t *handle);
        void (*disable_callback)(conf_object_t *NOTNULL obj,
                                 ram_cb_handle_t *handle);
        ram_cb_handle_t *(*register_access_before_cb)(
                conf_object_t *NOTNULL obj,
                conf_object_t *conn_obj,
                ram_access_cb_t cb,
                lang_void *data);
        ram_cb_handle_t *(*register_access_after_cb)(
                conf_object_t *NOTNULL obj,
                conf_object_t *conn_obj,
                ram_access_cb_t cb,
                lang_void *data);
        ram_cb_handle_t *(*register_access_filter_cb)(
                conf_object_t *NOTNULL obj,
                conf_object_t *connection,
                access_filter_cb_t cb,
                lang_void *data);
};

#define RAM_ACCESS_SUBSCRIBE_INTERFACE "ram_access_subscribe"

Execution Context
Global Context for all methods.

simple_timing_v2

Description
=============================================

TECH-PREVIEW

This interface may change without notice.

=============================================

The simple_timing_v2 interface is used to send information about timing, instructions executed and activity factor from timing models to power and temperature models. It should be implemented by the consumer of the data.

The period that is covered by a call is called a heartbeat. The length of that period may vary between calls.

When a core has completed a heartbeat new_active_data is called and when a period of idleness has passed new_idle_data is called.

The core argument is the core the performance data comes from.

The time argument is the virtual time of the core at the end of the heartbeat.

The frequency argument is what the core frequency was set to at the time of the call.

The cycles argument is the number of cycles in the heartbeat.

The ipc argument is average ipc during this heartbeat.

The cdyn argument is average activity factor during the heartbeat.

The version_data argument can be a NULL or a pointer to simple json-string that can contain information about the performance model.

Note: Temporal decoupling may cause calls regarding different cores to come out of order with regards to virtual time.

Time during heartbeat may not add up with time passed since last call on a particular core, especially when cores goes in and out of idle-mode.

To use the simple_timing_v2 add the following EXTRA_MODULE_VPATH := simple-timing-interface to the modules Makefile.

#define SIMPLE_TIMING_V2_MAX_NR_EVENTS  120

SIM_INTERFACE(simple_timing_v2) {
        bool (*new_active_data)
                (conf_object_t *obj,
                 double time,
                 conf_object_t *core,
                 uint64 frequency,

                 cycles_t cycles,
                 double ipc,
                 double cdyn,

                 char const *version_data);

        bool (*new_idle_data)
                (conf_object_t *obj,
                 double time,
                 conf_object_t *core,
                 uint64 frequency,
                 cycles_t cycles);
};

#define SIMPLE_TIMING_V2_INTERFACE "simple_timing_v2"

Execution Context
Called from performance models.

simulator_cache

Description
The simulator_cache interface is optionally implemented by processors. The interface can be used for translate objects to force a flush of the internal caches in a processor model, if a memory area that it previously allowed for caching is not valid anymore.

SIM_INTERFACE(simulator_cache) {
        void (*flush)(conf_object_t *obj);
};
#define SIMULATOR_CACHE_INTERFACE "simulator_cache"

Execution Context
flushCell Context

snoop_memory

Description
This interface is described with the timing_model interface.
Execution Context
Cell Context for all methods.

stall

Description
The stall interface can be implemented by objects that also implement the cycle and step interfaces. The stall interface controls the addition of extra cycles between steps.

The get_stall_cycles function returns the remaining number of stall cycles. The object will advance that number of cycles before starting with the next step.

The set_stall_cycles function is used to change the number of stall cycles before the next step. It is legal to first call this function with a large value for cycles and then at a later point reduce the cycle count is resume execution earlier than indicated by the first call.

The get_total_stall_cycles returns the total accumulated number of stall cycles.

SIM_INTERFACE(stall) {
        cycles_t (*get_stall_cycles)(conf_object_t *obj);
        void (*set_stall_cycles)(conf_object_t *obj, cycles_t cycles);
        cycles_t (*get_total_stall_cycles)(conf_object_t *obj);
};
#define STALL_INTERFACE "stall"

Execution Context
Cell Context for all methods.

step

Description
The step interface is typically implemented by processors, but can be implemented by other objects as well. Its purpose is to handle step events using a queue.

The current number of steps for the queue is returned when calling get_step_count.

The post_step function will schedule an event that will occur after steps (which must be nonnegative) counted from local current step at queue. An event previously posted can be removed by calling cancel_step. The cancel_step function takes a function pred as argument which is called when a matching event is found. The event is only removed if pred returns 1. The find_next_step takes the same arguments as cancel_step but only returns the number of cycles before the event will occur. The evclass is the event class, obj is the object posting the event, and user_data is pointer to data used as a parameter when calling the callback function defined in the evclass. If no matching event was found, find_next_step returns −1.

The events method returns a list of all pending events in expiration order. Each element is a four-element list containing the event object, the event class name, the expiration time counted in steps as an integer and the event description as given by the event class describe method, or nil for events whose event class do not define that method.

The advance function will increment the number of steps for the queue, decrementing the number of steps to the first event to the value defined by steps. The number of steps remaining to the next event is returned. It is an error to advance beyond the next pending event, so the return value is never negative.

The implementor of the step interface can use any checkpoint representation. The name field in the event class data structure is unique, and the attribute setter function for checkpoint restore can use SIM_get_event_class to get the event class structure corresponding to an event class name.

SIM_INTERFACE(step) {
        pc_step_t (*get_step_count)(conf_object_t *NOTNULL queue);
        void (*post_step)(
                conf_object_t *NOTNULL queue,
                event_class_t *NOTNULL evclass,
                conf_object_t *NOTNULL obj,
                pc_step_t steps,
                lang_void *user_data);
        void (*cancel_step)(
                conf_object_t *NOTNULL queue,
                event_class_t *NOTNULL evclass,
                conf_object_t *NOTNULL obj,
                int (*pred)(lang_void *data, lang_void *match_data),
                lang_void *match_data);
        pc_step_t (*find_next_step)(
                conf_object_t *NOTNULL queue,
                event_class_t *NOTNULL evclass,
                conf_object_t *NOTNULL obj,
                int (*pred)(lang_void *data, lang_void *match_data),
                lang_void *match_data);

        attr_value_t (*events)(conf_object_t *NOTNULL obj);

        pc_step_t (*advance)(conf_object_t *queue, pc_step_t steps);
};

#define STEP_INTERFACE "step"

Execution Context
Cell Context for all methods.

step_cycle_ratio

Description
The step_cycle_ratio interface is implemented by processors that support a changeable ratio between steps and cycles. The set-step-rate command uses this interface to set the ratio between steps and cycles.

The set_ratio sets the ratio between steps and cycles. Note that the introduction of stall cycles can skew the ratio. The get_ratio simply returns the current ratio.

The cycles and step arguments must be in the range [1..128] and cycles must be a power of two. Implementers of this interface may choose to ignore other values of cycles and step and may log an error.

typedef struct {
        uint32 steps;
        uint32 cycles;
} step_cycle_ratio_t;

SIM_INTERFACE(step_cycle_ratio) {
        step_cycle_ratio_t (*get_ratio)(conf_object_t *obj);
        void (*set_ratio)(conf_object_t *obj, uint32 steps, uint32 cycles);
};

#define STEP_CYCLE_RATIO_INTERFACE "step_cycle_ratio"

Execution Context
Cell Context for all methods.

step_event_instrumentation

Description
This interface is internal.
Execution Context
Global Context.

step_info

Description
The step_info interface can be implemented by processors that optimize the execution by advancing the step count using special instructions or processor modes.

The get_halt_steps and set_halt_steps functions are used to get and set the number of steps that have been advanced using special features in the architecture. Examples; X86 processor it is the number of halt instructions executed, PPC processors it is the number of steps spent in sleep mode, ARM processors it is the number of steps spent in the "wait for interrupt" state.

The get_ffwd and set_ffwd_steps functions are used to get and set the number of steps that the processor have optimized the execution by advancing time that is not architectural. This can for instance be execution loops that does not affect the processor state.

SIM_INTERFACE(step_info) {
        pc_step_t (*get_halt_steps)(conf_object_t *obj);
        void (*set_halt_steps)(conf_object_t *obj, pc_step_t steps);
        pc_step_t (*get_ffwd_steps)(conf_object_t *obj);
        void (*set_ffwd_steps)(conf_object_t *obj, pc_step_t steps);
        pc_step_t (*get_ma_steps)(conf_object_t *obj);
        void (*set_ma_steps)(conf_object_t *obj, pc_step_t steps);
};
#define STEP_INFO_INTERFACE "step_info"

Execution Context
Cell Context for all methods.

synchronous_mode

Description
Experimental, may change without notice.

SIM_INTERFACE(synchronous_mode) {
        int (*enter)(conf_object_t *NOTNULL obj);
        int (*leave)(conf_object_t *NOTNULL obj);
};
#define SYNCHRONOUS_MODE_INTERFACE "synchronous_mode"

Execution Context
Cell Context

temporal_state

Description
Deprecated interface. Use global notifiers and/or attributes instead.

This interface was used to save micro checkpoints for reverse execution. It remains in 7, but is only used to get notifications when an object's state is about to be restored, or has just been restored.

All functions in this interface are optional.

The save and merge functions are never called.

The function prepare_restore is called when a saved state is about to be loaded, before any attributes have been set.

The finish_restore function is called when all attributes have been set. The state argument is always NULL.

SIM_INTERFACE(temporal_state) {
        lang_void *(*save)(conf_object_t *obj);
        void (*merge)(conf_object_t *obj, lang_void *prev, lang_void *killed);
        void (*prepare_restore)(conf_object_t *obj);
        void (*finish_restore)(conf_object_t *obj, lang_void *state);
};

#define TEMPORAL_STATE_INTERFACE "temporal_state"

Execution Context
Cell Context for all methods.

timing_model

Description
The timing_model interface is used to communicate stall times for memory accesses. It is typically exported by cache models. The operate() function is then called on every memory access that misses in the STC, and the return value from the call is the number of cycles to stall.

The snoop_memory interface has the exact same layout as the timing_model interface, but its operate() function is called after the memory access has been performed. The return value from the operate() function of a snoop_memory interface is ignored.

The operate function is invoked via the timing_model attribute of the memory-space where the STC miss happens.

See the Model Builder User's Guide for more information on how to use these interfaces.

SIM_INTERFACE(timing_model) {
        cycles_t (*operate)(conf_object_t *NOTNULL mem_hier,
                            conf_object_t *NOTNULL space,
                            map_list_t *map_list,
                            generic_transaction_t *NOTNULL mem_op);
};

#define TIMING_MODEL_INTERFACE "timing_model"

SIM_INTERFACE(snoop_memory) {
        cycles_t (*operate)(conf_object_t *NOTNULL mem_hier,
                            conf_object_t *NOTNULL space,
                            map_list_t *map_list,
                            generic_transaction_t *NOTNULL mem_op);
};

#define SNOOP_MEMORY_INTERFACE "snoop_memory"
        

Execution Context
Cell Context for all methods.

transaction

Description

The transaction interface is implemented by devices that can be mapped into address spaces. The issue method is called when a memory transaction t is issued to the object.

The return value of the issue function is normally Sim_PE_No_Exception, but other pseudo exception_type_t values can be used to signal error conditions. The value Sim_PE_Deferred must be used when the transaction has been deferred using SIM_defer_transaction for completion at some later time.

SIM_INTERFACE(transaction) {
        exception_type_t (*issue)(
                conf_object_t *NOTNULL obj,
                transaction_t *NOTNULL t,
                uint64 addr);
};
#define TRANSACTION_INTERFACE  "transaction"

Execution Context
Cell Context for all methods.

transaction_subscribe

Description

Note: this interface is internal and may change without notice.

This interface is used to register callbacks to instrument transactions issued through a map target by the SIM_issue_transaction API call. This includes all memory_space objects handling transactions. The interface is only implemented by the sim.transactions object which serves all transactions.

The register_issue_cb method registers a callback that is called whan a transaction is passed to a map target. This makes it possible to modify or replace the transaction before it reaches its destination. See the documentation of the transaction_issue_cb_t type for more information on now to handle the transaction.

A transaction_cb_handle_t pointer is returned as a reference to the callback.

The registered callbacks above will receive all types of accesses, read, write, or execute, from any initiator hitting any address range. It is up to the callback to filter the information if needed, e.g., to only trace read accesses.

If more than one cell is used and multithreading is enabled, more that one callback can be issued at the same time.

Normally, for transactions to ram/rom, these accesses can be bypassed by caching the destination object by using the direct_memory_lookup interface. Then these accesses cannot be monitored by the transaction_subscribe interface. However, it is possible to block this caching by using the register_access_filter_cb method of the ram_access_subscribe interface. This has typically severe impact on simulation speed, but allows user to monitor all transactions in the system. Note however that a real systems also reduces the transactions to memory by using caches, which normally is not modeled by Simics,

The remove_callback method removes an earlier installed callback. The handle is used to identify the callback to be removed. The register functions above return such handle.

The enable_callback and disable_callback methods temporarily enables and disables a previously installed callback. Note that this will not necessary speed up the simulation, since the caching may be blocked anyway. The handle is used to identify the callback. The register functions above return such handle.

SIM_INTERFACE(transaction_subscribe) {
        void (*remove_callback)(conf_object_t *NOTNULL obj,
                                transaction_cb_handle_t *handle);
        void (*enable_callback)(conf_object_t *NOTNULL obj,
                                transaction_cb_handle_t *handle);
        void (*disable_callback)(conf_object_t *NOTNULL obj,
                                 transaction_cb_handle_t *handle);
        transaction_cb_handle_t *(*register_issue_cb)(
                conf_object_t *NOTNULL obj,
                conf_object_t *conn_obj,
                transaction_issue_cb_t cb,
                lang_void *data);
};

#define TRANSACTION_SUBSCRIBE_INTERFACE "transaction_subscribe"

Execution Context
Outside execution context for all methods.

tsc_update

Description
The methods allow to update/overwrite Time Stamp Counter with values coming from PUnit and measured in different units.

load_tsc_from_xtal sets TSC to an absolute value scaled from the xtal_value. The latter value is measured in units of always running timer clocks.

SIM_INTERFACE(tsc_update) {
        void (*load_tsc_from_xtal)(conf_object_t *obj, uint64 xtal_value);
};

Execution Context
Cell Context for all methods.

uint64_state

Description
Interface to transfer a state representable in an uint64 from one device to another. Examples of what the state might represent includes:

  • a fixed-point value representing the level of an analog signal
  • an integer representing a counter
  • an integer representing an enum value
  • The initiator should call set when the value changes, and after a new target is connected. The object implementing uint64_state should accept multiple calls to set with the same level, and may let this trigger side-effects. Therefore, any repeated calls must be deterministic; in particular, set must not be called while restoring a checkpoint.

    A device implementing this interface may choose to only accept a certain set of integer values; it is then an error to send any other values to the set method. A user must therefore be careful to read the documentation of both the source and destination object to make sure they are compatible.

    No interface call needs to be done after disconnecting a target; the target needs to be notified of this through some other channel (typically via a connector)

    Note: The uint64_state interface should be used instead of the deprecated multi_level_signal interface when writing new models.
    SIM_INTERFACE(uint64_state) {
            void (*set)(conf_object_t *NOTNULL obj, uint64 level);
    };
    #define UINT64_STATE_INTERFACE "uint64_state"
    

    Execution Context
    Cell Context for all methods.

    vga_text_info

    Description
    The vga_text_info interface facilitates the graphics console to obtain information about displayed text from its attached VGA device, when the video mode is a VGA text mode. This interface must be implemented by VGA devices that are attached to the graphics console.

    The text_mode method indicates whether the current video mode is a VGA text mode.

    If the current video mode is not a VGA text mode, all other methods have no effect, and will return false. Otherwise they return true and behaves as follows:

    The font_size method sets width and height to the current font size.

    The screen_size method sets columns and rows to the current screen size.

    The text method retrieves the screen text data and line lengths. The text parameter must be a buffer with size at least columns * rows, as given by screen_size. Similarly, the line_length parameter must be a buffer of length rows.

    SIM_INTERFACE(vga_text_info) {
            bool (*text_mode)(conf_object_t *NOTNULL obj);
            bool (*font_size)(conf_object_t *NOTNULL obj, int *width, int *height);
            bool (*screen_size)(conf_object_t *NOTNULL obj,
                                int *columns, int *rows);
            bool (*text)(conf_object_t *NOTNULL obj,
                         uint8 *text, uint8 *line_lengths);
    };
    #define VGA_TEXT_INFO_INTERFACE "vga_text_info"
    

    Execution Context
    Cell Context for all methods.

    vga_text_update

    Description
    The vga_text_update interface facilitates defining an input character stream for graphics consoles. The video device associated to a graphics console can use this interface to send a stream of characters to the console. This stream is used by the graphics console break strings. The stream should match the displayed VGA text whenever possible.

    SIM_INTERFACE(vga_text_update) {
            void (*write)(conf_object_t *NOTNULL obj, char value);
    };
    #define VGA_TEXT_UPDATE_INTERFACE "vga_text_update"
    

    Execution Context
    Cell Context

    vga_update

    Description
    The vga_update interface facilitates the graphics console to request screen redraw from its attached video device, which typically happens on every frame update event. This interface must be implemented by video devices that are attached to the graphics console. The implementation should call functions in the gfx_con interface, e.g. a sequence of put_block() calls followed by redraw(), which is implemented by the graphics console.

    The refresh method requests the video device to redraw dirty parts of the screen. The refresh_all method requests the video device to redraw the whole screen.

    SIM_INTERFACE(vga_update) {
            void (*refresh)(conf_object_t *NOTNULL obj);
            void (*refresh_all)(conf_object_t *NOTNULL obj);
    };
    #define VGA_UPDATE_INTERFACE "vga_update"
    

    Execution Context
    Cell Context for all methods

    virtual_data_breakpoint

    Description
    Add and remove virtual-address (and, on x86, linear-address) read and write breakpoints. On every read access that intersects a read breakpoint's interval, the registered callback function is called with the object that initiated the read, and the address and size of the read. (The interval includes both endpoints; first must be less than or equal to last.) Write breakpoints work exactly the same, except that the callback is given the actual value being written, not just its size.

    The callback is called before the read or write has taken place, but may not intervene. If one or more breakpoint callbacks stop the simulation, the current instruction is completed before the stop takes effect. If more than one breakpoint is triggered by the same read or write, the implementation may call their callbacks in any order.

    On x86, the Virtual_Breakpoint_Flag_Linear flag causes the breakpoint to use linear rather than virtual addresses. (Adding a breakpoint with unsupported flags is illegal.)

    Note: This interface is preliminary and may change without prior notice.
    typedef enum {
            Virtual_Breakpoint_Flag_Linear = 1
    } virtual_breakpoint_flags_t;

    SIM_INTERFACE(virtual_data_breakpoint) {
            virtual_data_bp_handle_t *NOTNULL (*add_read)(
                    conf_object_t *NOTNULL obj,
                    generic_address_t first, generic_address_t last,
                    void (*NOTNULL callback)(
                            cbdata_call_t data, conf_object_t *NOTNULL initiator,
                            generic_address_t address, unsigned size),
                    cbdata_register_t data, uint32 flags);
            virtual_data_bp_handle_t *NOTNULL (*add_write)(
                    conf_object_t *NOTNULL obj,
                    generic_address_t first, generic_address_t last,
                    void (*NOTNULL callback)(
                            cbdata_call_t data, conf_object_t *NOTNULL initiator,
                            generic_address_t address, bytes_t value),
                    cbdata_register_t data, uint32 flags);
            void (*remove)(conf_object_t *NOTNULL obj,
                           virtual_data_bp_handle_t *NOTNULL bp_handle);
    };
    #define VIRTUAL_DATA_BREAKPOINT_INTERFACE "virtual_data_breakpoint"
    

    Execution Context
    Cell Context for all methods.

    virtual_instruction_breakpoint

    Description
    Add and remove virtual-address (and, on x86, linear-address) instruction breakpoints. Every time the processor executes an instruction that intersects the breakpoint's interval, the callback function is called with the processor, and the address and size of the instruction. (The interval includes both endpoints; first must be less than or equal to last.)

    The callback is called before the instruction is executed. If one or more breakpoint callbacks stop the simulation, the stop takes effect before the instruction is run. (This means that once the simulation starts again, the same breakpoints will trigger immediately again. The callback can use VT_step_stamp to detect re-triggering.) If more than one breakpoint is triggered by the same instruction, the implementation may call their callbacks in any order.

    If the filter function is non-null and returns false, the callback is not called. The filter function is supplied with the instruction opcode (the raw bytes of the instruction) and a processor (which may not be the same processor that the breakpoint is set on, but is guaranteed to be of the same class). The filter may base its decision only on the opcode bytes and the string obtained by asking the processor to disassemble the instruction; this allows the implementation to cache the result and omit future calls to the filter function where the opcode and disassembly string would be the same.

    On x86, the Virtual_Breakpoint_Flag_Linear flag causes the breakpoint to use linear rather than virtual addresses. Calling with unsupported flags is illegal.

    Note: This interface is preliminary and may change without prior notice.
    typedef enum {
            Virtual_Breakpoint_Flag_Linear = 1
    } virtual_breakpoint_flags_t;

    SIM_INTERFACE(virtual_instruction_breakpoint) {
            virtual_instr_bp_handle_t *NOTNULL (*add)(
                    conf_object_t *NOTNULL obj,
                    generic_address_t first, generic_address_t last,
                    bool (*filter)(cbdata_call_t filter_data,
                                   conf_object_t *NOTNULL cpu, bytes_t opcode),
                    cbdata_register_t filter_data,
                    void (*NOTNULL callback)(
                            cbdata_call_t callback_data, conf_object_t *NOTNULL cpu,
                            generic_address_t address, unsigned size),
                    cbdata_register_t callback_data, uint32 flags);
            void (*remove)(conf_object_t *NOTNULL obj,
                           virtual_instr_bp_handle_t *NOTNULL bp_handle);
    };
    #define VIRTUAL_INSTRUCTION_BREAKPOINT_INTERFACE \
            "virtual_instruction_breakpoint"
    

    Execution Context
    Cell Context for all methods.

    x86_monitor

    Description
    This interface is meant to be implemented by an uncore device to support implementation of MONITOR/MWAIT instruction pair. A listener (e.g. a cpu) uses this interface to setup monitored write-back memory range. All listeners subscribed to a particular write-back memory range will be notified via x86_monitor_notification_interface when a memory write transaction hits the monitored memory range.

    This interface is internal and may change without notice.

    The arm method is to subscribe for notifications about writes to a write-back memory range starting from start_address up to start_address + length - 1 , returns true on success. The disarm unsubscribes listener, so the latter won't be notified about writes to a monitored memory range, returns true on success.

    SIM_INTERFACE(x86_monitor) {
        bool (*arm)(conf_object_t *obj, conf_object_t *listener,
                    physical_address_t start_address, physical_address_t length);
        bool (*disarm)(conf_object_t *obj, conf_object_t *listener);
    };
    
    #define X86_MONITOR_INTERFACE "x86_monitor"
    

    Execution Context
    Cell Context for all methods.

    x86_monitor_notification

    Description
    This interface is meant to be implemented by a processor to support complex cases of MONITOR/MWAIT instruction pair. A processor will be notified about writes to the monitored write-back memory range through the notify method. The return value indicates whether to unsubscribe from notifications or not. See x86_monitor_interface_t to find out how to subscribe for write notifications to a write-back memory range.
    SIM_INTERFACE(x86_monitor_notification) {
            bool (*notify)(conf_object_t *obj);
    };
    
    #define X86_MONITOR_NOTIFICATION_INTERFACE "x86_monitor_notification"
    

    Execution Context
    Cell Context.

    x86_rar_interrupt

    Description
    Methods of this interface are used to provide CPU with information about RAR interrupt status from APIC

    The is_rar_requested method returns whether a RAR event is pending.

    The ack_rar method acknowledges RAR interrupt.

    SIM_INTERFACE(x86_rar_interrupt) {
        bool (*is_rar_requested)(conf_object_t *obj);
        int (*ack_rar)(conf_object_t *obj);
    };
    #define X86_RAR_INTERRUPT_INTERFACE "x86_rar_interrupt"
    

    Execution Context
    Cell Context for all methods.

    x86_smm_notification

    Description
    Objects registered in processor's smm_listeners attribute will be called via the notification method whenever the CPU's enters and leaves SMI handler. SMI handler entry occurs on SMI processing. SMI handler exit occurs by RSM instruction execution. Please note that for both SMI handler entry and SMI handler exit notification method will be invoked twice: at the beginning of the entry/exit and at the end when CPU state was already modified. event argument says if entry/exit is performed, phase argument equals to X86_Smm_Phase0 for the beginning of the event and to X86_Smm_Phase1 for the end.

    typedef enum x86_smm_event_type {
        X86_Smm_Enter,
        X86_Smm_Leave
    } x86_smm_event_type_t;

    typedef enum x86_smm_phase_type {
        X86_Smm_Phase0,
        X86_Smm_Phase1
    } x86_smm_phase_type_t;

    SIM_INTERFACE(x86_smm_notification) {
            void (*notification)(conf_object_t *listener, conf_object_t *cpu,
                                 x86_smm_event_type_t event,
                                 x86_smm_phase_type_t phase);
    };
    #define X86_SMM_NOTIFICATION_INTERFACE "x86_smm_notification"
    

    Execution Context
    Cell Context.

    x86_unplug

    Description
    The methods of the interface are intended to be used by a platform to unplug (and optionally re-plug) CPU cores/threads, effectively hiding them from the #RESET/INIT signals.

    This interface is internal and may change without notice.

    The unplug_core method is to disable an operating core with all threads on it. The replug_core method is to enable a core previously unplugged with all threads on it. The disable_ht_package method is to disable every secondary thread. The enable_ht_package method is to enable every secondary thread.

    Values returned from these methods indicate success (1) or failure (0).

    SIM_INTERFACE(x86_unplug) {
            int (*unplug_core)(conf_object_t *obj);
            int (*replug_core)(conf_object_t *obj);
            int (*disable_ht_package)(conf_object_t *obj);
            int (*enable_ht_package)(conf_object_t *obj);
    };
    #define X86_UNPLUG_INTERFACE "x86_unplug"
    

    Execution Context
    Cell Context for all methods.

    x86_unplug_v2

    Description
    The methods of the interface are intended to be used by a platform to unplug (and optionally re-plug) CPU cores/threads, effectively hiding them from the #RESET/INIT signals.

    This interface is internal and may change without notice.

    The unplug_core method is to disable an operating core with all threads on it. The replug_core method is to enable a core previously unplugged with all threads on it. The disable_core_ht method is to disable HT in the core (not the package). The enable_core_ht method is to enable HT in the core (not the package). The core_is_plugged method returns true if core is plugged. The core_ht_is_enabled method returns true if HT is enabled in the core (not the package). The set_alive_logical_processors method updates number of alive processors reported through CPUID. The get_alive_logical_processors method returns number of alive processors reported through CPUID.

    Values returned from enable and disable methods indicate success (1) or failure (0).

    SIM_INTERFACE(x86_unplug_v2) {
            int (*unplug_core)(conf_object_t *obj);
            int (*replug_core)(conf_object_t *obj);
            int (*disable_core_ht)(conf_object_t *obj);
            int (*enable_core_ht)(conf_object_t *obj);
            bool (*core_is_plugged)(conf_object_t *obj);
            bool (*core_ht_is_enabled)(conf_object_t *obj);
            void (*set_alive_logical_processors)(conf_object_t *obj, int count);
            int (*get_alive_logical_processors)(conf_object_t *obj);
    };
    #define X86_UNPLUG_V2_INTERFACE "x86_unplug_v2"
    

    Execution Context
    Cell Context for all methods.

    6 Simulator API

    The Simics Simulator API completes the Device API defined in the Model Builder product to give full access to the Simics API from user-written extensions, in DML, Python or C/C++. The Simulator API is the same in all languages but the syntax of the types and functions declarations will of course differ.

    6.1 Simulator API Data Types

    6.1.1 Generic Data Types

    addr_prof_iter_t

    NAME
    addr_prof_iter_t
    SYNOPSIS
    typedef struct addr_prof_iter {
            uint64 (*next)(struct addr_prof_iter *i);
            void (*destroy)(struct addr_prof_iter *i);
            generic_address_t addr;
    } addr_prof_iter_t;

    DESCRIPTION
    An address profile iterator will iterate over a specified portion of the address space in some unspecified order, and return every nonzero counter value exactly once. When done, it will return 0.

    6.2 Simulator API Functions

    Breakpoints

    SIM_break_cycle()

    NAME
    SIM_break_cycle — insert breakpoint in time queue
    SYNOPSIS
    void
    SIM_break_cycle(conf_object_t *NOTNULL obj, int64 cycles);
    

    DESCRIPTION
    Insert a breakpoint event at cycles clock cycles from now, causing simulation to stop when reached by obj.
    EXECUTION CONTEXT
    Cell Context

    SIM_break_step()

    NAME
    SIM_break_step — set a step breakpoint
    SYNOPSIS
    void
    SIM_break_step(conf_object_t *NOTNULL obj, int64 steps);
    

    DESCRIPTION
    Sets a step breakpoint on a processor. The steps argument is the number of instructions until the break occurs.
    EXCEPTIONS
    SimExc_InterfaceNotFound Thrown if the obj object doesn't implement the step interface.

    EXECUTION CONTEXT
    Cell Context

    SIM_breakpoint()

    NAME
    SIM_breakpoint — set breakpoint
    SYNOPSIS
    breakpoint_id_t
    SIM_breakpoint(conf_object_t *NOTNULL obj,
                   breakpoint_kind_t kind,
                   access_t access,
                   uint64 address,
                   uint64 length,
                   breakpoint_flag_t flags);
    

    DESCRIPTION
    Add breakpoint on an object implementing the breakpoint interface. This is typically a memory space object such as physical memory.

    Please note that breakpoints set by this function may not appear in the output from bp.list. It's recommended to use the bp.memory.break command to set breakpoints.

    The kind argument sets what type of address to break on:

    typedef enum {
            Sim_Break_Physical = 0,
            Sim_Break_Virtual  = 1,
            Sim_Break_Linear   = 2      /* x86 only */
    } breakpoint_kind_t;

    The access argument is a bit-field setting the type of access. Any combination of the three alternatives can be given (added together).

    typedef enum {
            Sim_Access_Read = 1,
            Sim_Access_Write = 2,
            Sim_Access_Execute = 4
    } access_t;

    The address is the start of the breakpoint range and length is its length in bytes. This range will be truncated as necessary to fit in the address space. An access intersecting the given range will trigger the breakpoint. If length is zero, the breakpoint range will be the entire address space.

    The flags argument should be the sum of zero or more enumeration constants from breakpoint_flag_t:

    typedef enum breakpoint_flag {
            Sim_Breakpoint_Temporary = 1,
            Sim_Breakpoint_Simulation = 2,
            Sim_Breakpoint_Private = 4
    } breakpoint_flag_t;

    If the Sim_Breakpoint_Temporary bit is set, the breakpoint is automatically disabled when triggered the first time.

    If the Sim_Breakpoint_Simulation bit is set, the breakpoint will not show up in the bp.list command, nor can it be removed by the bp.delete command. Also, there will be no message printed on the Simics console when this breakpoint is triggered. This bit should be set when using breakpoints to simulate the target system.

    If the Sim_Breakpoint_Private bit is set, the breakpoint will not show up in the bp.list command, nor can it be removed by the bp.delete command.

    The default action for a triggered breakpoint is to return to the frontend (this can be changed by using haps). On execution breakpoints Simics will return to the frontend before the instructions is executed, while instructions triggering read or write breakpoints will complete before control is returned to the frontend.

    Several breakpoints can be set on the same address and Simics will break on them in turn. If hap handlers are connected to the breakpoints they will also be executed in turn. Hap handlers are called before the access is performed, allowing the user to read a memory value that may be overwritten by the access. See the Simics Reference Manual for a description of hap handlers.

    Several attributes can be set for a breakpoint for breaking only when some conditions are true. See the breakpoints attribute in the sim class.

    This function returns the breakpoint id which is used for further reference to the breakpoint:

    typedef int breakpoint_id_t;

    Breakpoints can be removed using SIM_delete_breakpoint.

    EXCEPTIONS
    SimExc_General Thrown if the type or access arguments are illegal. Also thrown if obj cannot handle breakpoints of the given kind.

    RETURN VALUE
    Breakpoint id, -1 on exception.
    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_breakpoint_remove, SIM_delete_breakpoint

    SIM_breakpoint_remove()

    NAME
    SIM_breakpoint_remove — delete breakpoint range
    SYNOPSIS
    void
    SIM_breakpoint_remove(int id,
                          access_t access,
                          generic_address_t address,
                          generic_address_t length);
    

    DESCRIPTION
    Deletes a breakpoint range from an existing breakpoint. Can thus be used to create holes in the breakpoint range. id is the breakpoint to operate on, as returned by SIM_breakpoint. A value of zero will operate on all breakpoints that were not set using the Sim_Breakpoint_Simulation flag.

    access is a bitfield describing the type of breakpoint to remove using the enumeration constants of the access_t enum.

    address is the start address of the range and length is the length of the range in bytes.

    EXCEPTIONS
    SimExc_Index Thrown if illegal breakpoint

    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_breakpoint, SIM_delete_breakpoint

    SIM_delete_breakpoint()

    NAME
    SIM_delete_breakpoint — delete breakpoint
    SYNOPSIS
    void
    SIM_delete_breakpoint(breakpoint_id_t id);
    

    DESCRIPTION
    Deletes breakpoint id as returned by SIM_breakpoint. A value of zero will delete all breakpoints that were set without the Sim_Breakpoint_Simulation flag.
    EXCEPTIONS
    SimExc_Index Thrown if no breakpoint with the id is found.

    EXECUTION CONTEXT
    Cell Context

    SIM_disable_breakpoint()

    NAME
    SIM_disable_breakpoint, SIM_enable_breakpoint — disable breakpoint
    SYNOPSIS
    void
    SIM_disable_breakpoint(breakpoint_id_t id);
    

    void
    SIM_enable_breakpoint(breakpoint_id_t id);
    

    DESCRIPTION
    Enables and disables breakpoint id, as returned by SIM_breakpoint.
    EXCEPTIONS
    SimExc_Index Thrown if no breakpoint with the id is found.
    EXECUTION CONTEXT
    Cell Context

    Configuration

    SIM_add_configuration()

    NAME
    SIM_add_configuration — set configuration from Python
    SYNOPSIS
    void
    SIM_add_configuration(pre_conf_object_set_t *NOTNULL set,
                          const char *file);
    

    DESCRIPTION
    This function creates objects from the parse objects in set and adds the initialized objects to the current configuration (creating one if necessary). When called from Python (which is the intended usage), the configuration set is a sequence (list or tuple) of pre_conf_object Python objects, or a dictionary of the form {name : pre_conf_object}.

    The file argument is the name of the file that a configuration was read from, and should be set to None/NULL if not used.

    The following examples are written in Python. As they do not map any devices in phys_mem, they will not work as stand-alone simulations.

    Example when set is a sequence:

        clock = pre_conf_object('timer', 'clock')
        clock.freq_mhz = 20
        space = pre_conf_object('phys_mem', 'memory-space')
        space.queue = clock
    
        SIM_add_configuration([clock, space], None)
      

    Example when set is a dictionary:

        objects = {}
        objects['clock'] = pre_conf_object('timer', 'clock')
        objects['clock'].freq_mhz = 20
        objects['space'] = pre_conf_object('phys_mem', 'memory-space')
        objects['space'].queue = objects['clock']
    
        SIM_add_configuration(objects, None)
      

    EXCEPTIONS
    SimExc_General Thrown if Simics fails to initialize all objects.

    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_create_object, SIM_set_configuration, SIM_read_configuration

    SIM_class_has_attribute()

    NAME
    SIM_class_has_attribute — check if class implements attribute
    SYNOPSIS
    bool
    SIM_class_has_attribute(conf_class_t *NOTNULL cls, const char *NOTNULL attr);
    

    DESCRIPTION
    Returns true if the class cls implements an attribute with the name attr.
    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_register_attribute, SIM_get_attribute

    SIM_create_object()

    NAME
    SIM_create_object — create and initialize object
    SYNOPSIS
    conf_object_t *
    SIM_create_object(conf_class_t *NOTNULL cls, const char *name,
                      attr_value_t attrs);
    

    DESCRIPTION
    Creates a new instance of the configuration class cls. name must consist of a letter followed by letters, digits or underscores (_). A unique name will be created if name is an empty string or NULL. For backward compatibility, hyphens (-) are allowed instead of underscores but their use is deprecated.

    The new object is initialized with attributes from attrs, which must be a list of (attribute-name, value) pairs, where each pair is a two-element list. All required attributes for the class cls must be present in attrs. In Python, attrs can be omitted (if no attributes are required), it can be normal lists: [['attribute1', value1], ['attribute2', value2]] or keyword arguments: attribute1=value1, attribute2=value2.

    Attributes in ports of the cls class can be initialized by prefixing the attribute name with the port name, e.g. ['p.portname.attr', value].

    The argument value may be modified, but the caller is still responsible for freeing it. Neither point applies when the function is called from Python.

    RETURN VALUE
    The new object, or NULL on error (in which case an exception is raised).
    EXCEPTIONS
    SimExc_General Thrown if the name is not well-formed, if an object named name already exists, or if the initialisation failed.

    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_add_configuration, SIM_set_configuration

    SIM_current_checkpoint_dir()

    NAME
    SIM_current_checkpoint_dir — directory of checkpoint being loaded
    SYNOPSIS
    char *
    SIM_current_checkpoint_dir();
    

    DESCRIPTION
    If called during the loading of a checkpoint, this function returns the checkpoint (bundle) directory. Otherwise, the return value is NULL. The directory can be absolute or relative, and may be the empty string if the checkpoint directory is the current working directory.
    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_read_configuration, SIM_add_configuration

    SIM_delete_objects()

    NAME
    SIM_delete_objects, SIM_delete_object — delete a list of objects
    SYNOPSIS
    int
    SIM_delete_objects(attr_value_t val);
    

    int
    SIM_delete_object(conf_object_t *NOTNULL obj);
    

    DESCRIPTION
    Delete the list of objects val (or the single object obj) passed as argument, provided that no reference to these objects is left in the rest of the configuration. Descendant objects of an object being deleted will also be deleted.

    Some specific objects in Simics, such as sim, are protected against deletion and will be ignored by this function.

    If Simics finds references to the objects in the rest of the configuration, a warning will be printed and the operation will be aborted. Note that in this case, the deletion process has started and the objects may already have began their clean-up routines. The safest action at this point is to fix the dangling references and to try to delete the objects once again.

    Events posted by the objects in cycle queues or step queues will be automatically removed. Hap callbacks and script branches waiting on deleted objects will be interrupted as well.

    RECURSION
    While removing the listed objects, SIM_delete_objects will call various callbacks (Core_Conf_Object_Pre_Delete and Core_Conf_Object_Delete haps, as well as pre_delete_instance and delete_instance for each object). Recursive calls to SIM_delete_objects are allowed during the pre-delete phase (Pre_Delete hap and pre_delete_instance callback), and the new objects will be added to the current list of objects to delete. Recursive calls after this stage will fail.

    This limited recursion is meant to let objects that "own" other objects destroy them automatically if they themselves are to be deleted. This is used for example by the standard Simics components.

    BUGS
    Note that for successful deletion of objects, each class should implement the proper deletion methods called by SIM_delete_objects. If the methods are not present, SIM_delete_objects will simply remove any reference to the object, but this may leave memory and resources unrecoverable.
    RETURN VALUE
    Returns zero if successful. Throws an exception and returns non-zero otherwise.
    EXCEPTIONS
    SimExc_General Thrown if an error occurred or a reference to the objects is left in the rest of the configuration.

    EXECUTION CONTEXT
    Global Context
    EXAMPLE
    The following line at the Simics prompt:
       @SIM_delete_objects(list(SIM_object_iterator(None)))
       

    will delete all unprotected objects in the configuration, leaving the Simics session empty.

    SIM_delete_snapshot()

    NAME
    SIM_delete_snapshot — delete a snapshot
    SYNOPSIS
    snapshot_error_t
    SIM_delete_snapshot(const char *name);
    

    DESCRIPTION
    Deletes an in-memory snapshot.
    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_take_snapshot, SIM_restore_snapshot, SIM_list_snapshots

    SIM_get_all_classes()

    NAME
    SIM_get_all_classes — get list of all loaded classes
    SYNOPSIS
    attr_value_t
    SIM_get_all_classes();
    

    DESCRIPTION
    Return an unordered list of the names of all configuration classes loaded into simulation.

    The Python function cli.global_cmds.list_classes can be used to get class names, by default including not-loaded classes.

    RETURN VALUE
    List of class names.
    EXECUTION CONTEXT
    Cell Context

    SIM_get_all_objects()

    NAME
    SIM_get_all_objects — get list of all objects
    SYNOPSIS
    attr_value_t
    SIM_get_all_objects();
    

    DESCRIPTION
    The function is going to be deprecated. Please use SIM_object_iterator instead.

    Return a list of all configuration objects. The order is unspecified and may vary between calls to this function.

    This function is deprecated and should not be used.

    RETURN VALUE
    List of objects.
    SEE ALSO
    SIM_object_iterator
    EXECUTION CONTEXT
    Cell Context

    SIM_get_attribute()

    NAME
    SIM_get_attribute, SIM_get_attribute_idx — get attribute
    SYNOPSIS
    attr_value_t
    SIM_get_attribute(conf_object_t *NOTNULL obj, const char *NOTNULL name);
    

    attr_value_t
    SIM_get_attribute_idx(conf_object_t *NOTNULL obj, const char *NOTNULL name,
                          attr_value_t *NOTNULL index);
    

    DESCRIPTION
    Extracts the attribute specified by name parameter from obj. If an error occurs, an invalid value is returned. The _idx version of the function can be used to get a single entry in a list or data attribute. The attribute must support indexing for this to work.

    The caller is as usual responsible for freeing the returned value by calling SIM_attr_free.

    RETURN VALUE
    Attribute value. An attribute of Invalid type is returned if the attribute could not be read.
    EXCEPTIONS
    • SimExc_AttrNotFound If the object did not have the specified attribute.
    • SimExc_AttrNotReadable If the attribute cannot be read.
    • SimExc_Type If the index has the wrong type.
    • SimExc_General If SIM_attribute_error or SIM_c_attribute_error was called inside the getter function.
    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_attr_free, SIM_set_attribute, SIM_attribute_error

    SIM_get_attribute_attributes()

    NAME
    SIM_get_attribute_attributes — get attribute flags
    SYNOPSIS
    attr_attr_t
    SIM_get_attribute_attributes(conf_class_t *NOTNULL cls,
                                 const char *NOTNULL attr);
    

    DESCRIPTION
    Returns the attribute flags of the attr attribute of the class cls.
    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_register_attribute

    SIM_get_class_attribute()

    NAME
    SIM_get_class_attribute, SIM_get_class_attribute_idx — get class attribute
    SYNOPSIS
    attr_value_t
    SIM_get_class_attribute(conf_class_t *NOTNULL cls, const char *NOTNULL name);
    

    attr_value_t
    SIM_get_class_attribute_idx(conf_class_t *NOTNULL cls,
                                const char *NOTNULL name,
                                attr_value_t *NOTNULL index);
    

    DESCRIPTION
    Extracts the class attribute specified by name from the class cls. If an error occurs, an invalid value is returned. The _idx version of the function can be used to get a single entry in a list or data attribute. The attribute must support indexing for this to work.

    The caller is as usual responsible for freeing the returned value by calling SIM_attr_free.

    RETURN VALUE
    Attribute value. A value of Invalid type is returned if the attribute could not be read.
    EXCEPTIONS
    • SimExc_AttrNotFound If the class did not have the specified attribute.
    • SimExc_AttrNotReadable If the attribute cannot not be read.
    • SimExc_Type If the index has the wrong type.
    • SimExc_General Other errors.
    EXECUTION CONTEXT
    Global Context, unless the attribute documentation says otherwise.
    SEE ALSO
    SIM_attr_free, SIM_set_class_attribute

    SIM_get_object()

    NAME
    SIM_get_object — get object
    SYNOPSIS
    conf_object_t *
    SIM_get_object(const char *NOTNULL name);
    

    DESCRIPTION
    Returns the object with name name.

    The function does an object look-up in the order; object ID, object name, and hierarchical location for all objects in the simulation. The function returns the first match from the look-up or NULL if there was no object match.

    The object ID is a unique name that never changes and is returned by the SIM_object_id function. The object name is the name of the object, used for instance when printing log messages and is returned by the SIM_object_name function. The hierarchical location is the absolute location of the object in the component hierarchy. The object name and the hierarchical location is the same.

    Please note that in Python Simics objects are available directly as attributes of the conf module. For example, one can access the sim object like this:

    conf.sim

    .

    RETURN VALUE
    Object, or NULL if not found.
    EXCEPTIONS
    SimExc_General Thrown if the object can not be found.

    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_object_name, SIM_object_id, SIM_object_parent, SIM_object_descendant

    SIM_get_python_interface_type()

    NAME
    SIM_get_python_interface_type — get Python interface type
    SYNOPSIS
    PyObject *
    SIM_get_python_interface_type(const char *NOTNULL name);
    

    DESCRIPTION
    Returns the Python data type for the name interface, or NULL if not available from Python.

    If necessary, will try to load modules registering the Python translation for this interface.

    SIM_get_snapshot_info()

    NAME
    SIM_get_snapshot_info — get information about a snapshot
    SYNOPSIS
    attr_value_t
    SIM_get_snapshot_info(const char *NOTNULL name);
    

    DESCRIPTION
    Returns a dictionary of information about a snapshot. The currently defined keys in the dictionary are:
    name
    The name of the snapshot
    pages
    The number of non-zero image pages in the snapshot
    previous
    The name of the latest snapshot taken or restored before this snapshot was taken. nil if there was no such snapshot, or if that snapshot has been deleted.

    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_list_snapshots, SIM_take_snapshot, SIM_restore_snapshot, SIM_delete_snapshot

    SIM_is_restoring_snapshot()

    NAME
    SIM_is_restoring_snapshot — check if a snapshot is currently being restored
    SYNOPSIS
    bool
    SIM_is_restoring_snapshot();
    

    DESCRIPTION
    Returns true if an in-memory snapshot is currently being restored.
    EXECUTION CONTEXT
    Cell Context

    SIM_list_snapshots()

    NAME
    SIM_list_snapshots — list snapshots
    SYNOPSIS
    attr_value_t
    SIM_list_snapshots();
    

    DESCRIPTION
    Returns a list of the names of the currently taken snapshots.
    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_take_snapshot, SIM_restore_snapshot, SIM_delete_snapshot, SIM_get_snapshot_info

    SIM_object_class()

    NAME
    SIM_object_class — get object class
    SYNOPSIS
    FORCE_INLINE conf_class_t *
    SIM_object_class(const conf_object_t *NOTNULL obj);
    

    DESCRIPTION
    Returns the class of an object.
    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_get_class

    SIM_object_descendant()

    NAME
    SIM_object_descendant — return a descendant of the specified object
    SYNOPSIS
    conf_object_t *
    SIM_object_descendant(conf_object_t *obj, const char *NOTNULL relname);
    

    DESCRIPTION
    This function returns the descendant object of obj which has the relative name relname, or NULL if no such object exists.

    It is legal for the relative name to contain multiple components, like "device.p.RESET".

    If obj is NULL, then the object lookup is performed relative the object hierarchy root.

    If obj is instantiated at the same time as the descendant, then the function is guaranteed to succeed if called after the alloc_object phase of object initialization; i.e., it is safe for obj to invoke the function from its init_object method.

    RETURN VALUE
    Object, or NULL if the object has no hierarchical descendant with the specified relative name.
    SEE ALSO
    SIM_object_parent SIM_register_port
    EXECUTION CONTEXT
    Cell Context

    SIM_object_is_processor()

    NAME
    SIM_object_is_processor — test if object is a processor
    SYNOPSIS
    bool
    SIM_object_is_processor(conf_object_t *NOTNULL obj);
    

    DESCRIPTION
    Returns non-zero if obj is a processor.
    EXECUTION CONTEXT
    All contexts (including Threaded Context)

    SIM_object_iterator()

    NAME
    SIM_object_iterator — start object iteration
    SYNOPSIS
    object_iter_t
    SIM_object_iterator(conf_object_t *obj);
    

    DESCRIPTION
    The SIM_object_iterator function returns an iterator for the descendants of the object obj. If obj is NULL, then the returned iterator will iterate over all objects in the configuration.

    The iterator returns objects sorted by name, with parents before children.

    RETURN VALUE
    Object iterator
    EXAMPLE
    Sample C code to find all objects implementing signal interface:
        #include <simics/util/vect.h>
        #include <simics/devs/signal.h>
    
        ...
    
        VECT(conf_object_t *) v = VNULL;
        object_iter_t it = SIM_object_iterator(NULL);
        conf_object_t *obj;
        while ((obj = SIM_object_iterator_next(&it)) != NULL) {
            if (SIM_C_GET_INTERFACE(obj, signal) != NULL)
                VADD(v, obj);
        }
        ...  // any code using 'v' vector here
        VFREE(v);
       

    Sample Python code to find all objects implementing signal interface:

        v = []
        for obj in SIM_object_iterator(None):
            if hasattr(obj.iface, simics.SIGNAL_INTERFACE):
                v.append(obj)

    The simics.SIGNAL_INTERFACE constant from the above example holds

    "signal"

    string. Such constants are available for some interfaces. One can safely use string literals instead.

    SEE ALSO
    SIM_object_iterator_next, SIM_shallow_object_iterator, SIM_object_iterator_for_class, SIM_object_iterator_for_interface
    EXECUTION CONTEXT
    Cell Context

    SIM_object_iterator_for_class()

    NAME
    SIM_object_iterator_for_class — start class instance iteration
    SYNOPSIS
    object_iter_t
    SIM_object_iterator_for_class(conf_class_t *cls);
    

    DESCRIPTION
    The SIM_object_iterator_for_class function returns an iterator for the instances of the class cls. See SIM_object_iterator for examples on how to use the iterator.
    RETURN VALUE
    Object iterator
    SEE ALSO
    SIM_object_iterator_next, SIM_object_iterator, SIM_object_iterator_for_interface
    EXECUTION CONTEXT
    Cell Context

    SIM_object_iterator_for_interface()

    NAME
    SIM_object_iterator_for_interface — start class instance iteration
    SYNOPSIS
    object_iter_t
    SIM_object_iterator_for_interface(attr_value_t ifaces);
    

    DESCRIPTION
    The SIM_object_iterator_for_interface function returns an iterator for the objects that implement all interfaces in ifaces (i.e. all objects if ifaces is empty), which must be a list of strings of length at most 16. See SIM_object_iterator for examples on how to use the iterator.
    RETURN VALUE
    Object iterator
    SEE ALSO
    SIM_object_iterator_next, SIM_object_iterator, SIM_object_iterator_for_class
    EXCEPTIONS
    SimExc_General Thrown if the ifaces argument does not conform to the above requirements.

    EXECUTION CONTEXT
    Cell Context

    SIM_object_iterator_next()

    NAME
    SIM_object_iterator_next — get next object
    SYNOPSIS
    conf_object_t *
    SIM_object_iterator_next(object_iter_t *iter);
    

    DESCRIPTION
    The SIM_object_iterator_next function returns the next object from an iterator obtained from SIM_object_iterator or SIM_shallow_object_iterator. If there are no more objects in the sequence, then NULL is returned.

    It is illegal to call SIM_object_iterator_next using an iterator which has reached the end of its sequence.

    RETURN VALUE
    Next object or NULL
    SEE ALSO
    SIM_object_iterator_next, SIM_object_iterator
    EXECUTION CONTEXT
    Cell Context

    SIM_object_parent()

    NAME
    SIM_object_parent — get object parent
    SYNOPSIS
    conf_object_t *
    SIM_object_parent(conf_object_t *NOTNULL obj);
    

    DESCRIPTION
    Returns the hierarchical parent of the specified object.
    RETURN VALUE
    Object, or NULL if the object has no hierarchical parent.
    SEE ALSO
    SIM_object_descendant, SIM_port_object_parent
    EXECUTION CONTEXT
    Cell Context

    SIM_port_object_parent()

    NAME
    SIM_port_object_parent — get object parent
    SYNOPSIS
    conf_object_t *
    SIM_port_object_parent(conf_object_t *NOTNULL obj);
    

    DESCRIPTION
    Returns the parent of the specified port object.
    RETURN VALUE
    Object, or NULL if the object is not a port object.
    SEE ALSO
    SIM_object_parent, SIM_object_descendant
    EXECUTION CONTEXT
    Cell Context

    SIM_printf_error()

    NAME
    SIM_printf_error, SIM_printf_error_vararg — print error message
    SYNOPSIS
    void
    SIM_printf_error(const char *format, ...);
    

    void
    SIM_printf_error_vararg(const char *format, va_list ap);
    

    DESCRIPTION
    This can be used to print an error message during the simulation. It is analogous to log error messages, but for non-device code. I.e. it should be used for errors that prevents the simulation from continuing.
    SEE ALSO
    SIM_printf_warning

    SIM_printf_warning()

    NAME
    SIM_printf_warning, SIM_printf_warning_vararg — print warning message
    SYNOPSIS
    void
    SIM_printf_warning(const char *format, ...);
    

    void
    SIM_printf_warning_vararg(const char *format, va_list ap);
    

    DESCRIPTION
    This can be used to print a warning message during the simulation. It is analogous to log warning messages, but for non-device code. I.e. it should be used for problems that do not prevent the simulation from continuing.
    SEE ALSO
    SIM_printf_error

    SIM_read_configuration()

    NAME
    SIM_read_configuration — read configuration
    SYNOPSIS
    void
    SIM_read_configuration(const char *NOTNULL file);
    

    DESCRIPTION
    Read configuration from filename and create a machine accordingly.
    EXCEPTIONS
    SimExc_General Thrown if the file could not be opened, the machine was already initialized, or if an error in the configuration file was detected.

    EXECUTION CONTEXT
    Global Context

    SIM_register_context_handler()

    NAME
    SIM_register_context_handler — register mandatory interface and attribute for context handler objects
    SYNOPSIS
    int
    SIM_register_context_handler(conf_class_t *NOTNULL cls,
                                 const context_handler_interface_t *NOTNULL iface);
    

    DESCRIPTION
    Register the cls class as a class for context handler objects. This includes registering the context_handler interface (iface), in addition to which SIM_register_context_handler registers a current_context attribute which will hold the current context.

    The context_handler interface will be wrapped by standard functions so that standard context change behavior is taken care off automatically. This includes, among other things, making sure that the context is valid, and triggering the correct haps on context changes. Thus the context_handler implementation need only care about the effect of the change on the context_handler object itself (virtual breakpoints present in the context, cache flushing, etc.).

    The return value is 0 if everything works, and non-zero if something fails. SIM_register_context_handler will return the error value provided by SIM_register_interface.

    RETURN VALUE
    Returns non-zero on failure, 0 otherwise.
    EXCEPTIONS
    SimExc_General Thrown if the context_handler interface has already been registered for this class.

    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_register_interface

    SIM_restore_snapshot()

    NAME
    SIM_restore_snapshot — restore a snapshot of the configuration state
    SYNOPSIS
    snapshot_error_t
    SIM_restore_snapshot(const char *name);
    

    DESCRIPTION
    Restores the state of the configuration to a previously taken snapshot.
    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_take_snapshot, SIM_delete_snapshot, SIM_list_snapshots

    SIM_set_attribute()

    NAME
    SIM_set_attribute, SIM_set_attribute_idx — set attribute
    SYNOPSIS
    set_error_t
    SIM_set_attribute(conf_object_t *NOTNULL obj,
                      const char *NOTNULL name,
                      attr_value_t *NOTNULL value);
    

    set_error_t
    SIM_set_attribute_idx(conf_object_t *NOTNULL obj,
                          const char *NOTNULL name,
                          attr_value_t *NOTNULL index,
                          attr_value_t *NOTNULL value);
    

    DESCRIPTION
    Set the name attribute in obj to value.

    The _idx version of the function can be used to get a single entry in a list or data attribute. For this to work, the attribute must support indexing.

    After the call the value is still owned by the caller.

    If the attribute setter function calls SIM_attribute_error or SIM_c_attribute_error and returns Sim_Set_Ok, it is treated like Sim_Set_IllegalValue.

    RETURN VALUE
    The return value is from the set_error_t enum, with Sim_Set_Ok indicating success.
    EXCEPTIONS
    • SimExc_AttrNotFound If the object did not have the specified attribute
    • SimExc_AttrNotWritable if the attribute cannot not be written
    • SimExc_Type if the index has the wrong type, the value to be set does not match the type specified by the attribute or the setter function returned Sim_Set_Illegal_Type
    • SimExc_IllegalValue if the setter function returned Sim_Set_Illegal_Value
    • SimExc_Index if the setter function returned Sim_Set_Illegal_Index
    • SimExc_InterfaceNotFound if the setter function returned Sim_Set_Interface_Not_Found
    • SimExc_General if the setter function returned something else than Sim_Set_Ok, Sim_Set_Illegal_Type, Sim_Set_Illegal_Value, Sim_Set_Illegal_Index or Sim_Set_Interface_Not_Found.
    EXECUTION CONTEXT
    Global Context in general; individual attributes may be less constrained.
    SEE ALSO
    SIM_get_attribute, SIM_attribute_error, set_error_t

    SIM_set_class_attribute()

    NAME
    SIM_set_class_attribute, SIM_set_class_attribute_idx — set class attribute
    SYNOPSIS
    set_error_t
    SIM_set_class_attribute(conf_class_t *NOTNULL cls,
                            const char *NOTNULL name,
                            attr_value_t *NOTNULL value);
    

    set_error_t
    SIM_set_class_attribute_idx(conf_class_t *NOTNULL cls,
                                const char *NOTNULL name,
                                attr_value_t *NOTNULL index,
                                attr_value_t *NOTNULL value);
    

    DESCRIPTION
    Set the name attribute in cls to value.

    The _idx version of the function can be used to set a single entry in a list or data attribute. For this to work, the attribute must support indexing.

    After the call the value is still owned by the caller.

    RETURN VALUE
    The return value is from the set_error_t enum, with Sim_Set_Ok indicating success.
    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_get_attribute, set_error_t

    SIM_set_configuration()

    NAME
    SIM_set_configuration — set configuration from data
    SYNOPSIS
    void
    SIM_set_configuration(attr_value_t conf);
    

    DESCRIPTION
    Note: It is recommended that the SIM_add_configuration function is used instead of SIM_set_configuration.
    This function is an alternative to reading the configuration from a file. A configuration is an attr_value_t which should have the following structure.

      (("name", "class",  ("attr_name", attr_val) ... ), ... )
      

    That is a list of object specifiers containing name, class, and a list of attribute specifiers. An attribute specifier is a list of length 2 containing the attribute name and its value. SIM_set_configuration allows an easy way of parameterizing the configuration, especially if called from Python.

    The argument value may be modified, but the caller is still responsible for freeing it. Neither point applies when the function is called from Python.

    EXAMPLE
    The following is a Python example:

      from configuration import OBJ
      from simics import SIM_set_configuration
    
      SIM_set_configuration([
       ["cpu0", "x86",
        ["queue", OBJ("cpu0")],
        ["freq_mhz", 20],
        ["physical_memory", OBJ("phys_mem0")]],
    
       ["phys_mem0", "memory-space",
        ["map",  [[0xa0000,    OBJ("vga0"),    1, 0, 0x20000],
                  [0x00000,    OBJ("mem0"),    0, 0x00000, 0xA0000],
                  [0xc0000,    OBJ("mem0"),    0, 0xc0000, 0x8000],
                  [0xc8000,    OBJ("setmem0"), 0, 0, 0x28000],
                  [0xf0000,    OBJ("mem0"),    0, 0xf0000, 0x10000],
                  [0x100000,   OBJ("mem0"),    0, 0x100000, 0x3ff00000],
                  [0xfee00000, OBJ("apic0"),   0, 0, 0x4000]]]],
          ... ])
      

    EXCEPTIONS
    SimExc_Attribute Thrown if malformed configuration list.

    SimExc_General Thrown if Simics fails to initialize all objects.

    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_add_configuration, SIM_create_object

    SIM_shallow_object_iterator()

    NAME
    SIM_shallow_object_iterator — start object iteration
    SYNOPSIS
    object_iter_t
    SIM_shallow_object_iterator(conf_object_t *obj);
    

    DESCRIPTION
    The SIM_shallow_object_iterator function returns an iterator for the direct children of the object obj. If obj is NULL, then the returned iterator will iterate over objects on the root level.

    The iterator returns objects sorted by name.

    RETURN VALUE
    Object iterator
    SEE ALSO
    SIM_object_iterator_next, SIM_object_iterator
    EXECUTION CONTEXT
    Cell Context

    SIM_take_snapshot()

    NAME
    SIM_take_snapshot — take snapshot of the current configuration
    SYNOPSIS
    snapshot_error_t
    SIM_take_snapshot(const char *name);
    

    DESCRIPTION
    Takes an in-memory snapshot of the state of all objects. Objects whose class_kind_t is equal to Sim_Class_Kind_Pseudo are not saved. This also holds for attributes (in all objects) of type Sim_Attr_Pseudo.
    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_restore_snapshot, SIM_delete_snapshot, SIM_list_snapshots

    SIM_write_configuration_to_file()

    NAME
    SIM_write_configuration_to_file — write configuration
    SYNOPSIS
    void
    SIM_write_configuration_to_file(const char *NOTNULL file, save_flags_t flags);
    

    DESCRIPTION
    Saves all objects to filename. Objects whose class_kind_t is equal to Sim_Class_Kind_Session or Sim_Class_Kind_Pseudo are not saved. This also holds for attributes (in all objects) of type Sim_Attr_Pseudo.

    The flags argument should be 0.

    EXECUTION CONTEXT
    Global Context

    SIM_write_persistent_state()

    NAME
    SIM_write_persistent_state — save persistent state
    SYNOPSIS
    void
    SIM_write_persistent_state(const char *file, conf_object_t *root,
                                        save_flags_t flags);
    

    DESCRIPTION
    Saves the persistent state to a file. Persistent data typically includes disk images, NVRAM and flash memory contents and clock settings, i.e data that survives reboots. The Persistent state is saved as a standard simics configuration.
    EXECUTION CONTEXT
    Global Context

    Embedding Simics

    SIM_get_init_arg_string()

    NAME
    SIM_get_init_arg_string, SIM_get_init_arg_boolean — get an argument that the Simics core was initialized with
    SYNOPSIS
    const char *
    SIM_get_init_arg_string(const char *name, const char *default_value);
    

    bool
    SIM_get_init_arg_boolean(const char *name, bool default_value);
    

    DESCRIPTION
    Returns the value of init argument name previously supplied to Simics using SIM_init_simulator2. Arguments are either strings (char *) or booleans (bool).

    This function is only needed when directly embedding libsimics-common in another application, which is deprecated.

    RETURN VALUE
    The argument value or default_value if the argument was not supplied to SIM_init_simulator2 or if the argument value was NULL.
    EXCEPTIONS
    SimExc_General Thrown if the argument is of the wrong type.
    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_init_simulator2

    SIM_init_command_line()

    NAME
    SIM_init_command_line — initialize the Simics command line
    SYNOPSIS
    void
    SIM_init_command_line();
    

    DESCRIPTION
    SIM_init_command_line initializes the Simics command line used when running from a Linux shell or the Windows Command Prompt.

    This function must be called after the Simics Python module has been loaded and should only be called when embedding Simics in another application.

    EXCEPTIONS
    SimExc_General Thrown if the function already has been called once.

    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_main_loop

    SIM_init_environment()

    NAME
    SIM_init_environment — perform early initialization of the simulator
    SYNOPSIS
    void
    SIM_init_environment(char **NOTNULL argv,
                         bool handle_signals, bool allow_core_dumps);
    

    DESCRIPTION
    The SIM_init_environment function should be called as early as possible when Simics is embedded in another application, before any other Simics API function. It will initialize Simics dynamic memory handling VTMEM, set up signal handling and perform some other early initialization.

    The argv argument is a NULL terminated list of strings. It must not be NULL. It must contain at least one element, which will be used as the program name. Often you can use the argv that main receives as the value of this argument.

    If handle_signals is true, Simics will install its handler for Control-C, e.g. the SIGINT signal on Linux and ConsoleCtrlHandler on Windows. Set this value to false if the embedding application handles signals itself.

    If allow_core_dumps is true, Simics will not install handlers for fatal signals but instead let the application crash possibly generating a core dump on Linux systems. If the argument is false, no core dump is generated and Simics will try to catch fatal signals and return control to the command line again.

    This function is only needed when directly embedding libsimics-common in another application, which is deprecated.

    EXECUTION CONTEXT
    Global Context

    SIM_init_simulator2()

    NAME
    SIM_init_simulator2 — perform initialization of the simulator
    SYNOPSIS
    void
    SIM_init_simulator2(init_arg_t *NOTNULL init_args);
    

    DESCRIPTION
    SIM_init_simulator2 initializes the simulator core and should only be called when embedding Simics in another application. It has to be called after SIM_init_environment but before using most other parts of the Simics API. The init_args argument is an array with init_arg_t structs, where the last entry has NULL in the name field.

    Each entry in the init_args array contains an argument name and an associated value that is either a string or a boolean. Simics has a number of pre-defined arguments that are used to configure the simulator.

    It is possible to provide additional arguments in the call to SIM_init_simulator2. Such arguments are ignored by Simics and assumed to be used-defined. Their values can be obtained using the SIM_get_init_arg_string and SIM_get_init_arg_boolean functions in the Simics API.

    List of pre-defined parameters and their types:

    batch-mode bool See -batch-mode command line flag.
    deprecation-level char * One of 0, 1 and 2. See the sim.deprecation_level attribute.
    gui-mode char * One of gui, mixed and no-gui
    fail-on-warnings bool See -werror command line flag.
    log-enable bool Deprecated.
    log-file char * See -log-file command line flag.
    no-settings bool See -no-settings command line flag.
    no-windows bool See -no-win command line flag.
    python-verbose bool Legacy flag; does nothing.
    project char * See -project command line flag.
    quiet bool See -quiet command line flag.
    script-trace bool Show when a Simics script is entered/exited, along with any parameters passed to it and result variables returned from it.
    verbose bool See --verbose command line flag.
    Internal or deprecated:
    alt-settings-dir char *
    application-mode char *
    check-ifaces bool
    disable-dstc bool
    disable-istc bool
    package-list char *
    py-import-all bool
    use-module-cache bool

    This function is only needed when directly embedding libsimics-common in another application, which is deprecated.

    EXCEPTIONS
    None
    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_init_environment, SIM_get_init_arg_string, SIM_get_init_arg_boolean.

    SIM_main_loop()

    NAME
    SIM_main_loop — run the Simics main loop
    SYNOPSIS
    void
    SIM_main_loop();
    

    DESCRIPTION
    SIM_main_loop enters the main loop of Simics and never returns. It should only be called when embedding Simics in another application that wishes to transfer full control of the simulation to Simics.

    The main loop waits for work requests to be posted by notifiers, SIM_thread_safe_callback and SIM_realtime_event. If the command line has been initialized it will be active as well.

    If the embedding application do not wish to transfer the control to Simics while the simulation is not advancing should use the SIM_process_work or SIM_process_pending_work to make sure that Simics can process any pending idle work.

    EXCEPTIONS
    SimExc_General Thrown if the function is called recursively.

    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_init_command_line, SIM_realtime_event, SIM_thread_safe_callback, SIM_process_work

    SIM_process_work()

    NAME
    SIM_process_work, SIM_process_pending_work — run the Simics main loop
    SYNOPSIS
    int
    SIM_process_work(int (*done)(lang_void *done_data), lang_void *done_data);
    

    int
    SIM_process_pending_work();
    

    DESCRIPTION
    SIM_process_work and SIM_process_pending_work processes work posted by SIM_register_work, SIM_thread_safe_callback and SIM_realtime_event and related functions to be run in Global Context. They do not process work posted with run_in_thread set. Such work is processed in worker threads.

    These process work functions are typically called when embedding Simics in another application to allow periodic and asynchronous Simics work to run while the simulation is not advancing. They can also be used as part of running the simulation to wait for events coming from external sources.

    SIM_process_pending_work runs all work that has been queued up since the last call and returns immediately after.

    SIM_process_work is similar but waits for new work to arrive. Each time all work that has been queued up has been processed the supplied done callback, which must be non-NULL, is called with done_data as its only argument. A return value of 1 tells SIM_process_work to stop processing work and return control to the caller again while 0 tells it to continue.

    The SIM_process_work functions return -1 if the user has pressed the interrupt key before or while they were running, provided that the simulator core was initialized to catch signals. Otherwise the return value is 0. The function checks for user interrupt at the same time as it checks the done predicate and only if such a predicate is provided.

    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_main_loop, SIM_realtime_event, SIM_thread_safe_callback

    SIM_set_frontend_context()

    NAME
    SIM_set_frontend_context — register a stack context buffer for Simics to longjmp back to
    SYNOPSIS
    void
    SIM_set_frontend_context(void *context);
    

    DESCRIPTION
    When Simics encounters a fatal error that it cannot handle, it uses longjmp() to give control back to the main loop. The longjmp destination depends on the stack context buffer registered by the embedding application using SIM_set_frontend_context. The main loop run by SIM_main_loop already sets up the stack context. You only need to set up the stack context manually if you write your own main loop.

    A stack context buffer is created by calling sigsetjmp() on Linux and setjmp() on Windows.

    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_main_loop, SIM_process_work

    Haps

    SIM_get_all_hap_types()

    NAME
    SIM_get_all_hap_types — get list of all hap types
    SYNOPSIS
    attr_value_t
    SIM_get_all_hap_types();
    

    DESCRIPTION
    Get a list of the names of all registered hap types.
    RETURN VALUE
    Attribute list of strings.
    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_hap_get_number, SIM_hap_add_type

    SIM_hap_add_callback()

    NAME
    SIM_hap_add_callback, SIM_hap_add_callback_index, SIM_hap_add_callback_range, SIM_hap_add_callback_obj, SIM_hap_add_callback_obj_index, SIM_hap_add_callback_obj_range — install callback on a hap
    SYNOPSIS
    hap_handle_t
    SIM_hap_add_callback(const char *NOTNULL hap,
                         NOTNULL obj_hap_func_t func,
                         lang_void *user_data);
    

    hap_handle_t
    SIM_hap_add_callback_index(const char *NOTNULL hap,
                               NOTNULL obj_hap_func_t func,
                               lang_void *user_data,
                               int64 index);
    

    hap_handle_t
    SIM_hap_add_callback_range(const char *NOTNULL hap,
                               NOTNULL obj_hap_func_t func,
                               lang_void *user_data,
                               int64 start,
                               int64 end);
    

    hap_handle_t
    SIM_hap_add_callback_obj(const char *NOTNULL hap,
                             conf_object_t *NOTNULL obj,
                             int flags,
                             NOTNULL obj_hap_func_t func,
                             lang_void *user_data);
    

    hap_handle_t
    SIM_hap_add_callback_obj_index(const char *NOTNULL hap,
                                   conf_object_t *NOTNULL obj,
                                   int flags,
                                   NOTNULL obj_hap_func_t func,
                                   lang_void *user_data,
                                   int64 index);
    

    hap_handle_t
    SIM_hap_add_callback_obj_range(const char *NOTNULL hap,
                                   conf_object_t *NOTNULL obj,
                                   int flags,
                                   NOTNULL obj_hap_func_t func,
                                   lang_void *user_data,
                                   int64 start,
                                   int64 end);
    

    DESCRIPTION
    Registers a function, pointed to by func, to be called when hap occurs for object obj. If a hap add function that does not have the obj argument is used, then the callback function will be called regardless of what object that triggers the hap. The user_data argument is the callback-specific data, and it will be passed as first argument to the installed callback function.

    Some hap add functions also take a flags argument. This flag is currently Simics internal and should be set to 0.

    The hap callback functions should not return any data. In C, the functions are declared to have a void return type and in Python, any return value is ignored. Since callback functions with different arguments may be installed using the same API function, the compiler may warn about a type mismatch. The solution is to cast the callback function pointer to the obj_hap_func_t type.

    The callback will be called in Cell Context, unless the documentation for the hap states otherwise.

    In hap functions, the execution can be interrupted by calling SIM_break_simulation. If a frontend or Python exception is raised, an error message will be printed including a stack trace if the callback is written in Python.

    The _index_ and _range_ versions will install callbacks that only trigger for a specified index, or range of indices. The index is specific for each hap type, see the hap documentation. The index and range must be non-negative and the end of the range must not be lower than the start.

    typedef int hap_handle_t;

    RETURN VALUE
    The return value is a hap callback handle (identifier) of the type hap_handle_t, or -1 on error. This handle can be used to remove the installed callback with SIM_hap_delete_callback_id.
    EXCEPTIONS
    SimExc_Lookup Thrown if the hap does not exist.

    SimExc_Attribute Thrown if the index is negative or if the range is negative in value or size.

    EXECUTION CONTEXT
    Cell Context for hap callbacks tied to an object, and Global Context for hap callbacks not tied to an object. An exception is made for callbacks on Core_Breakpoint_Memop, which can be installed with SIM_hap_add_callback_index even in Cell Context.

    SIM_hap_delete_callback()

    NAME
    SIM_hap_delete_callback, SIM_hap_delete_callback_obj, SIM_hap_delete_callback_id, SIM_hap_delete_callback_obj_id — delete installed hap callback
    SYNOPSIS
    void
    SIM_hap_delete_callback(const char *NOTNULL hap,
                            NOTNULL obj_hap_func_t func, lang_void *user_data);
    

    void
    SIM_hap_delete_callback_obj(const char *NOTNULL hap,
                                conf_object_t *NOTNULL obj,
                                NOTNULL obj_hap_func_t func, lang_void *user_data);
    

    void
    SIM_hap_delete_callback_id(const char *NOTNULL hap, hap_handle_t handle);
    

    void
    SIM_hap_delete_callback_obj_id(const char *NOTNULL hap,
                                   conf_object_t *NOTNULL obj, hap_handle_t handle);
    

    DESCRIPTION
    Removes a callback for a hap type specified by the hap argument.

    The SIM_hap_delete_callback_obj... functions will remove a callback that is installed on the specified object obj.

    SIM_hap_delete_callback removes a callback not associated with any object, with the callback function func and the same user_data. The SIM_hap_delete_callback_..._id functions take a hap handle argument instead, as returned by the SIM_hap_add_callback... functions.

    These functions will trigger the Core_Hap_Callback_Removed hap for each removed callback.

    EXCEPTIONS
    SimExc_Lookup Thrown if the specified hap does not exist.
    EXECUTION CONTEXT
    Cell Context for callbacks tied to an object. Global Context for callbacks not tied to an object.

    Logging

    SIM_get_quiet()

    NAME
    SIM_get_quiet — return setting of the quiet flag
    SYNOPSIS
    bool
    SIM_get_quiet();
    

    DESCRIPTION
    This function returns the current value of Simics's quiet flag.
    EXECUTION CONTEXT
    Cell Context

    SIM_get_verbose()

    NAME
    SIM_get_verbose — get the verbose flag
    SYNOPSIS
    bool
    SIM_get_verbose();
    

    DESCRIPTION
    This function returns the value of Simics's verbosity flag (corresponding to the --verbose command line argument).
    EXECUTION CONTEXT
    Cell Context

    SIM_set_quiet()

    NAME
    SIM_set_quiet — enable/disable quiet mode
    SYNOPSIS
    void
    SIM_set_quiet(bool quiet);
    

    DESCRIPTION
    Calling this function with an argument of true will enable the quiet mode, whereas an argument of false will disable it. Any other arguments will cause a frontend exception. Please note that enabling the quiet mode will disable verbose mode.
    EXECUTION CONTEXT
    Cell Context

    SIM_set_verbose()

    NAME
    SIM_set_verbose — enable/disable verbose mode
    SYNOPSIS
    void
    SIM_set_verbose(bool verbose);
    

    DESCRIPTION
    This function sets Simics's internal verbosity flag (corresponding to the --verbose command line argument). The verbose argument can be either true or false. Note that setting this flag will disable quiet mode.
    EXECUTION CONTEXT
    Cell Context

    Memory

    SIM_load_binary()

    NAME
    SIM_load_binary — read an executable file into memory
    SYNOPSIS
    physical_address_t
    SIM_load_binary(conf_object_t *NOTNULL obj, const char *NOTNULL file,
                    physical_address_t offset, bool use_pa, bool verbose);
    

    DESCRIPTION
    Read a binary file (ELF, Motorola S-Record, PE32, PE32+, or TI COFF format) into memory and return the code entry point.

    The file will be loaded at the address formed by adding the virtual load address from the file, with the offset offset. If the flag use_pa is set, the ELF physical load address is used instead. The verbose flag will cause Simics to print info about the binary to the console.

    The memory space to load into is given in the obj parameter. If the given space is a CPU object, its current virtual address space will be used, and addresses will be translated before writing to the physical memory space attached to the CPU.

    If the file is not found in the current directory, the search path (see add-directory) is used to find the file.

    EXCEPTIONS
    SimExc_IOError Thrown if there was a problem reading the file.
    SimExc_General Thrown if binary cannot be read into memory.
    RETURN VALUE
    The code entry address.
    EXECUTION CONTEXT
    Global Context

    SIM_load_file()

    NAME
    SIM_load_file — read a file into memory
    SYNOPSIS
    void
    SIM_load_file(conf_object_t *NOTNULL obj, const char *NOTNULL file,
                  physical_address_t base_address, bool verbose);
    

    DESCRIPTION
    Loads the contents of file into memory starting at address base_address. The obj argument can either be a processor, a memory-space, or an image object. In case of a processor, the address is interpreted as a virtual address.

    The file can be either a raw binary file or a file in the craff format.

    The verbose flag will cause Simics to print some information about the load.

    EXCEPTIONS
    SimExc_IOError Thrown if there was a problem reading the file.
    SimExc_General Thrown if file cannot be read into memory.
    EXECUTION CONTEXT
    Cell Context

    SIM_read_byte()

    NAME
    SIM_read_byte, SIM_write_byte — read/write byte from a memory space
    SYNOPSIS
    uint8
    SIM_read_byte(conf_object_t *NOTNULL obj, generic_address_t paddr);
    

    void
    SIM_write_byte(conf_object_t *NOTNULL obj,
                   generic_address_t paddr, uint8 value);
    

    DESCRIPTION
    Read or write a byte from a given address in the memory space obj.
    EXCEPTIONS
    SimExc_Memory Thrown if the memory space threw an exception

    SimExc_General Thrown if the object does not implement the memory space interface.

    RETURN VALUE
    The byte read.
    EXECUTION CONTEXT
    Cell Context

    SIM_read_phys_memory()

    NAME
    SIM_read_phys_memory — read data from a physical address
    SYNOPSIS
    uint64
    SIM_read_phys_memory(conf_object_t *NOTNULL cpu,
                         physical_address_t paddr,
                         int length);
    

    DESCRIPTION
    Reads length bytes from address paddr in the physical memory space associated with the processor cpu.

    Up to 8 bytes can be read in one call. The memory access will be of inquiry type, i.e. no timing-model or snoop device will be called.

    For non-inquiry accesses, use the memory_space interface directly.

    EXCEPTIONS
    SimExc_Memory Thrown if no memory defined at paddr.

    SimExc_Attribute Thrown if length is out of range.

    SimExc_General Thrown if the processors physical memory does not implement the necessary interface methods.

    RETURN VALUE
    The read data, zero-extended.
    EXECUTION CONTEXT
    Cell Context

    SIM_read_phys_memory_tags()

    NAME
    SIM_read_phys_memory_tags, SIM_write_phys_memory_tags — access auxiliary bits in physical memory
    SYNOPSIS
    uint64
    SIM_read_phys_memory_tags(conf_object_t *NOTNULL mem_space,
                              physical_address_t paddr, unsigned ntags);
    

    void
    SIM_write_phys_memory_tags(conf_object_t *NOTNULL mem_space,
                               physical_address_t paddr,
                               uint64 tag_bits, unsigned ntags);
    

    DESCRIPTION
    Reads or writes ntags auxiliary bits starting at paddr in the physical memory space mem_space. Up to 64 bits can be accessed at once. The bits are specified and returned right-aligned, least significant bit corresponding to the lowest address.
    EXECUTION CONTEXT
    Cell Context

    SIM_write_phys_memory()

    NAME
    SIM_write_phys_memory — write data to a physical address
    SYNOPSIS
    void
    SIM_write_phys_memory(conf_object_t *NOTNULL cpu,
                          physical_address_t paddr,
                          uint64 value, int length);
    

    DESCRIPTION
    Writes length bytes to address paddr in the physical memory space associated with the processor cpu.

    Up to 8 bytes can be written in one call. The memory access will be of inquiry type, i.e. no timing-model or snoop device will be called.

    EXCEPTIONS
    SimExc_Memory Thrown if no memory defined at paddr.

    SimExc_Attribute Thrown if length is out of range.

    SimExc_General Thrown if the processors physical memory does not implement the necessary interface methods.

    EXECUTION CONTEXT
    Cell Context

    Modules

    SIM_add_module_dir()

    NAME
    SIM_add_module_dir — add loadable module search path
    SYNOPSIS
    void
    SIM_add_module_dir(const char *path);
    

    DESCRIPTION
    Add given path to the list of paths where Simics searches for loadable modules. The function SIM_module_list_refresh has to be called after calling this function, for the change to take effect.
    EXECUTION CONTEXT
    Global Context

    SIM_get_all_failed_modules()

    NAME
    SIM_get_all_failed_modules — return a list of all modules that failed to load
    SYNOPSIS
    attr_value_t
    SIM_get_all_failed_modules();
    

    DESCRIPTION
    A failed module is a module that is not loadable by the current version of Simics. The list returned contains information about why the module failed. Each list entry is another list with module specific information. The layout of this sub-list is described below. The list may change in future Simics versions.
    • name - Module name (string).
    • path - File system path to the module (string).
    • duplicate - Flag indicating a duplicate module (boolean).
    • linker - Flag indicating a linker error (boolean).
    • version - Simics ABI version that the module was built for (integer).
    • build_id - Simics build number when the module was built (integer).
    • build_date - When the module was built, in seconds from epoch (integer).
    • user version - User version of the module (string).
    • error - Error message, typically from the linker (string or nil).
    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_get_all_modules

    SIM_get_all_modules()

    NAME
    SIM_get_all_modules — return a list of all modules
    SYNOPSIS
    attr_value_t
    SIM_get_all_modules();
    

    DESCRIPTION
    The list returned contains information about all modules that can be loaded into Simics. Each list entry is another list with module specific information. The layout of this sub-list is described below. The list may grow in future Simics version, but the currently defined fields will not change.
    • name - Module name (string).
    • path - File system path to the module (string).
    • loaded - Flag indicating that the module is already loaded (boolean).
    • version - Oldest Simics ABI version that the module was built for (integer).
    • user version - User version of the module (string).
    • build-id - Simics build-id that indicates in which Simics build this module was created (integer).
    • build-date - Build date of the module, in seconds (integer).
    • classes - Classes this module claims to implement.
    • thread-safe - If the module is thread-safe.
    • components - Components this module claims to implement.
    • user path - Module was loaded from path provided by user.
    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_get_all_failed_modules

    SIM_load_module()

    NAME
    SIM_load_module — load a module
    SYNOPSIS
    void
    SIM_load_module(const char *NOTNULL module);
    

    DESCRIPTION
    Load a Simics module. Normally, modules are loaded automatically as needed for the configuration classes they implement, and there is rarely any need to call this function explicitly.

    The module argument is the name of the module (not file name) to be loaded.

    EXCEPTIONS
    SimExc_License Thrown if the module requires a non-existing license feature.

    SimExc_General Thrown if the module failed to load for other reasons.

    EXECUTION CONTEXT
    Global Context

    SIM_module_list_refresh()

    NAME
    SIM_module_list_refresh — refresh list of loadable modules
    SYNOPSIS
    void
    SIM_module_list_refresh();
    

    DESCRIPTION
    Simics maintains a list of all modules that can be loaded successfully. If a module is changed or added, the list has to be refreshed before Simics can load this module.
    EXECUTION CONTEXT
    Global Context

    Object Locks

    SIM_ASSERT_CELL_CONTEXT()

    NAME
    SIM_ASSERT_CELL_CONTEXT — assert Cell Context
    SYNOPSIS
    SIM_ASSERT_CELL_CONTEXT(obj);
    

    DESCRIPTION
    The SIM_ASSERT_CELL_CONTEXT function verifies that cell thread domain associated with obj is held by the calling thread and raises a hard failure if this is not the case.

    In other worlds, the macro ensures that the execution context is either Cell Context or Global Context.

    SIM_ASSERT_OBJECT_LOCK()

    NAME
    SIM_ASSERT_OBJECT_LOCK — assert thread domain is held
    SYNOPSIS
    SIM_ASSERT_OBJECT_LOCK(obj);
    

    DESCRIPTION
    The SIM_ASSERT_OBJECT_LOCK function checks that the thread domain associated with obj is held. A hard failure is raised if the thread domain is not held.

    SIM_acquire_cell()

    NAME
    SIM_acquire_cell, SIM_release_cell, SIM_ACQUIRE_CELL, SIM_RELEASE_CELL — enter Cell Context
    SYNOPSIS
    domain_lock_t *
    SIM_acquire_cell(conf_object_t *NOTNULL obj,
                     const char *NOTNULL function_name,
                     const char *NOTNULL source_location);
    

    void
    SIM_release_cell(conf_object_t *NOTNULL obj, domain_lock_t *lock);
    

    SIM_ACQUIRE_CELL(obj, lockp);
    

    SIM_RELEASE_CELL(obj, lockp);
    

    DESCRIPTION
    Enters Cell Context for the cell associated with the object obj.

    As part of entering Cell Context, the cell thread domain for the cell associated with obj is acquired.

    Entering Cell Context multiple times is allowed, but acquired thread domains must be released in strict reverse order.

    This function will block until the cell is available if another thread is currently holding the cell thread domain. While blocking, any previously held domains can be acquired by the thread already in Cell Context. Thus, the caller must be prepared to handle e.g. incoming interface calls.

    In Cell Context, API functions marked with Cell Context or Global Context can be called safely, and interfaces on objects belonging to the same cell can be called directly. More generally, the full Standard Device Model applies in Cell Context. Refer to the chapter about threading in the API Reference Manual for more details.

    The macro version of this API call sets the function_name and source_location arguments automatically with the information where the API call was made. This data is used when lock statistics collection is enabled through the enable-object-lock-stats command.

    SEE ALSO
    SIM_acquire_object, SIM_acquire_target
    RETURN VALUE
    SIM_acquire_cell returns a domain lock handle which should be passed as an argument to SIM_release_cell when the lock is released. SIM_ACQUIRE_CELL does not return anything but instead stores the domain lock handle in the pointer passed as the second argument.
    EXECUTION CONTEXT
    Any

    SIM_acquire_object()

    NAME
    SIM_acquire_object, SIM_release_object, SIM_ACQUIRE_OBJECT, SIM_RELEASE_OBJECT — acquire thread domain
    SYNOPSIS
    domain_lock_t *
    SIM_acquire_object(conf_object_t *NOTNULL obj,
                       const char *NOTNULL function_name,
                       const char *NOTNULL source_location);
    

    void
    SIM_release_object(conf_object_t *NOTNULL obj, domain_lock_t *lock);
    

    SIM_ACQUIRE_OBJECT(obj, lockp);
    

    SIM_RELEASE_OBJECT(obj, lockp);
    

    DESCRIPTION
    Acquires the thread domain associated with the object obj.

    A particular thread domain can only be held by a single thread at a time, and this function blocks until the domain is available. Once the domain is held, the thread can safely access state protected by the domain.

    While blocking, any previously held domains can be acquired by threads with higher priority, such as a thread running in Cell Context.

    More than one thread domain can be held simultaneously, and the same thread domain may be acquired multiple times. However, domains must be released in strict reverse order.

    This function is typically used by models using the Threaded Device Model to acquire the model's own thread domain from its interface methods. In this case, obj is set to the model itself.

    The macro version of this API call sets the function_name and source_location arguments automatically with the information where the API call was made. This data is used when lock statistics collection is enabled through the enable-object-lock-stats command.

    More details about thread domains and the threading model are available in the chapter about threading in the API Reference Manual.

    SEE ALSO
    SIM_acquire_target, SIM_acquire_cell
    RETURN VALUE
    SIM_acquire_object returns a domain lock handle which should be passed as an argument to SIM_release_object when the lock is released. SIM_ACQUIRE_OBJECT does not return anything but instead stores the domain lock handle in the pointer passed as the second argument.
    EXECUTION CONTEXT
    Any

    SIM_acquire_object_for_execution()

    NAME
    SIM_acquire_object_for_execution — acquire object lock for execution
    SYNOPSIS
    domain_lock_t *
    SIM_acquire_object_for_execution(conf_object_t *NOTNULL obj);
    

    DESCRIPTION
    Acquire the thread domain lock associated with object arg.

    Note: This API function is considered tech-preview and may change without notice.

    RETURN VALUE
    Domain lock handle which should be passed as an argument to SIM_release_object when the lock is released.
    EXECUTION CONTEXT
    Any

    SIM_acquire_target()

    NAME
    SIM_acquire_target, SIM_release_target, SIM_ACQUIRE_TARGET, SIM_RELEASE_TARGET — conditionally enter Cell Context
    SYNOPSIS
    domain_lock_t *
    SIM_acquire_target(conf_object_t *NOTNULL obj,
                       const char *NOTNULL function_name,
                       const char *NOTNULL source_location);
    

    void
    SIM_release_target(conf_object_t *NOTNULL obj, domain_lock_t *lock);
    

    SIM_ACQUIRE_TARGET(obj, lockp);
    

    SIM_RELEASE_TARGET(obj, lockp);
    

    DESCRIPTION
    Enters Cell Context if the specified object obj uses the Standard Device Model. The function does nothing if obj is a thread-aware object, i.e., if the object belongs to a thread-domain other than the cell.

    The intended use for this function is ensuring that Cell Context is entered before a code running in Threaded Context invokes an interface on some external object. If the external object is thread aware, and does not require Cell Context, this function avoids entering Cell Context as an optimization.

    The macro version of this API call sets the function_name and source_location arguments automatically with the information where the API call was made. This data is used when lock statistics collection is enabled through the enable-object-lock-stats command.

    RETURN VALUE
    SIM_acquire_target returns a domain lock handle which should be passed as an argument to SIM_release_target when the lock is released. SIM_ACQUIRE_TARGET does not return anything but instead stores the domain lock handle in the pointer passed as the second argument.
    SEE ALSO
    SIM_acquire_object, SIM_acquire_cell
    EXECUTION CONTEXT
    Any

    SIM_drop_thread_domains()

    NAME
    SIM_drop_thread_domains, SIM_reacquire_thread_domains, SIM_DROP_THREAD_DOMAINS, SIM_REACQUIRE_THREAD_DOMAINS — temporarily release all held thread domains
    SYNOPSIS
    domain_lock_t *
    SIM_drop_thread_domains();
    

    void
    SIM_reacquire_thread_domains(domain_lock_t *dl);
    

    SIM_DROP_THREAD_DOMAINS(obj, lockp);
    

    SIM_REACQUIRE_THREAD_DOMAINS(obj, lockp);
    

    DESCRIPTION
    Temporarily releases all held thread domains and enters Threaded Context.

    This function is intended to use before blocking is initiated on an external synchronization mechanism, like a condition variable. Releasing thread domains before blocking is often necessary to avoid deadlock situations where other threads get stuck trying to acquire thread domains held by the blocking thread.

    Each call to SIM_drop_thread_domains must be followed with a call to SIM_reacquire_thread_domains to reacquire the released thread domains. This must be done from the same thread.

    If the purpose of the call is just to provide other threads an opportunity to acquire held domains, then the more efficient SIM_yield_thread_domains should be used instead.

    The macro versions of the API calls are currently wrappers of the corresponding SIM-function. In the future, they might collect extra information about where in the code the domain locks are reacquired.

    RETURN VALUE
    SIM_drop_thread_domains returns a domain lock handle which should be passed as an argument to SIM_reacquire_thread_domains_object. The SIM_DROP_THREAD_DOMAINS does not return anything but instead stores the domain lock handle in the pointer passed as the second argument.
    SEE ALSO
    SIM_yield_thread_domains
    EXECUTION CONTEXT
    Any

    SIM_yield_thread_domains()

    NAME
    SIM_yield_thread_domains — yield held thread domains
    SYNOPSIS
    void
    SIM_yield_thread_domains();
    

    DESCRIPTION
    Yields held thread domains if there are other threads waiting to acquire them.

    The function blocks until all threads waiting for one of the held domains have had the opportunity to acquire the domain in question, and then resumes execution with the domains held again.

    One example usage of this function is when a CPU model is notified through the execute_control interface that another thread wants to acquire the CPU's thread domain. Then the CPU function should call this function as quickly as possible, preferably before starting the simulation of the next instruction.

    SEE ALSO
    SIM_drop_thread_domains, SIM_acquire_object
    EXECUTION CONTEXT
    Any

    Output

    SIM_add_output_handler()

    NAME
    SIM_add_output_handler, SIM_remove_output_handler — add or remove output handler
    SYNOPSIS
    void
    SIM_add_output_handler(void (*NOTNULL f)(lang_void *user_data,
                                             const char *text,
                                             size_t length),
                           lang_void *user_data);
    

    void
    SIM_remove_output_handler(void (*NOTNULL f)(lang_void *user_data,
                                                const char *text,
                                                size_t length),
                              lang_void *user_data);
    

    DESCRIPTION
    SIM_add_output_handler registers f(user_data, text, length) to be called whenever there is text output from Simics.

    text contains length bytes of output data. user_data is passed unchanged to the output handler.

    SIM_remove_output_handler removes f as an output recipient. If user_data is NULL, all output handlers with the same function will be removed; otherwise, only those with equal user_data will be removed.

    Output handlers must be thread-safe in order to handle output from different threads properly. There will only be one activation of each handler at a given instant so strict re-entrancy is not required, but proper locking around resources shared with other code should be in place.

    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_write

    SIM_write()

    NAME
    SIM_write, SIM_flush, SIM_putchar, SIM_puts, SIM_printf_vararg, SIM_printf — text output routines
    SYNOPSIS
    int
    SIM_write(const void *NOTNULL src, int length);
    

    int
    SIM_flush();
    

    int
    SIM_putchar(int c);
    

    int
    SIM_puts(const char *NOTNULL s);
    

    int
    SIM_printf_vararg(const char *NOTNULL format, va_list ap);
    

    int
    SIM_printf(const char *NOTNULL format, ...);
    

    DESCRIPTION
    These are the Simics versions of the write, putchar, puts, printf, vprintf, and fflush C library functions. The arguments and return values are the same as for the library functions, except for SIM_write which does not take any file argument.

    The output will be sent to stdout, but more output recipients can be added using the SIM_add_output_handler function. Output is line buffered. SIM_flush will force output of an unterminated line.

    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_add_output_handler

    Path

    SIM_add_directory()

    NAME
    SIM_add_directory — add directory to search path
    SYNOPSIS
    void
    SIM_add_directory(const char *NOTNULL directory, bool prepend);
    

    DESCRIPTION
    Adds a directory to Simics's search path. This is a list of directories which Simics uses when searching for files such as disk dumps, kernel images, etc.

    The directory argument is first converted using SIM_native_path, to yield a path on host native form. If the path does not exist, a frontend exception is raised.

    If prepend is true, the directory is inserted first in the list of directories.

    This list of directories is saved as the attribute simics_path when doing write-configuration. Each directory is first converted to absolute form if relative.

    EXCEPTIONS
    SimExc_General Thrown if the directory does not exist.

    SEE ALSO
    SIM_lookup_file, SIM_clear_directories
    EXECUTION CONTEXT
    Global Context

    SIM_clear_directories()

    NAME
    SIM_clear_directories — clear the search path
    SYNOPSIS
    void
    SIM_clear_directories();
    

    DESCRIPTION
    Deletes all directories from the search path.
    SEE ALSO
    SIM_add_directory, SIM_lookup_file
    EXECUTION CONTEXT
    Global Context

    SIM_get_directories()

    NAME
    SIM_get_directories — get the current search path
    SYNOPSIS
    attr_value_t
    SIM_get_directories();
    

    DESCRIPTION
    Returns the current value of the directory search path.
    EXECUTION CONTEXT
    Cell Context

    SIM_lookup_file()

    NAME
    SIM_lookup_file — find a file using simics search path
    SYNOPSIS
    char *
    SIM_lookup_file(const char *file);
    

    DESCRIPTION
    Searches for a file in the Simics search path.

    The returned path will always be in host native format, so it will not need to be converted. See SIM_native_path for more details on what "host native format" means.

    NULL is returned if file cannot be found.

    The search algorithm is as follows.

    • If file is NULL or an empty string, the function returns NULL.
    • If file exists and is an absolute path, it is converted to host native form and returned.
    • If file starts with %simics%, the rest of the path is looked up first in the current Simics project, and then in all configured Simics packages. If a match is found, the native form of the file found will be returned.
    • If file exists in or relative to the current directory, it is returned without using the Simics search path. This is more or less equivalent of always having "." first in the search path.
    • For each directory in Simics search path: The directory and the file is concatenated and converted to host native format. Each such file is looked up first in the current Simics project, and then in all Simics packages. If a match is found, the native form of the file found will be returned.

    If the file was found, a pointer to the full path to the file is returned. The ownership of the string is passed to the caller.

    SEE ALSO
    SIM_add_directory, SIM_clear_directories
    EXECUTION CONTEXT
    Cell Context

    SIM_native_path()

    NAME
    SIM_native_path — convert path to its native form
    SYNOPSIS
    char *
    SIM_native_path(const char *NOTNULL path);
    

    DESCRIPTION
    Translates a path to its host native form. This functions is a no-op on all platforms except Windows.

    The value returned by this function is allocated and owned by the caller.

    EXECUTION CONTEXT
    Cell Context

    Processor

    SIM_clear_augmentation_bit()

    NAME
    SIM_clear_augmentation_bit, SIM_get_augmentation_bit, SIM_set_augmentation_bit — convenience functions to work with augmented memory bits
    SYNOPSIS
    FORCE_INLINE void
    SIM_clear_augmentation_bit(uint8 *tag_page_data, unsigned pofs);
    

    FORCE_INLINE int
    SIM_get_augmentation_bit(uint8 *tag_page_data, unsigned pofs);
    

    FORCE_INLINE void
    SIM_set_augmentation_bit(uint8 *tag_page_data, unsigned pofs);
    

    DESCRIPTION
    The SIM_clear_augmentation_bit, SIM_get_augmentation_bit, and SIM_set_augmentation_bit functions are used to modify and read augmented memory bits. The direct_memory_tags interface supports augmented memory through the data field in the direct_memory_tags_t struct.
    EXECUTION CONTEXT
    Cell Context

    SIM_disassemble_address()

    NAME
    SIM_disassemble_address — disassemble address
    SYNOPSIS
    tuple_int_string_t
    SIM_disassemble_address(conf_object_t *NOTNULL cpu, generic_address_t address, 
                            int logical, int sub_operation);
    

    DESCRIPTION
    This function disassembles the instruction at the given address. Address is either a physical address (logical == 0) or a logical address (logical == 1). For VLIW architectures, sub_operation is used to select which sub-operation to disassemble. A request for a not present sub-operation (for example sub-operation != 0 for non-VLIW architectures) results in the int part of the return tuple being set to zero.

    A tuple_int_string_t is returned which contains the disassembly string as well as the length of the instruction in bytes. tuple_int_string_t is defined like this:

    typedef struct {
            int integer;
            char *string;
    } tuple_int_string_t;

    For the Sparc and PowerPC targets the length is always 4 bytes.

    This function can be more convenient to use than the disassemble function in the processor_info interface.

    EXCEPTIONS
    SimExc_General Thrown if arguments are invalid.

    SimExc_Memory Thrown if the address is undefined or not mapped in the MMU (for logical addresses).

    EXECUTION CONTEXT
    Cell Context

    SIM_get_all_processors()

    NAME
    SIM_get_all_processors — get list of all processors
    SYNOPSIS
    attr_value_t
    SIM_get_all_processors();
    

    DESCRIPTION
    Return a list of all processor objects.
    RETURN VALUE
    List of processors.
    EXECUTION CONTEXT
    Cell Context

    SIM_get_processor()

    NAME
    SIM_get_processor — get processor pointer from number
    SYNOPSIS
    conf_object_t *
    SIM_get_processor(int proc_no);
    

    DESCRIPTION
    Converts processor id number to processor pointer. This function cannot be used until a configuration had been loaded successfully.
    EXCEPTIONS
    SimExc_Index Thrown if no processor with number proc_no exists.

    RETURN VALUE
    The processor pointer, NULL on failure.
    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_number_processors

    SIM_get_processor_number()

    NAME
    SIM_get_processor_number — get the number of a processor
    SYNOPSIS
    int
    SIM_get_processor_number(const conf_object_t *NOTNULL cpu);
    

    DESCRIPTION
    Returns the global processor number for a processor in Simics.
    RETURN VALUE
    The processor number
    EXECUTION CONTEXT
    Cell Context

    SIM_number_processors()

    NAME
    SIM_number_processors — number of processors
    SYNOPSIS
    int
    SIM_number_processors();
    

    DESCRIPTION
    Returns the current total number of processors in the system.
    RETURN VALUE
    Number of processors.
    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_get_processor

    SIM_processor_privilege_level()

    NAME
    SIM_processor_privilege_level — return the current privilege level for a processor
    SYNOPSIS
    int
    SIM_processor_privilege_level(conf_object_t *NOTNULL cpu);
    

    DESCRIPTION
    Return the current privilege level for a processor. The definition of privilege levels depends on the processor type.
    RETURN VALUE
    For SPARC, and PowerPC, and ARM processors: 0 for User mode, and 1 for Supervisor mode.
    For x86 and IA-64 processors: 0-3, where 0 is the most privileged.
    For MIPS processors: 0
    EXCEPTIONS
    SimExc_General Thrown if cpu does not implement the privilege level interface function.

    EXECUTION CONTEXT
    Cell Context

    SIM_reset_processor()

    NAME
    SIM_reset_processor — reset the processor
    SYNOPSIS
    void
    SIM_reset_processor(conf_object_t *NOTNULL cpu, int hard_reset);
    

    DESCRIPTION
    Performs a reset on the processor, causing a System Reset exception to be taken when execution continues. cpu is the processor that should be reset. hard_reset indicates if a soft (0) or hard (1) (power-on type) reset should be performed. If a hard reset is requested, a number of register are initiated with default values.
    EXCEPTIONS
    SimExc_General Thrown if cpu does not implement reset.

    EXECUTION CONTEXT
    Cell Context

    Profiling

    SIM_iter_next()

    NAME
    SIM_iter_next, SIM_iter_addr, SIM_iter_free — Iterate over address profile counters
    SYNOPSIS
    FORCE_INLINE uint64
    SIM_iter_next(addr_prof_iter_t *iter);
    

    FORCE_INLINE generic_address_t
    SIM_iter_addr(addr_prof_iter_t *iter);
    

    FORCE_INLINE void
    SIM_iter_free(addr_prof_iter_t *iter);
    

    DESCRIPTION
    EXPERIMENTAL. While this functionality is expected to be retained in future releases, the interface is likely to change.

    An address profile iterator visits some of the counters of an address profiler in some order. It is obtained from the iter function of the address_profiler interface.

    SIM_iter_next advances the address profile iterator iter to the next nonzero counter and returns the count. It will return 0 when there are no more counters to visit. Note that the order in which the counters are visited is unspecified.

    SIM_iter_addr returns the address of the counter returned by the most recent call to iter_next.

    When you are done with the iterator, deallocate it with SIM_iter_free.

    EXECUTION CONTEXT
    Cell Context

    Simulation Control

    SIM_break_message()

    NAME
    SIM_break_message — stop the simulation
    SYNOPSIS
    void
    SIM_break_message(const char *msg);
    

    DESCRIPTION
    Display the reason why Simics will stop simulation.

    This is similar to SIM_break_simulation, with the difference that it doesn't actually break the simulation. It can be used by code that wants to display a break message and stop the simulation by some other means.

    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_break_simulation

    SIM_break_simulation()

    NAME
    SIM_break_simulation — stop the simulation
    SYNOPSIS
    void
    SIM_break_simulation(const char *msg);
    

    DESCRIPTION
    Ask Simics to stop the simulation as soon as possible, displaying the supplied message.

    Simics will normally stop before the next instruction is executed. If this function is called when an instruction has started executing, and the instruction can be aborted, it will rewind to before the instruction. This might leave the simulation in a state where some repeatable part of the instruction is already executed.

    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_break_message

    SIM_continue()

    NAME
    SIM_continue — run the simulation
    SYNOPSIS
    pc_step_t
    SIM_continue(int64 steps);
    

    DESCRIPTION
    Run the simulation. In typical usage with steps being 0, the simulation will run forward until it is stopped, either by a breakpoint, internal event, or through the user interface.

    With a non-zero steps, Simics will make sure that at least one processor runs steps steps and then stop the simulation. As with steps being 0, the function can also return early if other break criteria are met.

    In order to properly control when simulation stops in time, it is advisable to use step or cycle breakpoints on one or more objects.

    The function returns non-zero if the simulation was started, and 0 otherwise.

    EXCEPTIONS
    SimExc_General Thrown if the simulation could not be started. Check the exception message for more information.

    EXECUTION CONTEXT
    Global Context

    SIM_current_clock()

    NAME
    SIM_current_clock — return current clock
    SYNOPSIS
    conf_object_t *
    SIM_current_clock();
    

    DESCRIPTION
    Returns the clock (an object implementing the cycle interface) that is driving the simulation in the current cell and current thread. In Global Context, NULL is returned.

    Please note that typically model code would use SIM_object_clock to obtain the clock used for posting events. Another alternative for models is to get the initiator of a memory transaction from the memory transaction itself with the functions like SIM_transaction_initiator and SIM_get_mem_op_initiator and use that for event posting.

    The currently running clock returned by this function can be used, for example, to post events right after the current instruction finishes. But, as it is pointed out above, there are other alternatives for getting a clock for posting events. The use of this function is generally discouraged.

    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_object_clock, SIM_transaction_initiator, SIM_get_mem_op_initiator

    SIM_simics_is_running()

    NAME
    SIM_simics_is_running — check if simulation is running
    SYNOPSIS
    bool
    SIM_simics_is_running();
    

    DESCRIPTION
    Returns true if the simulation is running, e.g. if it has been started using SIM_continue, or false otherwise. It also returns true when the simulation is reversing.
    EXECUTION CONTEXT
    Cell Context

    Simulation Independent Services

    SIM_cancel_realtime_event()

    NAME
    SIM_cancel_realtime_event — cancel callback in host time
    SYNOPSIS
    int
    SIM_cancel_realtime_event(int64 id);
    

    DESCRIPTION
    Cancel a callback registered by SIM_realtime_event, whose return value is specified as id.

    Returns 0 if the callback existed and was cancelled, or -1 if no callback with that identifier existed. (No exception is raised.)

    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_realtime_event

    SIM_notify_on_socket()

    NAME
    SIM_notify_on_socket, SIM_notify_on_object, SIM_notify_on_descriptor — register notification on host I/O events
    SYNOPSIS
    void
    SIM_notify_on_socket(socket_t sock, notify_mode_t mode, int run_in_thread,
                         void (*callback)(lang_void *data), lang_void *data);
    

    void
    SIM_notify_on_object(HANDLE obj, int run_in_thread,
                         void (*callback)(lang_void *data), lang_void *data);
    

    void
    SIM_notify_on_descriptor(int fd, notify_mode_t mode, int run_in_thread,
                             void (*callback)(lang_void *data),
                             lang_void *data);
    

    DESCRIPTION
    These functions allow the function callback to be called with argument data whenever a specific I/O event occurs on the host machine. If callback is a null function pointer, a previously installed notification is removed.

    If run_in_thread is 1, the callback function may be run in a thread where it cannot access or call anything in Simics except for these functions and SIM_thread_safe_callback. If run_in_thread is zero, the callback function is always run in Global Context. This may incur a small penalty in latency (time between the occurrence of the host event and execution of callback).

    Values other than 0 and 1 for run_in_thread are reserved.

    Notification on a specific event will be blocked during the execution of its callback function.

    SIM_notify_on_socket will call a registered callback depending on mode:

    mode condition
    Sim_NM_Read Socket is readable, closed, or incoming connection accepted
    Sim_NM_Write Socket is writeable, or outgoing connection has completed

    Socket notifiers of the mode Sim_NM_Write are not guaranteed to be called again unless a previous attempt to send data to the socket failed for flow control reasons (that is, it would have blocked).

    This means that notifiers of that mode should only be enabled for waiting on the completion of a nonblocking outgoing connection or for a previously "full" socket to accept data again.

    Linux only: SIM_notify_on_descriptor will call a registered callback depending on mode for a given file descriptor in a way similar to SIM_notify_on_socket.

    Windows only: SIM_notify_on_object will call a registered callback when object (which must be a waitable object) is in signalled state. The signalling object is modified in the same way as the Windows wait functions (WaitForMultipleObjects etc).

    Note: A notification should be removed before its socket or descriptor is closed.
    Note: On Windows, sockets registered for notification become nonblocking and must remain so for as long as they are registered. This is a limitation of the underlying Win32 API.
    EXECUTION CONTEXT
    Cell Context (call); Threaded Context (callback with nonzero run_in_thread); Global Context (callback otherwise)
    SEE ALSO
    SIM_thread_safe_callback

    SIM_realtime_event()

    NAME
    SIM_realtime_event — schedule callback in host time
    SYNOPSIS
    int64
    SIM_realtime_event(unsigned delay, void (*NOTNULL callback)(lang_void *data),
                       lang_void *data, int run_in_thread, const char *desc);
    

    DESCRIPTION
    Register callback to be run in delay ms, with argument data. The delay is in real time (on the host machine), and the actual delay may be somewhat larger because of host scheduling.

    If run_in_thread is 1, the callback may be run in a thread where it cannot access or call anything in Simics except for SIM_thread_safe_callback. If run_in_thread is zero, the callback function is always run in Global Context, with the simulation temporarily suspended and the entire Simics API available. This may cause the call to occur slightly later than requested, depending on what Simics is doing at the time.

    Values other than 0 and 1 for run_in_thread are reserved.

    The desc parameter is only present for debugging and has no other effect; it should be a static string describing the callback but may also be left NULL if desired.

    The callback is only called once.

    The return value is a non-zero identifier that can be used to cancel the callback using SIM_cancel_realtime_event.

    EXECUTION CONTEXT
    Cell Context. The callback is called in Threaded Context if run_in_thread is nonzero, in Global Context otherwise.
    SEE ALSO
    SIM_cancel_realtime_event, SIM_thread_safe_callback

    SIM_register_work()

    NAME
    SIM_register_work, SIM_thread_safe_callback, SIM_run_alone — register function to be called in Global Context
    SYNOPSIS
    void
    SIM_register_work(void (*NOTNULL f)(lang_void *data), lang_void *data);
    

    void
    SIM_thread_safe_callback(void (*NOTNULL f)(lang_void *data), lang_void *data);
    

    void
    SIM_run_alone(void (*NOTNULL f)(lang_void *data), lang_void *data);
    

    DESCRIPTION
    SIM_register_work and SIM_thread_safe_callback register work to be done in Global Context as soon as possible, (but not during the call to SIM_register_work or SIM_thread_safe_callback itself).

    SIM_run_alone also registers work to be done in Global Context and if called from Cell Context the callback is executed before the next instruction is dispatched in the cell. If this isn't used the cell may execute several instructions before the callback is executed. If SIM_run_alone is used while an instruction is being emulated then the callback will be invoked when the current instruction has completed and before the next instruction is dispatched.

    No other execution threads are running when the callback is invoked, but their exact position in simulated time may vary between runs. If the callback accesses objects in cells other than the one that SIM_run_alone was called from, then care must be taken to preserve determinism.

    When the callback is run, it is executed in Global Context, which means that it is safe to call any API functions from it. Another thread in the module may at this time also call API functions, if it synchronizes correctly with the callback function. For example, the callback function might just signal to the foreign thread to do its Simics API calls, wait for the thread to signal that it has finished, and then return.

    EXECUTION CONTEXT
    Threaded context (call); Global Context (callback)
    SEE ALSO
    SIM_run_unrestricted

    SIM_run_async_work()

    NAME
    SIM_run_async_work — launch asynchronous work in a separate thread
    SYNOPSIS
    void
    SIM_run_async_work(lang_void *(*NOTNULL async_call)(lang_void *arg),
                       void (*async_ready)(lang_void *async_ret, lang_void *arg),
                       lang_void *arg);
    

    DESCRIPTION
    SIM_run_async_work creates a new thread, running in parallel with the Simics main thread, where the async_call function will be called. Since the function runs in Threaded Context, most Simics API functions are not available. Once the async_call function has run, its return value is passed to async_ready, if supplied, that will be called in Global Context, i.e. in the Simics main thread.

    The user supplied arg parameter is passed unmodified to both callback functions.

    SIM_run_async_work is typically used when calling functions that would block the main thread for a long time while obtaining their result.

    If the result of SIM_run_async_work is used in the simulation, it should be sent through a recorder to make sure that the session can be replayed. See the recorder module and the recorder_v2 interface for more information.

    EXAMPLE
    import socket
    
    def async_call(arg):
        # runs in separate thread without blocking Simics
        return socket.gethostbyname(arg)
    
    def async_ready(ret, arg):
        # runs in Simics main thread with access to the full Simics API
        print("Host %s has IP address %s" % (arg, ret))
    
    simics.SIM_run_async_work(async_call, async_ready, "www.intel.com")
    

    EXECUTION CONTEXT
    Cell Context (call); Threaded Context (async_call callback); Global Context (async_ready callback)
    SEE ALSO
    SIM_notify_on_descriptor, SIM_notify_on_object, SIM_notify_on_socket, SIM_thread_safe_callback, SIM_run_alone, SIM_run_unrestricted

    SIM_run_in_thread()

    NAME
    SIM_run_in_thread — run function in a separate thread
    SYNOPSIS
    void
    SIM_run_in_thread(void (*NOTNULL f)(lang_void *arg), lang_void *arg);
    

    DESCRIPTION
    SIM_run_in_thread schedules the callback f to run on a separate thread. The callback will run in Threaded Context and must observe the associated restrictions.

    Simics maintains a pool of worker threads used by this function, and hence the callback can typically be started quickly.

    The callback is allowed to block or otherwise run for a long time.

    The user supplied arg parameter is passed unmodified to the callback.

    EXECUTION CONTEXT
    Any thread context (call); Threaded Context (callback);
    SEE ALSO
    SIM_run_async_work, SIM_run_alone

    Simulator Translation Caches

    SIM_STC_flush_cache()

    NAME
    SIM_STC_flush_cache, SIM_flush_I_STC_logical, SIM_flush_D_STC_logical, SIM_flush_I_STC_physical, SIM_flush_D_STC_physical — flush or remove entries in the STCs of a cpu
    SYNOPSIS
    void
    SIM_STC_flush_cache(conf_object_t *NOTNULL cpu);
    

    void
    SIM_flush_I_STC_logical(conf_object_t *NOTNULL cpu,
    			logical_address_t vaddr,
                            logical_address_t length);
    

    void
    SIM_flush_D_STC_logical(conf_object_t *NOTNULL cpu,
    			logical_address_t vaddr,
                            logical_address_t length);
    

    void
    SIM_flush_I_STC_physical(conf_object_t *NOTNULL cpu,
                             physical_address_t paddr,
                             physical_address_t length);
    

    void
    SIM_flush_D_STC_physical(conf_object_t *NOTNULL cpu,
                             physical_address_t paddr,
                             physical_address_t length,
                             read_or_write_t read_or_write);
    

    DESCRIPTION
    These functions remove entries from the Simics internal caches (STCs) or completely flushes the STCs contents. Memory mappings which have been cached in the STCs will be faster for Simics to execute. Simics extensions such as a cache model will need to flush entries in the STC when a cache line is replaced, in order to be called when a cache line is used again.

    SIM_STC_flush_cache flushes the entire contents of the STCs (both instruction and data) from the specified cpu.

    The SIM_flush_xxx functions removes specified memory ranges in the instruction or data STC. The address range is either the logical or the physical address. The read_or_write parameter specifies whether the read or the write D-STC should be flushed. If the function doesn't have such a parameter, both read and write D-STCs are flushed. The flushed address range is at least [ vaddr ... (vaddr + length − 1) ], but may be larger. SIM_flush_D_STC_logical currently always flushes an entire page.

    The SIM_flush_xxx functions can only be used on CPUs that implement the internal stc interface; hence, they can not be used on user-defined CPU models.

    EXECUTION CONTEXT
    Cell Context

    SIM_flush_all_caches()

    NAME
    SIM_flush_all_caches — clear Simics's internal caches
    SYNOPSIS
    void
    SIM_flush_all_caches();
    

    DESCRIPTION
    Clears Simics's internal caches such as STC contents and intermediate code. This function is mainly for internal use (for debugging purposes) and may be removed in the future.
    EXECUTION CONTEXT
    Global Context

    SIM_flush_cell_caches()

    NAME
    SIM_flush_cell_caches — clear internal caches for a given cell
    SYNOPSIS
    void
    SIM_flush_cell_caches(conf_object_t *NOTNULL obj);
    

    DESCRIPTION
    Clears internal caches in Simics for a given cell, such as STC contents and intermediate code.
    EXECUTION CONTEXT
    Cell Context

    Stalling

    SIM_stall_count()

    NAME
    SIM_stall_count — get number of cycles a processor has been stalled
    SYNOPSIS
    cycles_t
    SIM_stall_count(conf_object_t *NOTNULL obj);
    

    DESCRIPTION
    SIM_stall_count returns the total number of cycles the processor associated to obj has been stalled.
    RETURN VALUE
    Returns the total number of cycles the processor associated with obj has been stalled.
    EXECUTION CONTEXT
    Cell Context

    SIM_stall_cycle()

    NAME
    SIM_stall_cycle, SIM_stall — stall execution a specified number of cycles
    SYNOPSIS
    void
    SIM_stall_cycle(conf_object_t *NOTNULL obj, cycles_t cycles);
    

    void
    SIM_stall(conf_object_t *NOTNULL obj, double seconds);
    

    DESCRIPTION
    SIM_stall_cycle and SIM_stall set the stall duration of the processor obj. The stall duration is given in clock cycles or seconds and is how long obj will stall before resuming its normal activity. If obj was already stalling, the time remaining is changed. A zero stall duration is a request to cease stalling immediately.

    The specified duration is interpreted as relative the local time of obj.

    obj must implement the stall and cycle interfaces.

    EXECUTION CONTEXT
    Cell Context
    EXCEPTIONS
    SimExc_General Thrown if cycles or seconds is negative.

    SEE ALSO
    SIM_stalled_until, SIM_stall_count

    SIM_stalled_until()

    NAME
    SIM_stalled_until — query how many cycles that remains of stall
    SYNOPSIS
    cycles_t
    SIM_stalled_until(conf_object_t *NOTNULL obj);
    

    DESCRIPTION
    SIM_stalled_until returns how many more cycles the processor will stall before the associated processor starts to execute instructions again.
    EXECUTION CONTEXT
    Cell Context

    Time and Events

    SIM_get_global_message()

    NAME
    SIM_get_global_message — obtain current global message
    SYNOPSIS
    const char *
    SIM_get_global_message(void *ref);
    

    DESCRIPTION
    Return the global message currently being triggered, if ref does not match the reference of the source trigger, otherwise return NULL.

    This function must only be called from a callback of the global notifier Sim_Global_Notify_Message.

    EXECUTION CONTEXT
    Global Context
    SEE ALSO
    SIM_trigger_global_message

    SIM_trigger_global_message()

    NAME
    SIM_trigger_global_message — queue up a global message
    SYNOPSIS
    void
    SIM_trigger_global_message(const char *msg, void *ref);
    

    DESCRIPTION
    This queues up a global message, which will be dispatched shortly in global context, to all listeners of the Sim_Global_Notify_Message global notifier. The ref parameter is the reference of the source, or NULL to dispatch to all listeners.

    The notifier callbacks should use SIM_get_global_message to retrieve the message. Only callbacks that provide a NULL reference or a reference different from ref will obtain the message.

    EXECUTION CONTEXT
    All contexts including Threaded Context
    SEE ALSO
    SIM_get_global_message

    User Interface

    SIM_call_python_function()

    NAME
    SIM_call_python_function — call a Python named function
    SYNOPSIS
    attr_value_t
    SIM_call_python_function(const char *NOTNULL func, attr_value_t *NOTNULL args);
    

    DESCRIPTION
    Calls the Python function named func with arguments in args, which must be a list.

    The namespace searched for func is the same as the Simics commands @ and python use; i.e., the Python module __main__. You may want to use a module-relative name for func such as __builtin__.repr when calling functions not defined at the Simics command-line. This avoids calling any local redefinition of that function.

    EXCEPTIONS
    SimExc_Type Thrown if args is not list or cannot be converted to Python or if func is not callable or if the return value cannot be converted to an attr_value_t.

    SimExc_Lookup Thrown if func does not exist.
    SimExc_General Thrown if there was an error executing Python code.
    SimExc_Break Thrown on user interrupt.

    RETURN VALUE
    Return value of the Python function
    EXECUTION CONTEXT
    Cell Context
    SEE ALSO
    SIM_make_attr_list, SIM_run_python

    SIM_get_api_function()

    NAME
    SIM_get_api_function — return an API function by name
    SYNOPSIS
    api_function_t
    SIM_get_api_function(const char *function);
    

    DESCRIPTION
    Looks up a C function in the Simics API based on its name and returns a pointer to it. Typically used to access a function added to the Simics API in an update release (minor version) while remaining binary compatible with older versions of Simics.

    The pre-processor macro GET_API_FUNCTION provides wrapping of SIM_get_api_function for simpler type casting.

    SIM_get_api_function is neither available nor needed in Python. Code examples showing how to access a new function in a backward compatible in Python are provided below.

    EXAMPLE
    A new function SIM_foo is introduced in the Simics release with build id 5234. Since older versions of Simics do not have this function, a module writer that wants to use it while remaining compatible with old Simics versions, can write the following:
        GET_API_FUNCTION(tmp_SIM_foo, SIM_foo);
        if (tmp_SIM_foo != NULL)
            tmp_SIM_foo(1);
        else
            // code for older versions
       

    Once compatibility with versions before build id 5234 can be dropped, the code in the example is simply replaced with a direct call to SIM_foo.

    In Python, one can check whether the function is present like this:

        if hasattr(simics, 'SIM_foo'):
            simics.SIM_foo(1)
        else:
            # code for older versions
       

    Another alternative for Python code is to check the build id value:

        if conf.sim.build_id >= 5234:
            simics.SIM_foo(1)
        else:
            # code for older versions
       

    RETURN VALUE
    Returns a pointer to the API function if it exists or zero. The return type api_function_t is defined as:
    typedef void (*api_function_t)(void);

    EXECUTION CONTEXT
    Cell Context

    SIM_get_batch_mode()

    NAME
    SIM_get_batch_mode — return setting of the batch-mode
    SYNOPSIS
    bool
    SIM_get_batch_mode();
    

    DESCRIPTION
    This function returns the current value of Simics's batch-mode flag.
    EXECUTION CONTEXT
    Cell Context

    SIM_get_debugger()

    NAME
    SIM_get_debugger — return the debugger object
    SYNOPSIS
    conf_object_t *
    SIM_get_debugger();
    

    DESCRIPTION
    Returns the Simics Debugger. The returned object is the object which implements the Simics Debugger API. The debugger object is created if it does not already exist. Returns NULL and signals an exception if the debugger could not be created.
    RETURN VALUE
    Returns the debugger object
    EXCEPTIONS
    SimExc_General Thrown if the debugger could not be created.
    EXECUTION CONTEXT
    Global Context

    SIM_load_target()

    NAME
    SIM_load_target — load Simics target from file
    SYNOPSIS
    attr_value_t
    SIM_load_target(const char *NOTNULL target,
                    const char *ns, attr_value_t presets,
                    attr_value_t cmdline_args);
    

    DESCRIPTION
    Load the target target into Simics. This can either be a file name or a target name, as returned by the list-targets command.

    This function is functionally equivalent to invoking the script by passing it as a command line argument or to running the script with the load-target or run-script command, with the local flag set.

    The ns and presets arguments have the same semantics as namespace and presets arguments to the run-script command.

    The cmdline_args argument should be a list of 2-element lists of target parameters [name, value].

    EXCEPTIONS
    SimExc_Break Thrown if the script was interrupted by the user.

    SimExc_General Thrown if the script was interrupted by an error.

    SimExc_IOError Thrown if the script file could not be opened.

    EXECUTION CONTEXT
    Global Context

    SIM_quit()

    NAME
    SIM_quit — quit Simics
    SYNOPSIS
    void
    SIM_quit(int exit_code);
    

    DESCRIPTION
    Quit Simics in an orderly fashion. The Simics process will return the value exit_code & 0xFF, since the exit(3) call from the C standard library is used (see its man page). See the Core_Clean_At_Exit and Core_At_Exit haps for ways to run user code when Simics exits. Callbacks for the Core_Clean_At_Exit hap will only run if SIM_quit is called from Global Context, while Core_At_Exit is always called
    EXECUTION CONTEXT
    Cell Context. Global Context if possible.

    SIM_run_command()

    NAME
    SIM_run_command — evaluate a CLI command
    SYNOPSIS
    attr_value_t
    SIM_run_command(const char *NOTNULL line);
    

    DESCRIPTION
    Runs a CLI command and returns the value, if any, as an attr_value_t.
    EXCEPTIONS
    SimExc_General Thrown if there was an error executing the CLI command.

    SimExc_Type Thrown if the return value could not be converted to an attr_value_t.

    EXECUTION CONTEXT
    Global Context

    SIM_run_command_file()

    NAME
    SIM_run_command_file, SIM_run_command_file_params — read CLI commands from file
    SYNOPSIS
    void
    SIM_run_command_file(const char *NOTNULL file, bool local);
    

    void
    SIM_run_command_file_params(const char *NOTNULL file, bool local,
                                attr_value_t params);
    

    DESCRIPTION
    Read and execute the script file file; i.e., execute each line in the file as if it was typed at the Simics prompt.

    This function is functionally equivalent to invoking the script by passing it as a command line argument or to running the script with the run-command-file command.

    If local is true, the script will run with its own copy of all global CLI variables. When the script has finished executing, the previous variable set is restored.

    The params argument can be used to pass parameters to the script. It must be a list of name-value pairs of strings, for example, from Python it could be [["num_cores", "4"], ["memory_megs", "1024"]].

    EXCEPTIONS
    SimExc_Break Thrown if the script was interrupted by the user.

    SimExc_General Thrown if the script was interrupted by an error.

    SimExc_IOError Thrown if the script file could not be opened.

    EXECUTION CONTEXT
    Global Context

    SIM_run_python()

    NAME
    SIM_run_python — run a Python expression
    SYNOPSIS
    attr_value_t
    SIM_run_python(const char *NOTNULL line);
    

    DESCRIPTION
    SIM_run_python runs a Python expression or statement. The return value, if any, is converted to a Simics attribute value. If line is a statement, a NIL attribute is returned.
    EXCEPTIONS
    SimExc_General Thrown if there was an error executing Python code.

    SimExc_Type Thrown if the return value could not be converted to an attr_value_t.

    SimExc_Break Thrown on user interrupt.

    SEE ALSO
    SIM_call_python_function
    EXECUTION CONTEXT
    Cell Context

    SIM_shutdown()

    NAME
    SIM_shutdown — shutdown Simics
    SYNOPSIS
    void
    SIM_shutdown();
    

    DESCRIPTION
    Perform the same clean up as SIM_quit, but do not exit the process. After having called this function, no Simics API function can be called.
    EXECUTION CONTEXT
    Cell Context. Global Context if possible.

    SIM_source_python()

    NAME
    SIM_source_python, SIM_source_python_in_module — execute Python source file
    SYNOPSIS
    void
    SIM_source_python(const char *NOTNULL file);
    

    void
    SIM_source_python_in_module(const char *NOTNULL file,
                                const char *NOTNULL module);
    

    DESCRIPTION
    SIM_source_python executes Python from file in the global Python scope. SIM_source_python_in_module is similar but executes the file contents in a named Python module.
    EXCEPTIONS
    SimExc_General Thrown if there was an error executing Python code.

    SimExc_IOError Thrown if there was an error opening the file.

    SimExc_Break Thrown on user interrupt.

    EXECUTION CONTEXT
    Global Context

    7 Simulator-to-Simulator Interfaces

    address_profiler

    Description
    Interface for getting statistics out of profilers. The target is some kind of profiler whose data can be meaningfully viewed as counts per address.

    The function num_views returns the number k of different ways you can view the data of this object. The view selection parameter view to all other functions in the interface accepts values between 0 and k − 1.

    description returns a short string that explains what the data means. physical_addresses returns true if the profiler works with physical addresses, or false if it uses virtual addresses. address_bits returns the number of bits in an address.

    granularity_log2 returns the base 2 logarithm of the size, in bytes, of the address intervals that the counters are associated to. For example, if the data is instruction execution count and each instruction is 4 bytes long, one would expect the granularity to be at least 4 bytes since that is the smallest interval containing a whole instruction (but it might be more, if the profiler is less fine-grained for some reason). And for a 4-byte granularity, granularity_log2 would return 2.

    sum returns the sum of all counters between start and stop, inclusive. max returns the maximum value of any counter in the range.

    iter returns an address profile iterator that will visit all nonzero counters in the range precisely once, in some order. In C, you can use the functions SIM_iter_next, SIM_iter_addr and SIM_iter_free to operate the iterator. In Python, it works just like any other iterator, and returns (count, address) pairs. Note that you may not continue to use the iterator after the underlying address profiler has been modified.

    SIM_INTERFACE(address_profiler) {
            addr_prof_iter_t *(*iter)(conf_object_t *prof_obj, unsigned view,
                                      generic_address_t start,
                                      generic_address_t stop);
            uint64 (*sum)(conf_object_t *prof_obj, unsigned view,
                          generic_address_t start, generic_address_t end);
            uint64 (*max)(conf_object_t *prof_obj, unsigned view,
                          generic_address_t start, generic_address_t end);
            unsigned (*granularity_log2)(conf_object_t *prof_obj, unsigned view);
            int (*address_bits)(conf_object_t *prof_obj, unsigned view);
            int (*physical_addresses)(conf_object_t *prof_obj, unsigned view);
            const char *(*description)(conf_object_t *prof_obj, unsigned view);
            unsigned (*num_views)(conf_object_t *prof_obj);
    };
    
    #define ADDRESS_PROFILER_INTERFACE "address_profiler"
    

    Execution Context
    Cell Context for all methods.

    branch_arc

    Description

    Interface for getting branch arcs out profilers. The target is some kind of profiler whose data can be meaningfully viewed as branch arcs (usually a branch profiler).

    iter returns a branch arc iterator that will visit all branch arcs in the range precisely once, in order of selected address (to or from, selected with dir), other address and type. In Python, it works just like any other iterator, and returns (from, to, counter, type) tuples. Note that you may not continue to use the iterator after the underlying profiler has been modified.

    branch_arc_type_t defines the branch types returned by a branch arc iterator.

    Branch_Arc_Branch
    Normal branch operation
    Branch_Arc_Exception
    Branch because an exception was encountered
    Branch_Arc_Exception_Return
    Branch to finish an exception handler

    typedef enum {
            Branch_Arc_Branch,
            Branch_Arc_Exception,
            Branch_Arc_Exception_Return,
            Branch_Arc_Max
    } branch_arc_type_t;

    typedef enum {
            BR_Direction_From,
            BR_Direction_To
    } branch_recorder_direction_t;

    SIM_INTERFACE(branch_arc) {
            branch_arc_iter_t *(*iter)(conf_object_t *prof_obj,
                                       generic_address_t start,
                                       generic_address_t stop,
                                       branch_recorder_direction_t dir);
    };
    
    #define BRANCH_ARC_INTERFACE "branch_arc"
    

    Execution Context
    Cell Context for all methods.

    break_strings_v2

    Description
    The break_strings_v2 interface facilitates management of string breakpoints. It is implemented by the text console and the graphics console (but will only function when in text mode).

    The text console tries to match each break string on the stream of characters coming from the attached serial device, and if a match occurs, the given callback function will be called. If no callback is given, the simulation will be stopped. The graphics console behaves in the same way, but in this case the character stream is defined by what is sent to the console via the vga_text_update interface. Break strings only lives during a single Simics session, they are not checkpointed.

    The add method registers a breakpoint string str, and returns a breakpoint ID, unique during the Simics session, which is also passed to cb when the breakpoint matches. If cb is not NULL, then this function will be called on breakpoint match, otherwise a match stops the simulation.

    The add_single method is similar to add, but the breakpoint is removed automatically after the first match.

    The add_regexp method is similar to add, but the given string is interpreted as a regular expression. The support regular expression syntax is that of the Hyperscan library https://hyperscan.io.

    The remove method deactivates a previously activated breakpoint.

    SIM_INTERFACE(break_strings_v2) {
            int64 (*add)(conf_object_t *NOTNULL obj, const char *str,
                         break_string_cb_t cb, lang_void *arg);
            int64 (*add_single)(conf_object_t *NOTNULL obj, const char *str,
                                break_string_cb_t cb, lang_void *arg);
            int64 (*add_regexp)(conf_object_t *NOTNULL obj, const char *str,
                                break_string_cb_t cb, lang_void *arg);
            void (*remove)(conf_object_t *NOTNULL obj, int64 bp_id);
    };
    #define BREAK_STRINGS_V2_INTERFACE "break_strings_v2"
    

    Execution Context
    Global Context for all methods

    breakpoint_manager

    Description
    An internal interface used by the breakpoint manager. Can be changed at any time.
    Execution Context
    Internal.

    breakpoint_type

    Description
    The breakpoint_type interface is implemented by the breakpoint manager and facilitates registering breakpoint types.

    This interface is currently a tech preview and can be changed at any time.

    The register_type method registers a breakpoint type and creates CLI commands for this type. The name parameter should be the unique name for the type, which is also used in the names of any commands registered on interfaces or class. The provider parameter should be the provider object, which must implement the breakpoint_type_provider interface.

    The registered commands are break, run-until, wait-for, trace and untrace, which are registered on the provider class. If cls or iface are non-NULL, commands are also registered on that class or interface. These commands are bp-break-{name}, bp-run-until-{name}, bp-wait-for-{name}, bp-trace-{name} and bp-untrace-{name}, where {name} is the name parameter.

    The cls and iface parameters cannot both be non-NULL.

    The args parameter is a list that defines the CLI command arguments. It should be a list of lists where each inner list contains the name of the cli.Arg_type subclass, such as str_t, flag_t etc, and then all parameters to its constructor (including values for parameters that have default values).

    The docs parameter should be an 8-element list with short and long command documentation texts for the four commands break, run-until, wait-for and trace.

    The object_required parameter indicates if the commands registered on the provider class (as opposed to the commands on the class or interface) should require an object (or if the command can use a default object). Note that there will only be an object parameter if cls or iface are non-NULL.

    The temporary_default parameter indicates if the breakpoints of this type should be temporary by default. This also results in the generated break command not having a -once flag.

    Setting recursive to true will append a '-recursive' flag to both global and object commands, and for the global command, the 'object' argument will have no specified class or iface.

    The trigger method must be called by the provider every time a breakpoint triggers, both breakpoints added with register_bp method and those added with add_bp method of the breakpoint_type_provider interface.

    SIM_INTERFACE(breakpoint_type) {
            /* Returns false if type is already registered. */
            bool (*register_type)(conf_object_t *NOTNULL mgr,
                                  const char *NOTNULL name,
                                  conf_object_t *NOTNULL provider,
                                  /* CLI command arguments as a list */
                                  attr_value_t args,
                                  /* Class and/or iface for command */
                                  const char *cls,
                                  const char *iface,
                                  /* 8-element list with short and long
                                     command help texts */
                                  attr_value_t docs,
                                  /* Is an object required
                                     (or can it default to something) */
                                  bool object_required,
                                  /* Should breakpoints be temporary by default? */
                                  bool temporary_default,
                                  /* Set to true to allow all objects in 'object' argument */
                                  bool recursive);
            /* Notify manager that breakpoint has triggered, given ID returned by
               add_bp. Returns true if simulation was stopped or otherwise the
               breakpoint action happened. Optionally provide trigger object and
               message, used if the simulation is stopped. */
            bool (*trigger)(conf_object_t *NOTNULL mgr,
                            conf_object_t *NOTNULL provider, uint64 bp_id,
                            conf_object_t *trigger, const char *msg);
            /* Return provider ID from breakpoint manager ID. */
            uint64 (*get_break_id)(conf_object_t *NOTNULL mgr, uint64 bm_id);
            uint64 (*get_manager_id)(conf_object_t *NOTNULL mgr,
                                     conf_object_t *NOTNULL provider, uint64 bp_id);
    };
    #define BREAKPOINT_TYPE_INTERFACE "breakpoint_type"
    

    Execution Context
    Global Context

    breakpoint_type_provider

    Description
    The breakpoint_type_provider interface should be implemented by objects that wish to act as breakpoint type providers towards the breakpoint manager. An object that is passed to the breakpoint manager via the register_type method in the breakpoint_type interface must implement breakpoint_type_provider.

    This interface is currently a tech preview and can be changed at any time.

    The register_bp and add_bp methods receives the command arguments, corresponding to what the breakpoint manager received in the register_type. The register_bp method should set up a breakpoint, register it with the breakpoint manager via the breakpoint_registration interface, and return the breakpoint manager ID for that breakpoint. The add_bp method should set up an internal breakpoint, which is not registered with the breakpoint manager, and return a provider-specific ID for this breakpoint. The breakpoint manager will use this ID to remove the breakpoint via the remove_bp method, and this ID should also be used when calling the trigger method in the breakpoint_type interface.

    The register_bp and add_bp methods should return 0 to indicate an error in setting up the breakpoint.

    The break_msg method should return the message that should be printed by the bp.break command after the breakpoint is set up. It receives the breakpoint manager ID for the breakpoint.

    The trace_msg method should return the message that should be printed when an (internal) trace breakpoint has hit. It receives the provider specific ID for the breakpoint.

    The wait_msg method should return the message that is attached to the script branch while waiting for a breakpoint to hit (displayed by e.g. list-script-branches). It receives the provider specific ID for the breakpoint.

    The optional method break_data can be implemented to make the wait-for and run-until commands return something. It receives the provider specific ID for the breakpoint.

    The method values must be implemented if the provider has specified that CLI command expanders should be used, when registering the breakpoint type. Otherwise the method is not called by the breakpoint manager. It should return the possible values for the command argument arg, which will be one of the argument names used when registering the type. The parameter prev_args will be the list of preceding argument values.

    The deleted method is typically optional. If implemented, it is called by the deleted function of the breakpoint_registration interface. Normally, breakpoint manager registered breakpoints are deleted using the function that was given to the register_breakpoint method of the breakpoint_registration interface, which is used by the bp.delete, but if the breakpoint can be removed by other means, then this method can be implemented.

    SIM_INTERFACE(breakpoint_type_provider) {
            /* Register breakpoint in manager.
               Return breakpoint manager ID, or 0 on error. */
            uint64 (*register_bp)(conf_object_t *NOTNULL obj, uint64 bp_id);
            /* Add breakpoint and return provider specific ID, or 0 on error. */
            uint64 (*add_bp)(conf_object_t *NOTNULL obj,
                             int flags, attr_value_t data);
            /* Remove breakpoint, given ID returned by add_bp. */
            void (*remove_bp)(conf_object_t *NOTNULL obj, uint64 bp_id);
            /* Return trace message, given ID returned by add_bp. */
            char *(*trace_msg)(conf_object_t *NOTNULL obj, uint64 bp_id);
            /* Message returned by break command, given ID returned by add_bp. */
            char *(*break_msg)(conf_object_t *NOTNULL obj, uint64 bp_id);
            /* Script branch wait message, given ID returned by add_bp. */
            char *(*wait_msg)(conf_object_t *NOTNULL obj, uint64 bp_id);
            /* Optional return value from wait-for and run-until commands,
               given ID returned by add_bp. */
            attr_value_t (*break_data)(conf_object_t *NOTNULL obj, uint64 bp_id);
            /* Return possible values for command argument.
               Optional unless expanders used. */
            attr_value_t (*values)(conf_object_t *NOTNULL obj,
                                   const char *arg, attr_value_t prev_args);
            /* Optional trace output function. The default is to log on the
               provider with level 1 and group 0. */
            void (*trace)(conf_object_t *NOTNULL obj, const char *msg);
    };
    #define BREAKPOINT_TYPE_PROVIDER_INTERFACE "breakpoint_type_provider"
    

    Execution Context
    Global Context

    checkpoint

    Description
    The save function in this interface is called when a checkpoint is saved, right before the attributes of an object is read. If defined, it should prepare the object for checkpointing, saving any state to path that is not directly included in the attributes. Default behavior is image to be compressed craff and config to be compressed too. Errors are signalled through exceptions.

    The save_v2 function is same as save but take an extra parameter with the type of save_flags_t to control format of files in the checkpoint other than defaults.

    The path argument may be the empty string, which indicates that the checkpoint bundle directory is the same as the current working directory while the checkpoint is being saved.

    The finish function is called after the checkpoint has been saved, for all objects that save was called for. If success is nonzero, the checkpoint was saved successfully; otherwise there was a failure. This permits the object to clean up temporary data structures and files in either case. In particular, any files written to path in the save method must be removed in finish if success is zero.

    The function has_persistent_data, if implemented, should return 0 if the object only has volatile attributes, 1 otherwise. This overrides Sim_Attr_Persistent on individual attributes.

    SIM_INTERFACE(checkpoint) {
            void (*save)(conf_object_t *obj, const char *NOTNULL path);
            void (*finish)(conf_object_t *obj, int success);
            int (*has_persistent_data)(conf_object_t *obj);
            void (*save_v2)(conf_object_t *obj, const char *NOTNULL path,
                            save_flags_t flags);
    };
    
    #define CHECKPOINT_INTERFACE "checkpoint"
    

    Execution Context
    Global Context for all methods.

    con_input

    Description
    The con_input interface facilitates sending simulated input to the target system. It is implemented by the text console.

    Simulated input is passed through the associated recorder object and then sent to the serial device connected to the console. The console will not perform VT100 input handling or BS/DEL conversion.

    The input_str method allows input of a NUL-terminated string. The input_data allows sending a buffer, which can include NUL characters.

    SIM_INTERFACE(con_input) {
            void (*input_str)(conf_object_t *NOTNULL obj, const char *str);
            void (*input_data)(conf_object_t *NOTNULL obj, bytes_t data);
    };
    #define CON_INPUT_INTERFACE "con_input"
    

    Execution Context
    Global Context

    con_input_code

    Description
    The con_input_code interface facilitates sending simulated key events to the simulation. It is implemented by the graphics console.

    Simulated key events are passed through the associated recorder object and then sent to the keyboard connected to the console.

    The input method sends the key code, either a key press or a release, depending on the down parameter.

    SIM_INTERFACE(con_input_code) {
            void (*input)(conf_object_t *NOTNULL obj, sim_key_t code, bool down);
    };
    #define CON_INPUT_CODE_INTERFACE "con_input_code"
    

    Execution Context
    Global Context

    context_handler

    Description
    Note: This interface is not supported, and may change in the future.
    Get and set current context. The set_current_context function returns zero if the passed object is not of the context class, otherwise one is returned.

    SIM_INTERFACE(context_handler) {
            conf_object_t *(*get_current_context)(conf_object_t *obj);
            int (*set_current_context)(conf_object_t *obj, conf_object_t *ctx);
    };
    
    #define CONTEXT_HANDLER_INTERFACE "context_handler"
    

    Execution Context
    Cell Context for all methods.

    debug_notification

    Description

    This interface is used to get notifications from events in the debugger. Examples of events are when certain functions, addresses or code lines are hit.

    In order to be able to get notifications for symbols, the symbol file containing the debug information must have been added using the debug_setup interface or in some other way.

    All notifications take callback functions that are called when the debugger event occurs. The notifications will not stop the simulation, to do so SIM_break_simulation can be called in the callback.

    For all functions that return an attr_value_t, that return value will consists of a list with two elements. The first element is an error code of debugger_error_t type (see debug_query interface documentation for definition). The second element depends on the first. If the first element is Debugger_No_Error, meaning that the function went well, then the second element will contain the expected return value that is specified per function below. If the first element is another error code, then the second element will be a string describing the error that occurred.

    notify_context_creation provides a callback when a new context that matches the context query query is created or renamed. The callback will also be triggered when a context is renamed, so if the context query matches both the name before and after the context was renamed then there will be two creation callbacks for the same context. When the callback is triggered because of a rename the updated argument of the callback will be true, otherwise if it is triggered because a new context was created the updated argument will be false.

    notify_context_destruction provides a callback when a context that matches the context query query is destroyed.

    The callbacks for notify_context_creation and notify_context_destruction will contain an ID to the context that was created, updated or destroyed, ctx_id, the tcf_agent object obj and some custom data.

    Note: The notify_context_creation and notify_context_destruction callbacks will only trigger for contexts that have state, this is most commonly the leaf nodes in an OS Awareness node tree.
    notify_location will give a callback when a memory access of type access is done at the address specified by location, for contexts matching query. The size argument is used to specify the width of the symbol provided by location. For execution notifications a size of 1 is usually used. The maximum value of size is 0x7fffffff. Notifying on location will only work for global symbols. For symbols that are not global, no errors will be given, and no callback will be triggered.

    notify_address will provide a callback when an address is hit with a certain access type for contexts matching query. The size argument specifies the width of the breakpoint for the notification, with a maximum value of 0x7fffffff. The notification can be set to notify on physical breakpoints instead of virtual, but for that to work a processor or memory space context must be covered by the query. For process related contexts physical should be false.

    notify_line will provide a callback when a specific line and column in a specific source file for a context matching query is executed. The column argument can be set to 0 to not care about column.

    The notification functions notify_location, notify_address and notify_line will all provide callbacks on the same format. They will pass the context ID, ctx_id, for which the access occurred. A processor, cpu, which did the access is provided. The instruction_address is the address of the instruction that performed the access. For execution callbacks the callback will occur before the instruction has run, but for read or write accesses the callback will occur after the instruction has run. The data_address will provide which data address was accesses, for execution accesses this is the same as instruction_address but for read or write accesses this is where the actual access was. And size specifies the actual size of the access that was made to trigger the notification, for execution this size is 1.

    notify_activated and notify_deactivated are used to notify when a context, that matches the query, gets activated or deactivated. The callback for this will include which context, ctx_id, was (de)activated and on what processor, cpu.

    For all notifications functions in this interface, on success, the returned value of a notification function will be a cancel ID which can be used to cancel the notification.

    If several callbacks occur on the same cycle, then the order for which the callbacks are called is not determined. This means that a notify_activated callback for one processor can occur before a notify_deactivated callback on the same processor.

    notify_callbacks_done will be called once all other callbacks that happen because of the same event are done. For example when a move to and a move from is done in the same step then this callback can be used to keep grouped notifications together that occurred at the same time. This will always be called after one or more callbacks have been called.

    cancel is used to cancel a notification by providing it with a cancel ID, cid, that was returned from the notification function. When this goes well the returned value will be nil.

    Errors specific to this function:

    • Debugger_Unknown_Id - The cancel ID, cid, is unknown.

    All callbacks except notify_location, notify_address, and notify_line, with execution access, will occur after the instruction triggering the callbacks has executed. For the callbacks specified here, when using execution access, the callback will occur before the instruction at that location, address or line has executed.

    Note: In order to get contexts for processes, OS Awareness with a properly configured tracker has to exist. A context will then be created for each OS Awareness node. Without any OS Awareness tracker enabled for the system, contexts will only be available for processors and some memory spaces. The notify_activated and notify_deactivated functions will only give callbacks when a tracker is used, because processor contexts are always active. More information about configuring and using OS Awareness and trackers can be found in the Analyzer User's Guide
    Note: For functions that take query as argument, having this set to nil will work the same way as for "*". A bad context query will result in a Debugger_Incorrect_Context_Query error.
    SIM_INTERFACE(debug_notification) {
            attr_value_t (*notify_context_creation)(
                    conf_object_t *NOTNULL obj, const char *query,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj,
                               const char *ctx_id, bool updated),
                    cbdata_register_t data);
            attr_value_t (*notify_context_destruction)(
                    conf_object_t *NOTNULL obj, const char *query,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj,
                               const char *ctx_id), cbdata_register_t data);
            attr_value_t (*notify_location)(
                    conf_object_t *NOTNULL obj, const char *query,
                    const char *NOTNULL location, unsigned size, access_t access,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj,
                               const char *ctx_id, conf_object_t *cpu,
                               uint64 instruction_address, uint64 data_address,
                               unsigned size), cbdata_register_t data);
            attr_value_t (*notify_address)(
                    conf_object_t *NOTNULL obj, const char *query, uint64 address,
                    unsigned size, access_t access, bool physical,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj,
                               const char *ctx_id, conf_object_t *cpu,
                               uint64 instruction_address, uint64 data_address,
                               unsigned size), cbdata_register_t data);
            attr_value_t (*notify_line)(
                    conf_object_t *NOTNULL obj, const char *query,
                    const char *NOTNULL file, unsigned line, unsigned column,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj,
                               const char *ctx_id, conf_object_t *cpu,
                               uint64 instruction_address, uint64 data_address,
                               unsigned size), cbdata_register_t data);
            attr_value_t (*notify_activated)(
                    conf_object_t *NOTNULL obj, const char *query,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj,
                               const char *ctx_id, conf_object_t *cpu),
                    cbdata_register_t data);
            attr_value_t (*notify_deactivated)(
                    conf_object_t *NOTNULL obj, const char *query,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj,
                               const char *ctx_id, conf_object_t *cpu),
                    cbdata_register_t data);
            attr_value_t (*notify_callbacks_done)(
                    conf_object_t *NOTNULL obj,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj),
                    cbdata_register_t data);
            attr_value_t (*cancel)(conf_object_t *NOTNULL obj,
                                   debug_cancel_id_t cid);
    };
    #define DEBUG_NOTIFICATION_INTERFACE "debug_notification"
    

    Execution Context
    Global Context for all methods.

    debug_query

    Description

    This interface provides functions for querying the debugger for contexts and their information. Functions here will be used to find specific contexts or to create context-queries, that can be used with other functions in debugger interfaces.

    Most functions in this interface take a Context ID, ctx_id, as argument. This ID is passed as an argument to most callback functions in the debug_notification interface and returned by some functions in this interface.

    All functions return an attr_value_t consisting of a list with two elements. The first element is an error code of debugger_error_t type. The second element depends on the first. If the first element is Debugger_No_Error, meaning that the function went well, then the second element will contain the expected return value that is specified per function below. If the first element is another error code, then the second element will be a string describing the error that occurred.

    matching_contexts returns a list of context IDs matching the specified context-query, query. The returned list can be empty if there are no matching contexts.

    get_context_group returns a context ID for the context marked as the group leader for the specified context, ctx_id. As example in a Linux tracker the process node will be the group leader for all threads belonging to that process. A context that lacks a specific group leader will return itself.

    get_context_parent returns an ID to the parent context for the specified context.

    Errors specific to this function:

    • Debugger_Not_Supported_For_Context - The context does not have a parent.

    get_context_children returns a list of context IDs for the children of the specified context. This list can be empty if the context has no children.

    query_for_context_group, query_for_context_id and query_for_context_tree will return context-queries which can be used for matching all contexts in a group, the context that matches an ID or contexts in the tree that starts with the specified context. The latter context-query will match the context itself plus all its child contexts, the children of those contexts and so on. The result of these functions should be used with functions that take a context-query as argument.

    context_name returns the name of the specified context.

    Errors specific to this function:

    • Debugger_Not_Supported_For_Context - If the he context lacks a name.

    context_id_for_object returns a context ID for the specified Simics object, ctx_obj, if that has an associated context. In general, processors and some memory spaces usually have contexts associated with them.

    Errors specific to this function:

    • Debugger_No_Context_For_Object - The object does not have any associated context.

    context_has_state returns a boolean that tells whether the specified context has state or not. That a context has state will mean that callbacks in the debug_notification will trigger for this context. The contexts that have state are usually leaf nodes in the OS Awareness node tree.

    object_for_context is used to get a Simics object that matches the context for ctx_id, if such an object exists.

    Errors specific to this function:

    • Debugger_Missing_Object - The context does not match a Simics object.

    get_active_processor is used check if a context is active and in that case return the Simics processor object that the node is active on.

    Errors specific to this function:

    • Debugger_Context_Is_Not_Active - Context is not active.

    Note: For functions that take query as argument, having this set to nil will work the same way as for "*". A bad context query will result in a Debugger_Incorrect_Context_Query error.
    SIM_INTERFACE(debug_query) {
            attr_value_t (*matching_contexts)(conf_object_t *NOTNULL obj,
                                              const char *query);
            attr_value_t (*get_context_group)(conf_object_t *NOTNULL obj,
                                              const char *NOTNULL ctx_id);
            attr_value_t (*get_context_parent)(conf_object_t *NOTNULL obj,
                                               const char *NOTNULL ctx_id);
            attr_value_t (*get_context_children)(conf_object_t *NOTNULL obj,
                                                 const char *NOTNULL ctx_id);
            attr_value_t (*query_for_context_group)(conf_object_t *NOTNULL obj,
                                                    const char *ctx_id);
            attr_value_t (*query_for_context_id)(conf_object_t *NOTNULL obj,
                                                 const char *NOTNULL ctx_id);
            attr_value_t (*query_for_context_tree)(conf_object_t *NOTNULL obj,
                                                   const char *NOTNULL ctx_id);
            attr_value_t (*context_name)(conf_object_t *NOTNULL obj,
                                         const char *NOTNULL ctx_id);
            attr_value_t (*context_id_for_object)(conf_object_t *NOTNULL obj,
                                                  conf_object_t *NOTNULL ctx_obj);
            attr_value_t (*object_for_context)(conf_object_t *NOTNULL obj,
                                               const char *NOTNULL ctx_id);
            attr_value_t (*context_has_state)(conf_object_t *NOTNULL obj,
                                              const char *NOTNULL ctx_id);
            attr_value_t (*get_active_processor)(conf_object_t *NOTNULL obj,
                                                 const char *NOTNULL ctx_id);
    };
    #define DEBUG_QUERY_INTERFACE "debug_query"
    

    typedef enum {
            Debugger_No_Error = 0,
            Debugger_Not_Allowed_In_Execution_Context,
            Debugger_Unknown_Context,
            Debugger_Not_Supported_For_Context,
            Debugger_Context_Does_Not_Have_State,
            Debugger_Context_Is_Not_Active,
            Debugger_Lookup_Failure,
            Debugger_Failed_To_Get_Stack_Frame,
            Debugger_Failed_To_Get_PC,
            Debugger_Failed_To_Read,
            Debugger_Failed_To_Write,
            Debugger_Frame_Outside_Of_Known_Stack,
            Debugger_Failed_To_Evaluate_Expression,
            Debugger_Incorrect_Type,
            Debugger_Incorrect_Size,
            Debugger_Incorrect_Context_Query,
            Debugger_Unknown_Id,
            Debugger_Source_Not_Found,
            Debugger_File_Not_Found,
            Debugger_Unrecognized_File_Format,
            Debugger_Unsupported_For_File_Format,
            Debugger_Failed_To_Open_File,
            Debugger_Not_Relocatable,
            Debugger_Segment_Info_Missing,
            Debugger_Section_Info_Missing,
            Debugger_Segment_Not_Found,
            Debugger_Section_Not_Found,
            Debugger_Already_Running,
            Debugger_Failed_To_Continue,
            Debugger_No_Context_For_Object,
            Debugger_Invalid_Path,
            Debugger_Missing_Object,
            Debugger_Unexpected_Error,
            Debugger_Step_Interrupted,
    } debugger_error_t;
    

    Execution Context
    Global Context for all methods.

    debug_setup

    Description

    Functions in the debug_setup interfaces are used to provide the debugger with symbol files and paths. There are also functions for listing what symbol files and paths have been added.

    For all functions that return an attr_value_t, that return value will consists of a list with two elements. The first element is an error code of debugger_error_t type (see debug_query interface documentation for definition). The second element depends on the first. If the first element is Debugger_No_Error, meaning that the function went well, then the second element will contain the expected return value that is specified per function below. If the first element is another error code, then the second element will be a string describing the error that occurred.

    Upon success, all functions for adding symbols will return an id that can be used with remove_symbol_file.

    add_symbol_file adds a symbol file, symbol_file, used for debugging contexts that match the context-query query. The address argument specifies the address that the file should be mapped to. If absolute_address is set then the given address will be the absolute address of the first relocatable segment and other segments will be added with their given offsets to that segment.

    Errors specific to this function:

    • Debugger_Failed_To_Open_File - File cannot be opened.
    • Debugger_Unrecognized_File_Format - The file format is not recognized.
    • Debugger_Segment_Info_Missing - If an ELF file is being added, but no valid segments can be found.

    add_symbol_segment adds symbols from the specified segment of an ELF symbol file. Other arguments are the same as for add_symbol_file. The address of the segment is specified with the address argument. If absolute_address is set this address will be an absolute address otherwise it will be an offset to the address found in the symbol file for that segment.

    Errors specific to this function:

    • Debugger_Segment_Not_Found - Segment not found when adding a segment.
    • Debugger_Segment_Info_Missing - Segment information is missing or incomplete.
    • Debugger_Not_Relocatable - The segment is not relocatable.
    • Debugger_Unsupported_For_File_Format - File format is not ELF.

    add_symbol_section adds symbols from the specified section of an ELF symbol file. Other arguments are the same as for add_symbol_file. The address of the section is specified with the address argument. If absolute_address is set this address will be an absolute address otherwise it will be an offset to the address found in the symbol file for that section.

    Errors specific to this function:

    • Debugger_Section_Not_Found - Section not found when adding a section.
    • Debugger_Section_Info_Missing - Section information is missing or incomplete.
    • Debugger_Not_Relocatable - The section is not relocatable.
    • Debugger_Unsupported_For_File_Format - File format is not ELF.

    Note: Adding the same symbol file, section or segment more than once might result in unexpected behavior and is not supported.
    remove_symbol_file removes the debugger's knowledge of symbols that was added with any of the functions for adding symbols. The id argument is the id returned from the add function.

    Errors specific to this function:

    • Debugger_Unknown_Id - The id is unknown.

    clear_symbol_files removes the debugger's knowledge about all symbol files added by add_symbol_file.

    symbol_files lists all added symbol files. A dictionary, with id as key will be returned. An id is always bound to one query and one symbol file, but it can contain several memory maps. The listed id is the argument passed to remove_symbol_file. The dictionary values have the following format:

    • query (string) - The context query the symbol is valid for.
    • relocation (uint64) - The relocation address provided when the symbol file was added.
    • symbol-file (string) - The file containing the symbol information.
    • memory-maps ([<dict>, ...]) - A list of memory maps that are added togheter as the same id, see format below:

    The dictionary describing a memory map has the following format:

    • address (uint64) - The address of the section in memory.
    • size (uint64) - The section size in memory.
    • flags (uint64) - Format specific flags describing the section.
    • section (string) - The name of the section.
    • file-offset (uint64) - Offset in symbol file for the section.
    • file-size (uint64) - Size of the section in the symbol file.

    symbol_files_for_ctx is the same as symbol_files except that it only returns symbol files that are valid for the given context id, ctx_id.

    list_all_mappings lists all symbol mappings for a certain context ctx_id. This will be all mappings from symbol files added by users plus any symbol mappings added elsewhere, from trackers for example. The returned value is a dictionary on the following format:

    • filename (string) - The file backing the memory map.
    • query (string) - The query the map is valid for.
    • address (uint64) - The map's address in context memory.
    • size (uint64) - The size of the map in memory.
    • flags (uint64) - Read, write, and execute flags, bit 0 is set if readable, bit 1 if writeable and bit 2 if executable. If this value is 0 this is the same as if all flags are set.
    • section-name (string) - The section name, or NIL.
    • file-offset (int64) - Offset into the backing file.
    • file-size (uint64) - Size of the map in the backing file.
    • relocation (uint64) - The offset from the address in the symbol file to where the mappings is actually loaded in memory. This is not always present in the dictionary.

    Some other internal entries could possibly also be present in the dictionary.

    add_path_map_entry adds a path math entry that maps a source file from the source in the symbol file to the actual destination, dest, where it is located on disk. The query argument specifies for which context-queries the mapping should apply. The returned id can be used with remove_path_map_entry to remove the added path map. The source path may not be empty or be just "." or "./".

    Errors specific to this function:

    • Debugger_Invalid_Path - The source path is not valid.

    remove_path_map_entry removes an entry that was added with add_path_map_entry. The id is the value returned from the add function.

    Errors specific to this function:

    • Debugger_Unknown_Id - The provided id is unknown.

    clear_path_map_entries removes all knowledge about all path map entries added with add_path_map_entry.

    path_map_entries lists all path map entries that have been added with add_path_map_entry, that matches the given context id. If the context id is nil, then all path maps will be listed. The format of the entries in the returned list are dictionaries, with an id of type debug_setup_id_t as key:

    • query (string) - The context query the path map is valid for.
    • source (string) - The source to translate from.
    • destination (string) - The destination to translate to.

    path_map_entries_for_ctx is the same as path_map_entries except that it only lists path maps that are valid for the given context id, ctx_id.

    apply_path_map applies any added path map to a file path, filename, for a given context with ID ctx_id. The path with the path map applied will be returned. The path map will only apply if the destination file exists and if the path given in filename does not, otherwise the provided file will be returned. The returned path will always contain forward slashes as path separator, regardless of what the host system uses, or if any path map was applied or not.

    Note: For functions that take query as argument, having this set to nil will work the same way as for "*". A bad context query will result in a Debugger_Incorrect_Context_Query error.
    typedef int64 debug_setup_id_t;
    
    SIM_INTERFACE(debug_setup) {
            attr_value_t (*add_symbol_file)(conf_object_t *NOTNULL obj,
                                            const char *query,
                                            const char *NOTNULL symbol_file,
                                            uint64 address, bool absolute_address);
            attr_value_t (*add_symbol_segment)(conf_object_t *NOTNULL obj,
                                               const char *query,
                                               const char *NOTNULL symbol_file,
                                               unsigned segment, uint64 address,
                                               bool absolute_address);
            attr_value_t (*add_symbol_section)(conf_object_t *NOTNULL obj,
                                               const char *query,
                                               const char *NOTNULL symbol_file,
                                               const char *NOTNULL section,
                                               uint64 address,
                                               bool absolute_address);
            attr_value_t (*remove_symbol_file)(conf_object_t *NOTNULL obj,
                                               debug_setup_id_t id);
            void (*clear_symbol_files)(conf_object_t *NOTNULL obj);
            attr_value_t (*symbol_files)(conf_object_t *NOTNULL obj);
            attr_value_t (*symbol_files_for_ctx)(conf_object_t *NOTNULL obj,
                                                 const char *NOTNULL ctx_id);
            attr_value_t (*list_all_mappings)(conf_object_t *NOTNULL obj,
                                              const char *NOTNULL ctx_id);
            attr_value_t (*add_path_map_entry)(conf_object_t *NOTNULL obj,
                                               const char *query,
                                               const char *NOTNULL source,
                                               const char *NOTNULL dest);
            attr_value_t (*remove_path_map_entry)(conf_object_t *NOTNULL obj,
                                                  debug_setup_id_t id);
            void (*clear_path_map_entries)(conf_object_t *NOTNULL obj);
            attr_value_t (*path_map_entries)(conf_object_t *NOTNULL obj);
            attr_value_t (*path_map_entries_for_ctx)(conf_object_t *NOTNULL obj,
                                                     const char *NOTNULL ctx_id);
            attr_value_t (*apply_path_map)(conf_object_t *NOTNULL obj,
                                           const char *NOTNULL ctx_id,
                                           const char *NOTNULL filename);
    };
    #define DEBUG_SETUP_INTERFACE "debug_setup"
    

    Execution Context
    Global Context for all methods.

    debug_step

    Description

    This interface is used to perform stepping with the debugger, on a specified debug context.

    For all functions that return an attr_value_t, that return value will consists of a list with two elements. The first element is an error code of debugger_error_t type (see debug_query interface documentation for definition). The second element depends on the first. If the first element is Debugger_No_Error, meaning that the function went well, then the second element will contain the expected return value that is specified per function below. If the first element is another error code, then the second element will be a string describing the error that occurred.

    instruction_into and instruction_over runs one step forward for the specified context. instruction_into will enter subroutine calls while instruction_over will step over subroutine calls.

    into and over will run one source line forward for the specified context. into will enter function calls while over will skip over functions.

    out will run until the currently active function returns.

    All function take a context ID, ctx_id, as argument. This context ID is passed as an argument to callbacks for functions in the debug_notification interface. The context, that is passed to functions in this interface, has to have state (see context_has_state in the debug_query interface) otherwise a Debugger_Context_Does_Not_Have_State error will be returned.

    Calling functions in this interface can only be done when simulation is stopped, otherwise a Debugger_Already_Running error will be returned.

    For all functions in this interface, if another stop reason occurs before a function finishes the simulation will stop at that point instead.

    Stepping for a context that is not active will run until that context becomes active and then take the step.

    SIM_INTERFACE(debug_step) {
            attr_value_t (*instruction_into)(conf_object_t *NOTNULL obj,
                                             const char *NOTNULL ctx_id);
            attr_value_t (*into)(conf_object_t *NOTNULL obj,
                                 const char *NOTNULL ctx_id);
            attr_value_t (*instruction_over)(conf_object_t *NOTNULL obj,
                                             const char *NOTNULL ctx_id);
            attr_value_t (*over)(conf_object_t *NOTNULL obj,
                                 const char *NOTNULL ctx_id);
            attr_value_t (*out)(conf_object_t *NOTNULL obj,
                                const char *NOTNULL ctx_id);
            attr_value_t (*reverse_instruction_into)(conf_object_t *NOTNULL obj,
                                                     const char *NOTNULL ctx_id);
            attr_value_t (*reverse_into)(conf_object_t *NOTNULL obj,
                                         const char *NOTNULL ctx_id);
            attr_value_t (*reverse_instruction_over)(conf_object_t *NOTNULL obj,
                                                     const char *NOTNULL ctx_id);
            attr_value_t (*reverse_over)(conf_object_t *NOTNULL obj,
                                         const char *NOTNULL ctx_id);
            attr_value_t (*reverse_out)(conf_object_t *NOTNULL obj,
                                        const char *NOTNULL ctx_id);
    };
    #define DEBUG_STEP_INTERFACE "debug_step"
    

    Execution Context
    Global Context for all methods.

    debug_symbol

    Description

    This interface contains functions for retrieving various symbol information for a debug context, ctx_id. There are also a few functions for updating symbol information.

    Prior to using functions in this interface, symbol file(s) containing symbol information should have been added using the debug_setup interface, for a context-query that matches the context ID provided to the function here. Symbol files can also be added in other ways such as from a tracker or from Eclipse.

    Some functions, that do read values or stack, can also be used directly with symbol files opened with the debug_symbol_file interface.

    All functions in this interface take a context ID ctx_id as argument. This is the ID passed as an argument to debug_notification callbacks or returned from some debug_query interface functions.

    For all functions that return an attr_value_t, that return value will consists of a list with two elements. The first element is an error code of debugger_error_t type (see debug_query interface documentation for definition). The second element depends on the first. If the first element is Debugger_No_Error, meaning that the function went well, then the second element will contain the expected return value that is specified per function below. If the first element is another error code, then the second element will be a string describing the error that occurred.

    All addresses used in this interface are virtual addresses.

    For functions that take frame as argument, providing frame = -1 means no frame. This can be used when finding symbols for functions or global variables. When using other frame than -1 the context has to be active, otherwise no frame will exists and a Debugger_Context_Is_Not_Active error will be returned. If the specified frame cannot be found, then error code Debugger_Frame_Outside_Of_Known_Stack will be returned.

    Functions that handle stack can only be used with an active context, otherwise error code Debugger_Context_Is_Not_Active or Debugger_Context_Does_Not_Have_State will be returned depending on if the context has state or not.

    address_source will provide callbacks, cb, with source information for the range specified by address and size. The range must not wrap around the 64-bit limit. Source information will be provided as code areas, which is the source information for a range of continuous addresses matching the same file and line. User data can be passed to the callback using the data argument and will be passed as the first argument in the callback. Each code area matching the range will get a callback with information about the code area in the code_area argument, which is a dictionary with the following elements:

    • filename (string) - File name of the source file where the specified address is found.
    • start-line, end-line (int64) - Starting and ending lines in the source file for the address. end-line is inclusive so if the address just matches one source line start-line and end-line will be the same.
    • start-column, end-column (int64) - Starting and ending columns on the line for address. If column information is not available in debug information the value will be 0. end-column is inclusive so the column is included for address.
    • start-address, end-address (uint64) - Starting and ending addresses that correspond to the returned line and column information. end-address is inclusive so this matches the last byte of the last instruction of this code area. If the code area is empty then, then end-address will not be present. This can happen when asking for a line prior to the first executable line.

    Errors specific to this function:

    • Debugger_Source_Not_Found - There are no matching code areas.
    • Debugger_Incorrect_Size - Incorrect size provided. The size cannot be zero and it cannot make the end address exceed 64 bits.
    • Debugger_Lookup_Failure Address lookup failure. Can occur if the address is not in the debug information or the lookup failed for some other reason. The error message explains more what went wrong.

    source_address will provide callbacks, with source information for the line specified by filename, line and column. The column argument will only be useful for binaries with column information in the debug information.

    One call to this function will provide as many callbacks as there are code areas matching that source information. The code_area provided to the callback is a dictionary with the same format as for the callback from address_source.

    Errors specific to this function:

    • Debugger_File_Not_Found - There is no matching source file, filename, in the debug information.
    • Debugger_Source_Not_Found - The line or column is not found in the debug information.
    • Debug_Lookup_Failure - Some problem with the lookup other than that file, line or column was not found. Error described in error message.

    For binaries without column information, a line is executable if the start-line in the callback matches the asked line.

    For binaries with column information one can say that the line is executable if any code area can be found with start-line matching the asked line. When asking for a line and column and the start-line matches a previous line, but the end-line matches the asked line, then one should ask for the column just after end-column to see if the start-line of that code area matches the asked line and if it does then the asked line is considered executable.

    stack_depth returns the current stack depth.

    Errors specific to this function:

    • Debugger_Failed_To_Get_Stack_Frame - Failed to get stack frames.

    stack_frames returns a list of dictionaries with information about each frame. The executing frame is at position zero in the list. The elements of the stack frame dictionary are:

    • address (uint64) - For the executing frame this is the address of the program counter, for all other frames this is the address that the function will return to.
    • source-file (string) - The source file for the frame. Can be nil if no matching file is found.
    • source-line (uint64) - The source line in the file for the frame. Will be nil if source-file is nil.
    • function-name (string) - The function that is executing in the frame. Can be nil if no function is found.

    Errors specific to this function:

    • Debugger_Failed_To_Get_Stack_Frame - If there are problems getting stack depth or getting frame info.
    • Debugger_Failed_To_Read - If a register cannot be read for some frame.
    • Debugger_Failed_To_Get_PC - If the program counter definition cannot be found for the context.

    local_variables returns a list of names for local variables in the specified frame.

    local_arguments returns a list of names of arguments to the function in the specified frame.

    Both local_variables and local_arguments can return an empty list if no local variables or arguments are found. If something goes wrong while looking up variables or arguments they will return a Debugger_Lookup_Failure with more information in the error string.

    expression_value returns the value of an expression, expr, in the specified frame. See note about address_scope further down. The returned value will be of integer type if the expression is of integer type, including if it is an address. Floating-point types will be returned as such. If the expression is a structure, union, class or an array a list containing the elements of that type will be returned.

    Errors specific to this function:

    • Debugger_Failed_To_Evaluate_Expression - The expression could not be evaluated, more information in the error message.

    expression_type returns the type of an expression, expr, in the specified frame. See note about address_scope further down. For most types the return value will be a string containing the type, for example 'int', 'double', 'char' or 'my_own_type_t.

    For pointers the return value will be a list with '*' as the first argument followed by the type of the pointer, for example ['*', 'void'] or ['*', ['*', 'char']].

    For qualifiers ('const', 'volatile' or 'restrict') these will be added as an element to the list, such as ['const', 'char'] or ['volatile', ['*', 'int']].

    Functions are returned with a '()' string as the first element of a list, followed by the return type, followed by a list of arguments to the function. Example: ['*', ['()', 'int', ['int', ['*', ['*', 'char']]]]] for a function of type int (*)(int, char **).

    A struct or union will return a string 'struct', followed by the struct name, if available, then followed by a list of lists containing the struct member type and name ['struct', 'my_struct', [['int', 'i'], ['float', 'f']]] as example. If the struct has been assigned a type with typedef then the output will be 'typedef' followed by the name of the assigned type, then the list of members. An example: ['typedef', 'mytype_t', [['int', 'age'], [['*', 'char'], 'name']]]. For unions the string 'struct' will be replace with the string 'union'.

    A bit field will return a list containing a string 'bitfield' followed by the basic type of the bit field, followed by the size of the bit field. An example: ['bitfield', 'int', 5] for a variable declared as int var:5.

    For array types expression_type will return a list, ['[]', array size, array type], where the array type is of the same format as other types for this function. An example: ['[]', 10, 'char'] for a variable declared as char x[10];

    Enumerations will be displayed as a list: ['enum', enum name, members]. The enum name is the declared name for the enumeration, if no such name exists this list field will be left out. The members field will contain a list of [name, value] lists for all the members of the enumeration. An example: ['enum, 'my_enum', [['My_Val_0', 0], [My_Val_1, 1]]].

    Note: There are some limitations for symbols from PE files that can depend on the version of dbghelp.dll.
    • Type defined types might get shown as the base type instead of the 'typedef' type.
    • Variables with a const qualifier might be shown without that qualifier.
    • Members of anonymous structures within a base structure are shown as being part of the base structure.
    Errors specific to this function:
    • Debugger_Failed_To_Evaluate_Expression - Could not evaluate the expression, more information in the error message.

    type_info returns information about what base type a type that has been added with typedef has. See note about address_scope further down. The returned value will be a list on the same format as for expression_value.

    Errors specific to this function:

    • Debugger_Incorrect_Type - If the type asked for is not a valid type.
    • Debugger_Lookup_Failure - Finding the symbol failed or the type of symbol cannot be retrieved. More information in the error string.

    type_to_string converts the return value from expression_type or type_info to a readable string and returns that.

    Errors specific to this function:

    • Debugger_Incorrect_Type - The format of type is incorrect.

    symbol_address takes a frame and a symbol as arguments and returns a list of addresses that matches that symbol name. If a single symbol address is wanted near a provided instruction pointer then the expression_value function can be used with the expression set as &<symbol>.

    Errors specific to this function:

    • Debugger_Lookup_Failure - The address for the symbol cannot be found. This can be because the symbol was not found or if evaluation failed. More information will be found in the error message.

    address_string returns the string at the specified address. The maxlen is used to specify the maximum length of a string to read from memory. If the string at address exceeds the given length the truncated string will be returned, and a terminating null character will be added if needed. A maxlen value of zero means no maximum string length.

    Errors specific to this function:

    • Debugger_Failed_To_Read - Failed to read memory at address.

    lvalue_write writes a value to a symbol in the specified frame. The value can be of integer types or floating-point type if the type of the lvalue is of floating-point type. The returned value when the write goes well is nil.

    Errors specific to this function:

    • Debugger_Incorrect_Type - The type of value is incorrect.
    • Debugger_Failed_To_Evaluate_Expression - The provided symbol could not be found or evaluated as an expression.
    • Debugger_Failed_To_Write - Failed to write to symbol.

    address_write writes an attr_value_t of data type, value, to the specified address. Returned value is nil when the write goes well.

    Errors specific to this function:

    • Debugger_Incorrect_Type - The type of value is incorrect.
    • Debugger_Failed_To_Write - The memory at address cannot be written to.

    address_read reads size number of bytes from the specified address. The read data is returned as an attr_value_t of data type.

    Errors specific to this function:

    • Debugger_Failed_To_Read - The address cannot be read.

    struct_members returns a list of all members of a struct, struct_name. See note about address_scope further down. Each element of the returned list will be on the format [name, offset, size]. The size and offset elements are usually integers representing the offset into the struct and the size of the variable. If the struct member is a bit field then size will be a list on the format [base size, bits], where base size is the number of bytes for the declared base type and bits is the number of bits the declared for the bit field. For bit fields offset will be a list on the format [byte offset, bit offset], where byte offset is the offset of in bytes into the structure and bit offset is the offset in bits from the byte offset to where the bit field starts. If some member, size or offset cannot be retrieved then that element will be set as nil. This can for example occur if a struct member is an anonymous struct or union.

    Errors specific to this function:

    • Debugger_Incorrect_Type - The provided symbol, struct_name, is not a structure.
    • Debugger_Lookup_Failure - Failed to find the symbol or its type.

    struct_field returns a list of [offset, size] for a field of a given structure, struct_name. The offset and size are usually integers, but if the field is a bit field then the returned size and offset will be on the same format as for struct_members. See note about address_scope below.

    This function can return the same error codes, for the same reasons, as the struct_members function.

    The address_scope argument that is provided for several functions can be used to specify where to find the symbol if there are several matches for the provided symbol name or expression. This argument is used to provide an address that tells the function in which scope to search for the symbol. This is only taken in account when no frame (-1) is given as frame. This address can be an address that belongs to a loaded symbol file to prioritize finding symbols from that symbol file.

    list_functions and list_global_variables lists all function or global variable symbols that are known for the given context. The symbols shown are the ones that have been added with the add_symbol_file function of the debug_setup interface. The returned format is a list of dictionaries with the dictionary elements on the format:

    • symbol (string) - The name of the symbol.
    • address (uint64) - The address in memory of the symbol.
    • size (uint64) - The size of the symbol in memory.

    list_source_files lists all source files provided by the debug information of the symbol files for the given context.

    SIM_INTERFACE(debug_symbol) {
            attr_value_t (*address_source)(conf_object_t *NOTNULL obj,
                                           const char *NOTNULL ctx_id,
                                           uint64 address, uint64 size,
                                           void (*cb)(cbdata_call_t data,
                                                      attr_value_t code_area),
                                           cbdata_register_t data);
            attr_value_t (*source_address)(conf_object_t *NOTNULL obj,
                                           const char *NOTNULL ctx_id,
                                           const char *NOTNULL filename,
                                           uint32 line, uint32 column,
                                           void (*cb)(cbdata_call_t data,
                                                      attr_value_t code_area),
                                           cbdata_register_t data);
            attr_value_t (*address_symbol)(conf_object_t *NOTNULL obj,
                                           const char *NOTNULL ctx_id,
                                           uint64 address);
            attr_value_t (*stack_depth)(conf_object_t *NOTNULL obj,
                                        const char *NOTNULL ctx_id);
            attr_value_t (*stack_frames)(conf_object_t *NOTNULL obj,
                                         const char *NOTNULL ctx_id, int min,
                                         int max);
            attr_value_t (*local_variables)(conf_object_t *NOTNULL obj,
                                            const char *NOTNULL ctx_id, int frame);
            attr_value_t (*local_arguments)(conf_object_t *NOTNULL obj,
                                            const char *NOTNULL ctx_id, int frame);
            attr_value_t (*expression_value)(conf_object_t *NOTNULL obj,
                                             const char *NOTNULL ctx_id,
                                             int32 frame, uint64 address_scope,
                                             const char *NOTNULL expr);
            attr_value_t (*expression_type)(conf_object_t *NOTNULL obj,
                                            const char *NOTNULL ctx_id,
                                            int32 frame, uint64 address_scope,
                                            const char *NOTNULL expr);
            attr_value_t (*type_info)(conf_object_t *NOTNULL obj,
                                      const char *NOTNULL ctx_id,
                                      uint64 address_scope,
                                      const char *NOTNULL type);
            attr_value_t (*type_to_string)(conf_object_t *NOTNULL obj,
                                           attr_value_t type);
            attr_value_t (*symbol_address)(conf_object_t *NOTNULL obj,
                                           const char *NOTNULL ctx_id, int32 frame,
                                           const char *NOTNULL symbol);
            attr_value_t (*address_string)(conf_object_t *NOTNULL obj,
                                           const char *NOTNULL ctx_id,
                                           uint64 address, int maxlen);
            attr_value_t (*lvalue_write)(conf_object_t *NOTNULL obj,
                                         const char *NOTNULL ctx_id, int32 frame,
                                         const char *NOTNULL symbol,
                                         attr_value_t value);
            attr_value_t (*address_write)(conf_object_t *NOTNULL obj,
                                          const char *NOTNULL ctx_id,
                                          uint64 address, attr_value_t value);
            attr_value_t (*address_read)(conf_object_t *NOTNULL obj,
                                         const char *NOTNULL ctx_id, uint64 address,
                                         unsigned size);
            attr_value_t (*struct_members)(conf_object_t *NOTNULL obj,
                                           const char *NOTNULL ctx_id,
                                           uint64 address_scope,
                                           const char *NOTNULL struct_name);
            attr_value_t (*struct_field)(conf_object_t *NOTNULL obj,
                                         const char *NOTNULL ctx_id,
                                         uint64 address_scope,
                                         const char *NOTNULL struct_name,
                                         const char *NOTNULL field);
            attr_value_t (*list_functions)(conf_object_t *NOTNULL obj,
                                           const char *NOTNULL ctx_id);
            attr_value_t (*list_global_variables)(conf_object_t *NOTNULL obj,
                                                  const char *NOTNULL ctx_id);
            attr_value_t (*list_source_files)(conf_object_t *NOTNULL obj,
                                              const char *NOTNULL ctx_id);
    };
    #define DEBUG_SYMBOL_INTERFACE "debug_symbol"
    

    Execution Context
    Global Context for all methods.

    debug_symbol_file

    Description

    This interface has functions for operating directly on symbol files, instead of using contexts related to processes or processors. Files opened with this interface can be used together with functions in the debug_symbol interface that do not require any stack or location information. There are also functions for getting information about the symbol file, such as listing sections or segments.

    For all functions that return an attr_value_t, that return value will consists of a list with two elements. The first element is an error code of debugger_error_t type (see debug_query interface documentation for definition). The second element depends on the first. If the first element is Debugger_No_Error, meaning that the function went well, then the second element will contain the expected return value that is specified per function below. If the first element is another error code, then the second element will be a string describing the error that occurred.

    All function but open_symbol_file has to act on a context id, ctx_id, that has been returned by open_symbol_file, otherwise a Debugger_Not_Supported_For_Context error will be returned.

    open_symbol_file opens a symbol file, specified by the filename argument, as a context so that this can be used with many of the symbol lookup functions in the debug_symbol interface. The address is the offset for which to load the symbol file if absolute_address is false. If absolute_address is true, address will instead be the absolute address to load the symbol file on. The returned value will be a context id that can be used as argument where a ctx_id is required. Functions that take a stack frame can only be accessed with no stack (value -1) when used with a symbol file context. Files that read or write memory cannot be used.

    Errors specific to this function:

    • Debugger_Unrecognized_File_Format - The file format of the file is not ELF or PE.
    • Debugger_Unsupported_For_File_Format - If the symbol file is of PE format then the address cannot be 0 as the internal handling does not support that.

    open_symbol_section opens a symbol file in the same way as open_symbol_file, but only adds symbols from the specified section. Other arguments and return value are as for open_symbol_file. The symbol section is closed using close_symbol_file. This method can only handle ELF binaries. In addition to errors reported by open_symbol_file this function can report Debugger_Section_Not_Found if the section cannot be found.

    close_symbol_file closes a symbol file that was opened with open_symbol_file. The ctx_id should be the context id returned from that function. The returned value will just be nil when this goes well.

    symbol_file_info returns a list containing a string describing the file format and a dictionary with information about the file. The ctx_id argument should be the context id returned from the open_symbol_file. The returned information depends on which file format the file has. For ELF files the string is "ELF" and the returned entries are:

    • big-endian (uint64) - Set to 1 if the binary is built for big endian, otherwise 0.
    • elf-machine-id (uint64) - The ELF machine identifier number (e_machine) in the ELF header. This is usually prefixed with EM_ in headers. For example EM_386 = 3 and EM_X86_64 = 62.

    For PE files the string is "PE" and the returned entries are:

    • image-size (uint64) - The size of the PE image in memory.
    • image-base (uint64) - The recommended address for the image to be loaded at.

    Both PE and ELF files will include the following entries:

    • entry-address (uint64) - The program counter for where the execution in the file should begin.
    • file-size (uint64) - The file size in bytes.
    • machine (string) - The type of machine the binary is built for, for example "X86-64", "X86" or "ARM".
    • address-width (uint64) - The address width the file was built for, should be 32 or 64, but 0 specifies unknown.

    sections_info provides information about the sections in the symbol file. The ctx_id must be an id for a file opened with open_symbol_file or open_symbol_section in this interface. The returned result is a list with two elements, the first a string specifying the format of the file, "ELF" or "PE", and the second a list of dictionaries where each dictionary contains information about the section. If an id from open_symbol_section is used then only the opened section will be included in the list. The following keys exist in the dictionary:

    • name (string) - The name of the section. This key could potentially be left out if the sections does not have a name.
    • address (uint64) - The address in memory.
    • offset (uint64) - The offset in the file.
    • size (uint64) - The section size in the file image.
    • executable (boolean) - A boolean telling if the section is executable or not.
    • index (uint64) - Only available for ELF files. The section index.
    • flags (uint64) - Only available for ELF files. The value of sh_flags in the ELF section header.
    • characteristics (uint64) - Only available for PE files. The value of Characteristics in the PE section IMAGE_SECTION_HEADER structure.

    segments_info provides information about the segments in the symbol file, this is only supported for ELF. The ctx_id must be an id for a file opened with open_symbol_file in this interface. The returned result is a list where each entry represent a segment. Each entry is in turn a dictionary with the following keys:

    • address (uint64) - Virtual address in memory.
    • size (uint64) - The segment size in memory, specified in bytes.
    • offset (uint64) - Offset into the segment location on file.
    • flags (uint64) - Flags, depending on segment type, corresponds to p_flags in the ELF program header table.
    • type (uint64) - The type of the segment, corresponds to p_type in the ELF program header table.
    • physical-address (uint64) - Physical address in memory, if applicable.
    • file-size (uint64) - The size of the segment in file.
    • sections ([string,...]) - A list of sections included in the segment, presented by the section name.

    SIM_INTERFACE(debug_symbol_file) {
            attr_value_t (*open_symbol_file)(conf_object_t *NOTNULL obj,
                                             const char *NOTNULL filename,
                                             uint64 address, bool absolute_address);
            attr_value_t (*close_symbol_file)(conf_object_t *NOTNULL obj,
                                             const char *NOTNULL ctx_id);
            attr_value_t (*symbol_file_info)(conf_object_t *NOTNULL obj,
                                             const char *NOTNULL ctx_id);
            attr_value_t (*sections_info)(conf_object_t *NOTNULL obj,
                                          const char *NOTNULL ctx_id);
            attr_value_t (*segments_info)(conf_object_t *NOTNULL obj,
                                          const char *NOTNULL ctx_id);
            attr_value_t (*open_symbol_section)(conf_object_t *NOTNULL obj,
                                                const char *NOTNULL filename,
                                                const char *NOTNULL section,
                                                uint64 address,
                                                bool absolute_address);
    };
    #define DEBUG_SYMBOL_FILE_INTERFACE "debug_symbol_file"
    

    Execution Context
    Global Context for all methods.

    disassemble

    Description
    The disassemble interface can be used to disassemble code from a buffer in memory. It is typically used to disassemble code for the host architecture independent of the target architecture implemented in a particular version of Simics.

    SIM_INTERFACE(disassemble) {
            /* Set up new block to disassemble */
            void (*init)(conf_object_t *obj, uint8 *buff,
                         int buff_len, uint64 address);
            /* Disassemble the next instruction */
            disasm_instr_t (*next)(conf_object_t *obj);
    };
    
    #define DISASSEMBLE_INTERFACE "disassemble"
    

    init() is used to initialize a new disassemble session. You should provide a buffer in buff, the buffer length in bytes in buff_len and the base address for this chunk in address. The address parameter is used to calculate program counter relative offsets (for branches and other program counter relative constructs).

    typedef struct {
            int start;          /* Where the instructions starts in the buffer */
            int length;         /* Length of instruction, or -1 if incomplete */
            char *string;       /* Disassembly string (allocated) */
    } disasm_instr_t;

    next() returns a structure with the next disassembled instruction. Repeated use of next() will disassemble additional instructions.

    Execution Context
    Cell Context for all methods.

    follower_agent

    Description
    This interface is intended to be implemented by a follower agent to accept data from the follower.

    The accept method delivers a deterministic message from the follower to the agent.

    The accept_async method delivers an asynchronous (non-deterministic) message from the follower to the agent.

    SIM_INTERFACE(follower_agent) {
            void (*accept)(conf_object_t *obj, bytes_t msg);
            void (*accept_async)(conf_object_t *obj, bytes_t msg);
    };
    #define FOLLOWER_AGENT_INTERFACE "follower_agent"
    

    Execution Context
    Cell Context for all methods.

    gfx_break

    Description
    The gfx_break interface facilitates management of graphical breakpoints. It is implemented by the graphics console.

    A graphical breakpoint is defined by an image patch and a location on the screen, stored in a file using a bespoke format. Such a file can be created using the store method.

    A breakpoint can then be activated using the add method. The console will check if the breakpoint matches the screen data every interval seconds in virtual time, using the clock that is associated to the console. Graphical breakpoints are therefore deterministic.

    Note that the coordinates of the image patch is stored in the graphical breakpoint, and the breakpoint will only match on those coordinates.

    The store method stores the specified rectangle on the screen in the given file. It returns false if the rectangle is invalid or on I/O error.

    The add method activates a previously stored graphical breakpoint, and returns a breakpoint ID, which is also passed to cb when the breakpoint matches. The parameter name is the breakpoint name that will appear in log messages. If name is NULL then the file name is used. If oneshot is true, the breakpoint will be removed automatically after the first match. The interval parameter specifies how often the breakpoint is tested, in seconds of simulated time. If cb is not NULL, then this function will be called on breakpoint match, otherwise a match stops the simulation. If the breakpoint file cannot be loaded, the method returns -1.

    The remove method deactivates a previously activated breakpoint.

    The match method determines if a stored graphical breakpoint matches the current screen. It returns -1 if the breakpoint could not be loaded, 1 on match or 0 otherwise.

    The info method returns the header of a stored graphical breakpoint, including the image patch coordinates. If the given file cannot be read or has invalid data, then a header containing all 0's is returned.

    The export_png method converts the image data in a graphical breakpoint file to PNG format.

    The add_bytes method behaves as add but reads the breakpoint data from memory instead of a file.

    SIM_INTERFACE(gfx_break) {
            bool (*store)(conf_object_t *NOTNULL obj,
                          const char *file,
                          int minx, int miny, int maxx, int maxy);
            int64 (*add)(conf_object_t *NOTNULL obj,
                         const char *file, const char *name,
                         bool oneshot, double interval,
                         gfx_break_cb_t cb, lang_void *arg);
            bool (*remove)(conf_object_t *NOTNULL obj, int64 break_id);
            int (*match)(conf_object_t *NOTNULL obj, const char *file);
            gbp_header_t (*info)(conf_object_t *NOTNULL obj, const char *file);
            bool (*export_png)(conf_object_t *NOTNULL obj, const char *file,
                               const char *png_file);
            int64 (*add_bytes)(conf_object_t *NOTNULL obj,
                               bytes_t data, const char *name,
                               bool oneshot, double interval,
                               gfx_break_cb_t cb, lang_void *arg);
    };
    #define GFX_BREAK_INTERFACE "gfx_break"
    

    Execution Context
    Global Context for all methods

    host_serial

    Description
    The host_serial interface is used to control the text console host serial connection.

    The setup method will set up a host serial connection on a pty (Linux) or COM port (Windows). On Linux, name can be NULL in which case a new pty is opened.

    The name method returns the name of any opened pty or COM port, or NULL.

    The shutdown closes any opened pty or COM port.

    SIM_INTERFACE(host_serial) {
            bool (*setup)(conf_object_t *NOTNULL obj, const char *name);
            const char *(*name)(conf_object_t *NOTNULL obj);
            void (*shutdown)(conf_object_t *NOTNULL obj);
    };
    #define HOST_SERIAL_INTERFACE "host_serial"
    

    Execution Context
    Global Context for all methods

    instrumentation_connection

    Description
    This interface is intended to be implemented by instrumentation connections using the instrumentation framework. This interface is used to request that instrumentation should be temporarily disabled and then re-enabled. That is, the connection should not collect any data when it is being disabled. How this is achieved is up to the tool, it could tell the provider to stop sending information, or simply throw away anything it sends. This interface can be used with high frequency while simulation is running, so it should be implemented with performance in mind.
    SIM_INTERFACE(instrumentation_connection) {
            void (*enable)(conf_object_t *obj);
            void (*disable)(conf_object_t *obj);
    };
    
    #define INSTRUMENTATION_CONNECTION_INTERFACE "instrumentation_connection"
    

    Execution Context
    Cell Context for all methods.

    instrumentation_filter_master

    Description
    This interface is intended to be implemented by instrumentation filters. Instrumentation filters should enable the associated slaves, which themselves are associated with instrumentation connections.

    The set_source_id method supplies the filter with an unique source number for the filter. This function should only be called once, the filter needs to store this number so it can be used when calling the instrumentation_filter_slave interface methods.

    The add_slave method informs the filter that it should enable or disable this slave too. The slave object should implement the instrumentation_filter_slave interface which should be used. The provider_obj parameter is the provider object that is located behind the slave and its connection. Depending on how the filter works, it may or may not make use of this parameter. For example, the process-filter might detect that the filtered process is now running on a particular processor, then it can enable this particular connection only, given that it can match the provider_obj with the processor currently running the tracked process.

    The remove_slave method removes a slave from the filter, so it should not call it anymore.

    The short_filter_config method should return a short textual description on how the filter is currently set up. This information is used in various print commands.

    SIM_INTERFACE(instrumentation_filter_master) {
            void (*set_source_id)(conf_object_t *obj, unsigned source_id);
            bool (*add_slave)(conf_object_t *obj, conf_object_t *slave,
                              conf_object_t *provider_obj);
            void (*remove_slave)(conf_object_t *obj, conf_object_t *slave,
                                 conf_object_t *provider_obj);
            char *(*short_filter_config)(conf_object_t *obj);
    };
    #define INSTRUMENTATION_FILTER_MASTER_INTERFACE "instrumentation_filter_master"
    

    Execution Context
    Global Context for all methods.

    instrumentation_filter_slave

    Description
    This interface is implemented by the instrumentation_filter_aggregator class objects, here referred to as "aggregator". The interface should be called by instrumentation filters to enable or disable a connection. The aggregator object is located between the filters and the connection, keeping the connections unaware of multiple filters that might be disabling them.

    The disable method tells the aggregator that the unique source_id currently wants to disable the connection. As long as there is one source_id that is disabled, the connection is disabled. Only when all sources are enabled the connection is enabled.

    Similarly, the enable enables the connection. That is, the filter is now in a state when it thinks the connection should be enabled.

    SIM_INTERFACE(instrumentation_filter_slave) {
            void (*disable)(conf_object_t *obj, unsigned source_id);
            void (*enable)(conf_object_t *obj, unsigned source_id);
    };
    #define INSTRUMENTATION_FILTER_SLAVE_INTERFACE "instrumentation_filter_slave"
    

    Execution Context
    Cell Context for all methods.

    instrumentation_filter_status

    Description
    This interface is implemented by the instrumentation_filter_aggregator class objects. This interface should only be used by Simics instrumentation framework itself. The get_disabled_sources method returns an attr_value_t list of integers representing the source_ids that currently causing the connection to be disabled.

    SIM_INTERFACE(instrumentation_filter_status) {
            attr_value_t (*get_disabled_sources)(conf_object_t *obj);
    };
    #define INSTRUMENTATION_FILTER_STATUS_INTERFACE "instrumentation_filter_status"
    

    Execution Context
    Global Context for all methods.

    instrumentation_tool

    Description
    This interface is intended to be implemented by instrumentation tools using the instrumentation framework. The instrumentation framework handles setting up, controlling and removing the connection between providers and tools, but the actual communication is handled by instrumentation specific interfaces.

    When a connection with a provider is being established, the connect method is called. The provider argument specifies the provider which should be connected. The args are tool specific arguments that can be used allowing the connection to be configured a certain way. The tool should create a new dedicated connection object, which register itself with the provider using the dedicated interface. The connection object created is returned by the connect function. If, for any reason, the tool cannot successfully connect to the provider, NULL should be returned to indicate failure.

    If a connection should be removed, the disconnect method is called. The conn_obj argument is the connection object returned earlier in connect. It is up to the tool to delete the created object which should unregister itself from the provider.

    SIM_INTERFACE(instrumentation_tool) {
            conf_object_t *(*connect)(
                    conf_object_t *NOTNULL obj,
                    conf_object_t *NOTNULL provider,
                    attr_value_t args);
            void  (*disconnect)(
                    conf_object_t *NOTNULL obj,
                    conf_object_t *NOTNULL conn_obj);
    };
    #define INSTRUMENTATION_TOOL_INTERFACE "instrumentation_tool"
    

    Execution Context
    Global Context for all methods.

    leader_message

    Description
    This interface is implemented by the leader, and is used from a follower agent to send data to the follower.

    The send method sends a deterministic message to the follower to be delivered at time. If several messages will be delivered at same time, an increasing skey determines the sort order.

    The send_async method sends a non-deterministic (asynchronous) message to the follower to be delivered as soon as possible.

    SIM_INTERFACE(leader_message) {
            void (*send)(conf_object_t *obj,
                         follower_time_t time, uint64 skey, bytes_t msg);
            void (*send_async)(conf_object_t *obj, bytes_t msg);
    };
    #define LEADER_MESSAGE_INTERFACE "leader_message"
    

    Execution Context
    Cell Context for all methods.

    osa_component

    Description

    get_admin returns the osa_admin object associated with the component.

    get_root_node returns a maybe_node_id_t with the valid field set to true and id set to the current root node if a root node exists. If no root node exists the valid field will be set to false.

    It is only valid to call get_admin or get_root_node on instantiated components.

    notify_tracker registers a callback function cb that will be called when a tracker is added to the component using the insert-tracker command. Returns a cancel id that can be used to cancel the callback using cancel_notify. It is a one time notification and will automatically be canceled once it has been called. The data argument will be passed on to the callback.

    cancel_notify cancels a callback made by notify_tracker.

    has_tracker returns true if the component has a tracker inserted, otherwise false.

    get_processors returns a list of processors to use for the software domain.

    SIM_INTERFACE(osa_component) {
            conf_object_t *(*get_admin)(conf_object_t *NOTNULL obj);
            maybe_node_id_t (*get_root_node)(conf_object_t *NOTNULL obj);
            cancel_id_t (*notify_tracker)(conf_object_t *NOTNULL obj,
                                          void (*cb)(cbdata_call_t data),
                                          cbdata_register_t data);
            void (*cancel_notify)(conf_object_t *NOTNULL obj,
                                  cancel_id_t cancel_id);
            bool (*has_tracker)(conf_object_t *NOTNULL obj);
            attr_value_t (*get_processors)(conf_object_t *NOTNULL obj);
    };
    
    #define OSA_COMPONENT_INTERFACE "osa_component"
    

    Execution Context
    Cell Context for all methods.

    osa_control

    Description

    request is used to register clients that are interested in using the tracker framework and activates the tracker framework if it is not already activated. The initiator argument is a string which should describe the client that requests to activate the OS Awareness framework. The return value is an ID that should be passed to the release function to signal that the client no longer needs the OS Awareness framework.

    Upon a failure while initializing the OS Awareness framework, OSA_Request_Error_ID will be returned.

    release removes a client that has previously requested to use the tracker framework. The id argument is the returned value from request. The tracker framework will be disabled when there are no more registered users.

    SIM_INTERFACE(osa_control) {
            request_id_t (*request)(conf_object_t *NOTNULL obj,
                                    const char *initiator);
            void (*release)(conf_object_t *NOTNULL obj, request_id_t id);
    };
    
    #define OSA_CONTROL_INTERFACE "osa_control"
    

    Execution Context
    Global Context for all methods.

    osa_control_v2

    Description

    request is used to register clients that are interested in using the tracker framework and activates the tracker framework if it is not already activated. The initiator argument is a string which should describe the client that requests to activate the OS Awareness framework. The return format is [bi|s]. If the first element is True, then the second element will contain the request_id, which can be passed to the release function to signal that the client no longer needs the OS Awareness framework. If the first element is False, the second element will be an error message.

    release removes a client that has previously requested to use the tracker framework. The id argument is the returned value from request. The tracker framework will be disabled when there are no more registered users.

    clear_state can be called to clear the state in the tracker framework that could exist after loading a checkpoint. This can only be called while the tracker is disabled. The return value will be on the format [bi|s]. If the first element is True then clearing state succeeded and the second element can be ignored. If the first element is False then clearing state failed and the second element will contain a string with a message of what went wrong.

    SIM_INTERFACE(osa_control_v2) {
            attr_value_t (*request)(conf_object_t *NOTNULL obj,
                                    const char *initiator);
            void (*release)(conf_object_t *NOTNULL obj, request_id_t id);
            attr_value_t (*clear_state)(conf_object_t *NOTNULL obj);
    };
    
    #define OSA_CONTROL_V2_INTERFACE "osa_control_v2"
    

    Execution Context
    Global Context for all methods.

    osa_machine_notification

    Description

    notify_mode_change registers a callback function that will be called when processor cpu changes processor mode. The callback function will be called with the processor that changed mode cpu, the mode previous to the change old_mode and the mode after the change new_mode.

    notify_exception registers a callback function that will be called when processor cpu takes an exception with exception number exc_num. The callback function cb will be called with the processor cpu causing the exception and exception number exc_num of that exception.

    notify_control_reg registers a callback function that will be called when a control register, with register number reg_num, in processor cpu is updated. The callback function cb will be called with the processor cpu, register number reg_num and the written register value (see Core_Control_Register_Write documentation for more details) as arguments. The register number for a certain register can be retrieved with the get_register_number function.

    notify_control_reg_read registers a callback function that will be called when a control register, with register number reg_num, in processor cpu is read. The callback function cb will be called with the processor cpu and register number reg_num as arguments. The register number for a certain register can be retrieved with the get_register_number function.

    notify_exec_breakpoint, notify_read_breakpoint and notify_write_breakpoint plant breakpoints of length len for processor cpu on address. The breakpoint is of type execution, read, write respectively. The virt argument specifies if address is a virtual or physical address. The callback function cb is called when the breakpoint is hit. The arguments of the callback functions are the processor that the breakpoint hit on cpu and the address (virtual or physical depending on what the breakpoint was registered as) that was hit. Callbacks functions for notify_read_breakpoint and notify_write_breakpoint also gets the access size len of the read or write. The callback function for notify_write_breakpoint additionally has the previous value old_val at the address written and the new value new_val that is being written passed as arguments. Reading the actual memory from the callback will result in reading the new value that has been written as the callback is called after the write is done. On x86 virtual breakpoints use linear addresses (as opposed to logical addresses).

    For all functions, the tracker argument should be the tracker calling this interface. This makes it possible for a hypervisor tracker to handle guests differently.

    All methods that register a notification callback take data as an argument which will be passed on to callback function. These methods return a cancel ID to be used with the cancel method to cancel the callback. A returned value of 0 means that an error occurred and no callback was registered, in which case the caller is responsible for freeing the callback data.

    cancel cancels the callback function with ID cancel_id and will free the callback data associated with the notification. This ID will have been returned from the function that registered the callback.

    typedef enum {
            OSA_Read_One_Byte = 1,
            OSA_Read_Two_Byte = 2,
            OSA_Read_Four_Byte = 4,
            OSA_Read_Eight_Byte = 8,
    } osa_read_len_t;
    
    SIM_INTERFACE(osa_machine_notification) {
            cancel_id_t (*notify_mode_change)(
                    conf_object_t *NOTNULL obj, conf_object_t *NOTNULL tracker,
                    conf_object_t *NOTNULL cpu,
                    void (*cb)(cbdata_call_t data, conf_object_t *cpu,
                               processor_mode_t old_mode,
                               processor_mode_t new_mode),
                    cbdata_register_t data);
            cancel_id_t (*notify_exception)(
                    conf_object_t *NOTNULL obj, conf_object_t *NOTNULL tracker,
                    conf_object_t *NOTNULL cpu, int exc_num,
                    void (*cb)(cbdata_call_t data, conf_object_t *cpu, int exc_num),
                    cbdata_register_t data);
            cancel_id_t (*notify_control_reg)(
                    conf_object_t *NOTNULL obj, conf_object_t *NOTNULL tracker,
                    conf_object_t *NOTNULL cpu, int reg_num,
                    void (*cb)(cbdata_call_t data, conf_object_t *cpu, int reg_num,
                               uint64 value),
                    cbdata_register_t data);
            cancel_id_t (*notify_exec_breakpoint)(
                    conf_object_t *NOTNULL obj, conf_object_t *NOTNULL tracker,
                    conf_object_t *NOTNULL cpu, uint64 address, uint64 len,
                    bool virt,
                    void (*cb)(cbdata_call_t data, conf_object_t *cpu,
                               uint64 address),
                    cbdata_register_t data);
            cancel_id_t (*notify_read_breakpoint)(
                    conf_object_t *NOTNULL obj, conf_object_t *NOTNULL tracker,
                    conf_object_t *NOTNULL cpu, uint64 address, unsigned len,
                    bool virt,
                    void (*cb)(cbdata_call_t data, conf_object_t *NOTNULL cpu,
                               uint64 address, unsigned len),
                    cbdata_register_t data);
            cancel_id_t (*notify_write_breakpoint)(
                    conf_object_t *NOTNULL obj, conf_object_t *NOTNULL tracker,
                    conf_object_t *NOTNULL cpu, uint64 address, unsigned len,
                    bool virt,
                    void (*cb)(cbdata_call_t data, conf_object_t *NOTNULL cpu,
                               uint64 address, unsigned len, uint64 old_val,
                               uint64 new_val),
                    cbdata_register_t data);
            void (*cancel)(conf_object_t *NOTNULL obj,
                           conf_object_t *NOTNULL tracker, cancel_id_t cancel_id);
            cancel_id_t (*notify_control_reg_read)(
                    conf_object_t *NOTNULL obj, conf_object_t *NOTNULL tracker,
                    conf_object_t *NOTNULL cpu, int reg_num,
                    void (*cb)(cbdata_call_t data, conf_object_t *cpu, int reg_num),
                    cbdata_register_t data);
    };
    
    #define OSA_MACHINE_NOTIFICATION_INTERFACE "osa_machine_notification"
    

    Execution Context
    Cell Context for all methods.

    osa_machine_query

    Description

    read_register reads the register with number reg (number can be retrieved with get_register_number) from processor cpu and returns the value of that register.

    get_register_number returns the register number of the register with name reg from processor cpu or -1 upon error.

    read_phys_memory reads len bytes of memory from physical address addr of processor cpu. The returned value is an uint64 with the value if the read succeeded, otherwise nil. The len argument should use one of the lengths declared in the osa_read_len_t enum.

    read_phys_bytes reads len bytes of memory from physical address addr. The length to read can be up to 1024 bytes. The returned value is of data type containing the bytes read upon success or nil otherwise.

    virtual_to_physical translates the virtual address vaddr of processor cpu to a physical address as translation would be for a data read. The returned value is the physical address as an uint64 upon success, otherwise nil. For x86 this uses linear to physical translation (as opposed to the logical to physical variant).

    cpu_mode returns the current processor mode of cpu.

    get_all_processors returns all available processors. For example, when detecting parameters, a tracker should use its known processors if the system is enabled, otherwise it can get them via get_all_processors. For hypervisor configurations, the tracker framework must be enabled in order to detect parameters for a guest.

    get_exception_number returns the exception number of the exception with name name from processor cpu. Returns -1 if no exception with the given name exists.

    For all functions, the tracker argument should be the tracker calling this interface. This makes it possible for a hypervisor tracker to handle guests differently.

    SIM_INTERFACE(osa_machine_query) {
            uint64 (*read_register)(
                    conf_object_t *NOTNULL obj, conf_object_t *NOTNULL tracker,
                    conf_object_t *NOTNULL cpu, int reg);
            int (*get_register_number)(
                    conf_object_t *NOTNULL obj, conf_object_t *NOTNULL tracker,
                    conf_object_t *NOTNULL cpu, const char *reg);
            attr_value_t (*read_phys_memory)(
                    conf_object_t *NOTNULL obj, conf_object_t *NOTNULL tracker,
                    conf_object_t *NOTNULL cpu, physical_address_t addr,
                    osa_read_len_t len);
            attr_value_t (*read_phys_bytes)(
                    conf_object_t *NOTNULL obj, conf_object_t *NOTNULL tracker,
                    conf_object_t *NOTNULL cpu, physical_address_t paddr,
                    unsigned len);
            attr_value_t (*virtual_to_physical)(
                    conf_object_t *NOTNULL obj, conf_object_t *NOTNULL tracker,
                    conf_object_t *NOTNULL cpu, uint64 vaddr);
            processor_mode_t (*cpu_mode)(conf_object_t *NOTNULL obj,
                                         conf_object_t *NOTNULL tracker,
                                         conf_object_t *NOTNULL cpu);
            attr_value_t (*get_all_processors)(conf_object_t *NOTNULL obj,
                                               conf_object_t *NOTNULL tracker);
            int (*get_exception_number)(
                    conf_object_t *NOTNULL obj, conf_object_t *NOTNULL tracker,
                    conf_object_t *NOTNULL cpu, const char *name);
    };
    
    #define OSA_MACHINE_QUERY_INTERFACE "osa_machine_query"
    

    Execution Context
    Cell Context for all methods.

    osa_mapper_admin

    Description

    tracker_updated is called from the node tree when entities are added, modified or removed. To receive such an update, the mapper must subscribe to tracker updates by calling subscribe_tracker in the osa_tracker_state_notification interface. The initiator argument is the processor object that initiated the transaction. This can be nil if the transaction was not initiated by a processor (for example, enable or disable tracker). The format of changeset is a dictionary with tracker objects that were updated as keys and other dictionaries as values.

    The dictionary that is set as the value for each tracker contains the following keywords: "added", "modified", "removed" and "events".

    The value for "added" is a dictionary which contains the added entity IDs as keys and the attributes of those entities as values.

    An example of "added" where two entities were added:

    "added": {0x1000: {"name": "task1", "pid": 1},
              0x2000: {"name": "task2", "pid": 2}}

    The value for "modified" is a dictionary which contains the modified entity IDs as keys and a dictionary with the attribute name as key and a list of old and new values for that attribute as its value. Only the attributes that have changed will be included. If an attribute is removed that will be set so that it changed to nil. If an attribute was added that will be set so that it changed from nil.

    An example of "modified", entity 0x1000 had "name" changed and entity 0x2000 had "tgid" added and "pid" removed:

    "modified": {0x1000: {"name": ["task1", "new_name"]},
                 0x2000: {"tgid": [None, 4], "pid": [2, None]}}

    The value for "removed" is a list which contains the entity IDs for the entities that have been removed.

    The value for "events" is a dictionary indexed by the entity id. Each value is a list of lists, each inner list is an event. The first element of the inner list is the event name and the second element is user defined data associated with the event.

    An example of "events" where entity 0x1000 has two associated events and entity 0x2000 has one associated event:

    "events": {0x1000: [["event1", {}], ["event2", {}]],
               0x2000: [["syscall", {'sys_num': 0x10, 'sys_name': "open"}]]}

    An example of how the complete changeset might look like:

    {<the tracker 'tracker1_obj'>: {"added": {0x1000: {"name": "task"}},
                                    "modified": {0x2000: {"dummy": [1, 2]}},
                                    "removed": [0x3000, 0x3100]},}

    SIM_INTERFACE(osa_mapper_admin) {
            void (*tracker_updated)(conf_object_t *NOTNULL obj,
                                    conf_object_t *initiator,
                                    attr_value_t changeset);
    };
    #define OSA_MAPPER_ADMIN_INTERFACE "osa_mapper_admin"
    

    Execution Context
    Cell Context for all methods.

    osa_mapper_control

    Description

    The disable function is called when the mapper should be disabled. The mapper should then clean-up the node tree and stop listening to changes from trackers.

    The enable function is called when the mapper should be enabled. The mapper should then create the node tree and start listening to changes from trackers.

    The clear_state is called to clear the mapper's state. The mapper should clear all its internal data when this is called, so that enable can be called again. This call can only occur while the mapper is disabled.

    SIM_INTERFACE(osa_mapper_control) {
            void (*disable)(conf_object_t *NOTNULL obj);
            bool (*enable)(conf_object_t *NOTNULL obj);
            void (*clear_state)(conf_object_t *NOTNULL obj);
    };
    #define OSA_MAPPER_CONTROL_INTERFACE "osa_mapper_control"
    

    Execution Context
    Cell Context for all methods.

    osa_mapper_query

    Description

    The optional get_process_list function provides data for the 'list' command. It should return a two-element list, where the first element is a list of column headers, and the second element is a list of (row, subtable) two-element lists. All rows should have the same number of elements as the header list (this is the number of columns in the resulting table).

    The elements of the header list and row lists---that is, the individual elements in the table---should be of type string or integer. Integers will be formatted by the system, so in order to force a specific base, such as decimal or hexadecimal, convert them to strings.

    The subtables paired with each row should either be None (meaning no subtable) or a nested list such as that returned by get_process_list(), in which case that list will be printed, slightly indented, below the row. This makes it possible for the list command to handle stacked trackers. An example of how a complete return value from get_process_list function can look like:

    [["Process", "Pid"], [[["ls", 1], None], [["cat", 2], None]]]

    If the function is not implemented, the function pointer should be set to NIL.

    The optional get_mapper function returns the mapper that is responsible for the given node. A mapper that has guest mappers should forward the request to the guests as well if the node belongs to one of the guests. If the function is not implemented by the mapper, it is assumed that the node is owned by the mapper.

    If this function is not implemented, the function pointer should be set to NIL. Stacked trackers, which support guest trackers must implement this function.

    SIM_INTERFACE(osa_mapper_query) {
            attr_value_t (*get_process_list)(conf_object_t *NOTNULL obj);
            conf_object_t *(*get_mapper)(conf_object_t *NOTNULL obj,
                                         node_id_t node_id);
    };
    #define OSA_MAPPER_QUERY_INTERFACE "osa_mapper_query"
    

    Execution Context
    Global Context for all methods.

    osa_micro_checkpoint

    Description

    This interface is used to get information when micro checkpointing (for reverse execution) starts and stops. The functions will only be called when the tracker framework is enabled.

    started is called when a saved state is about to be loaded, before any attributes have been set.

    finished is called once all attributes have been set for all objects. At this point callbacks calls to the machine interfaces can be done.

    It is allowed to implement only one of these functions if notification are only wanted before or after setting attributes of a micro checkpoint.

    This interface is optional and can be implemented by either a tracker or a mapper.

    SIM_INTERFACE(osa_micro_checkpoint) {
            void (*started)(conf_object_t *NOTNULL obj);
            void (*finished)(conf_object_t *NOTNULL obj);
    };
    
    #define OSA_MICRO_CHECKPOINT_INTERFACE "osa_micro_checkpoint"
    

    Execution Context
    Global Context for all methods.

    osa_node_path

    Description

    matching_nodes function returns a list of all nodes rooted at root_id that matches the given node_path_pattern. The node_path_pattern should be either an integer representing a node id or a string, see Analyzer User's Guide for more details.

    Upon success, the return value is a list where the first entry is true and the second entry is a list containing all the matching node ids.

    Upon failure, the return value is a list where the first entry is false and the second entry is a string describing the error.

    node_path function translates a node id into a fully qualified node path string. See Analyzer User's Guide for more details.

    Upon success, the return value is a list where the first entry is true and the second entry is the node path string.

    Upon failure, the return value is a list where the first entry is false and the second entry is a string describing the error.

    SIM_INTERFACE(osa_node_path) {
            attr_value_t (*matching_nodes)(conf_object_t *NOTNULL obj,
                                           node_id_t root_id,
                                           attr_value_t node_path_pattern);
            attr_value_t (*node_path)(conf_object_t *NOTNULL obj,
                                      node_id_t node_id);
    };
    
    #define OSA_NODE_PATH_INTERFACE "osa_node_path"
    

    Execution Context
    Global Context for all methods.

    osa_node_tree_admin

    Description

    begin is called from the mapper to start a transaction when adding, updating or removing nodes in the node tree. The initiator argument specifies the initiator processor, this can be nil if the transaction is not initiated by a processor. The initiator will be passed as cpu argument to callback functions in the osa_node_tree_notification interface. The function returns an ID to be used when calling end.

    end is called from the mapper to end a transaction. This should be called at the end of a transaction when all modifications to the node tree are complete. The transaction_id argument should be the value returned from the begin method that started the transaction. Stacked calls to begin and end are possible, then the transaction will be ended when the first begin is ended. The begin methods must be ended in the opposite order that they were called. For stacked calls to begin only the initiator of the first call to begin will be used.

    create creates a new node tree and associates mapper with it. The properties of the root node for the new tree are set through props which is a dictionary. The returned value is the node ID of the created root node.

    add adds a new node rooted at parent_id. The new node gets the properties specified by props which is a dictionary. The returned value is the node ID of the newly added node.

    update updates the properties of a node in the node tree. node_id specifies the node to be updated and props is a dictionary of the properties that should be updated.

    set_property updates one property of a node in the node tree. This is similar to update but there is no need to build up a dictionary. node_id specifies the node to be updated, key the key of the property to be updated and value the value to update the property with.

    reset resets a node, node_id, to the properties specified by props. All the children for the node will be removed and all properties except the ones in props will be removed. If the reset node was previously active it will be deactivated.

    All methods have the limitation that data and dictionary types are not supported as the value of a property. The keys of the props dictionary must all be of string type.

    remove removes the node with the ID specified by node_id from the node tree.

    event registers a new event, associated with the given node_id. The event_name argument is the name of the event, this name can also be used by a user to only listen to a specific event type per node tree. The event_data argument is the data associated with the event and it is up to the responsible tracker to document its exact form. An event differes from other properties in the way that they are not persistent.

    activate sets node_id as the active node for processor cpu in the node tree where node_id exists. All the ancestors of node_id will also be set as active. Any previously active node for cpu will be deactivated.

    deactivate deactivates processor cpu in the node tree where node_id exists. The node_id argument should be set to the node that was previously active on cpu in the node tree.

    register_formatter registers a callback function which will be called when the property specified by the key argument should be formatted in a specific way. This is typically called from "get_formatted_properties" in the osa_node_tree_query interface. This is useful for systems where an integer property should be formatted in hexadecimal to make a closer match to the target OS mapper of that property. For example, a node with the following properties:

    {"name": "foo", "tid": 4711}

    could then be formatted as:

    {"name": "foo", "tid": "0x1267"}

    The function itself must return a string, given as an attr_value_t. The mapper must have been registered by calling the create function in the osa_node_tree_admin interface before registering a formatter.

    The register_formatter function returns a cancel id that can be passed to the unregister_formatter function to unregister the formatting function. Registering a new formatter on the same node_id and key as a previous formatter will override the previous formatter with the new one. This is useful when dealing with stacked trackers and a sub-tracker needs to register a formatter for a node that already have a registered formatter.

    unregister_formatter unregisters a previously registered formatter function using the register_formatter function.

    SIM_INTERFACE(osa_node_tree_admin) {
            transaction_id_t (*begin)(conf_object_t *NOTNULL obj,
                                      conf_object_t *initiator);
            void (*end)(conf_object_t *NOTNULL obj,
                        transaction_id_t transaction_id);
            node_id_t (*create)(conf_object_t *NOTNULL obj,
                                conf_object_t *NOTNULL mapper, attr_value_t props);
            node_id_t (*add)(conf_object_t *NOTNULL obj,
                             node_id_t parent_id, attr_value_t props);
            void (*update)(conf_object_t *NOTNULL obj, node_id_t node_id,
                           attr_value_t props);
            void (*remove)(conf_object_t *NOTNULL obj, node_id_t node_id);
            void (*event)(conf_object_t *NOTNULL obj, node_id_t node_id,
                          const char *event_name, attr_value_t event_data);
            void (*activate)(conf_object_t *NOTNULL obj, node_id_t node_id,
                             conf_object_t *NOTNULL cpu);
            void (*deactivate)(conf_object_t *NOTNULL obj, node_id_t node_id,
                               conf_object_t *NOTNULL cpu);
            cancel_id_t (*register_formatter)(
                    conf_object_t *NOTNULL obj, node_id_t node_id,
                    const char *NOTNULL key,
                    bool recursive, attr_value_t (*formatter)(attr_value_t val));
            void (*unregister_formatter)(
                    conf_object_t *NOTNULL obj, cancel_id_t node_id);
            void (*reset)(conf_object_t *NOTNULL obj,
                          node_id_t node_id, attr_value_t props);
            void (*set_property)(conf_object_t *NOTNULL obj, node_id_t node_id,
                                 const char *key, attr_value_t value);
    };
    
    #define OSA_NODE_TREE_ADMIN_INTERFACE "osa_node_tree_admin"
    

    Execution Context
    Cell Context for all methods.

    osa_node_tree_notification

    Description

    notify_create and notify_destroy register callbacks to be called when the node is created and destroyed, respectively. The node_id argument specifies for which node the callback should be installed. By specifying both the node_id and the recursive arguments it is possible to get notifications for all nodes in a subtree. It is safe to read the node with get_node in the osa_node_tree_query interface from within the callback function.

    Calling notify_create without recursive being set is only useful when used together with reverse execution, as only then can the node ID of a node that is to be created later be known.

    notify_property_change registers a callback that is triggered when the given property key changes on the node (or any property, if key is nil). The callback function will receive the name of the property that was changed in the key argument and the old and new values of that property in the old_val and new_val arguments.

    notify_event register a callback cb to be called when an event occurs for the given node_id. If the event_name argument is nil the callback will be associated with all events, by providing a specific event name instead the callback will only trigger for that particular event type. The event_data argument passed to the callback contains tracker specific data associated with the event. See specific tracker documentation for details.

    If recursive, the callback will be triggered for the given node's descendants as well as the node itself.

    Most callbacks have cpu and obj arguments. The cpu argument specifies the processor that caused the event, but may be nil if the event was not caused by a processor. The obj will contain the object that implements the interface. The node_id argument passed to the callback specifies the node ID for the node that has been created, destroyed, modified or has triggered an event.

    notify_cpu_move_from and notify_cpu_move_to register callbacks that are triggered when a processor moves from one node path to another—but only if either path lies in the subtree rooted at the given node node_id.

    Since a single update to the node tree can result in several different callbacks being triggered, reading nodes with get_node from a callback function may yield a result containing updates whose callbacks have not yet been run. For example, if two nodes change their name attributes simultaneously, the final state of both nodes may be visible to both property change callbacks. With notify_callbacks_done, you can register a callback that will run when all other callbacks pertaining to a particular change in the node tree are finished.

    notify_enable register a callback cb to be called when the tracker framework is enabled.

    notify_disable register a callback cb to be called when the tracker framework is disabled.

    The functions that install callbacks return an integer ID. This ID can be passed to cancel_notify in order to uninstall the callback. In case of error in a notification function the returned cancel ID from that function will be 0.

    New callbacks registered inside a registered callback will not be called until the next transaction they trigger for. Canceled callbacks are canceled immediately.

    SIM_INTERFACE(osa_node_tree_notification)
    {
            cancel_id_t (*notify_create)(conf_object_t *NOTNULL obj,
                                         node_id_t node_id, bool recursive,
                                         void (*cb)(cbdata_call_t data,
                                                    conf_object_t *obj,
                                                    conf_object_t *cpu,
                                                    node_id_t node_id),
                                         cbdata_register_t data);
            cancel_id_t (*notify_destroy)(conf_object_t *NOTNULL obj,
                                          node_id_t node_id, bool recursive,
                                          void (*cb)(cbdata_call_t data,
                                                     conf_object_t *obj,
                                                     conf_object_t *cpu,
                                                     node_id_t node_id),
                                          cbdata_register_t data);
            cancel_id_t (*notify_property_change)(
                    conf_object_t *NOTNULL obj, node_id_t node_id,
                    const char *key, bool recursive,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj,
                               conf_object_t *cpu, node_id_t node_id,
                               const char *key, attr_value_t old_val,
                               attr_value_t new_val),
                    cbdata_register_t data);
            cancel_id_t (*notify_cpu_move_from)(
                    conf_object_t *NOTNULL obj, node_id_t node_id,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj,
                               conf_object_t *cpu, attr_value_t node_path),
                    cbdata_register_t data);
            cancel_id_t (*notify_cpu_move_to)(
                    conf_object_t *NOTNULL obj, node_id_t node_id,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj,
                               conf_object_t *cpu, attr_value_t node_path),
                    cbdata_register_t data);
            cancel_id_t (*notify_event)(
                    conf_object_t *NOTNULL obj, node_id_t node_id,
                    const char *event_name, bool recursive,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj,
                               conf_object_t *cpu, node_id_t node_id,
                               const char *event_name, attr_value_t event_data),
                    cbdata_register_t data);
            cancel_id_t (*notify_enable)(
                    conf_object_t *NOTNULL obj,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj),
                    cbdata_register_t data);
            cancel_id_t (*notify_disable)(
                    conf_object_t *NOTNULL obj,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj),
                    cbdata_register_t data);
            void (*cancel_notify)(conf_object_t *NOTNULL obj,
                                  cancel_id_t cancel_id);
            cancel_id_t (*notify_callbacks_done)(
                    conf_object_t *NOTNULL obj, uint64 node_id,
                    void (*cb)(cbdata_call_t data, conf_object_t *obj),
                    cbdata_register_t data);
    };
    
    #define OSA_NODE_TREE_NOTIFICATION_INTERFACE "osa_node_tree_notification"
    

    Execution Context
    Cell Context for all methods.

    osa_node_tree_query

    Description

    get_root_nodes returns a list of node IDs for the root nodes.

    get_node returns a dictionary for a given node, containing all the node's properties; or nil if no such node exists.

    get_current_nodes returns the current node path of the given processor. That is, a list of node IDs of all nodes that are currently running on the processor, the first node being the root node, and every subsequent node a child of the node before it. If the tracker is not tracking the given processor, the return value is nil.

    get_current_processors returns a list of processors that are currently active on the given node, or one of it's descendants. The list will be empty if there is no active processor. Nil will be returned if the given node does not exist.

    get_all_processors returns a list of all processors that are available for the OS Awareness framework.

    get_parent returns the node ID of the specified node's parent; or nil if the node has no parent.

    get_children returns a list of node IDs for the children of the specified node, this will be an empty list if the node does not have any children. The method will return nil if the node does not exist.

    The get_formatted_properties function returns a dictionary containing all properties for a node, formatted as strings or integers. It will return nil upon a failure. For example, a tracker could format the value of property pid to show the value in hexadecimal form.

    {'name': "Our OS", 'pid': "0x1234"}

    SIM_INTERFACE(osa_node_tree_query) {
            attr_value_t (*get_root_nodes)(conf_object_t *NOTNULL obj);
            attr_value_t (*get_node)(conf_object_t *NOTNULL obj, node_id_t node_id);
            attr_value_t (*get_current_nodes)(conf_object_t *NOTNULL obj,
                                              node_id_t base_id,
                                              conf_object_t *cpu);
            attr_value_t (*get_current_processors)(conf_object_t *NOTNULL obj,
                                                   node_id_t node_id);
            attr_value_t (*get_all_processors)(conf_object_t *NOTNULL obj);
            conf_object_t *(*get_mapper)(conf_object_t *NOTNULL obj,
                                         node_id_t node_id);
            attr_value_t (*get_parent)(conf_object_t *NOTNULL obj,
                                       node_id_t node_id);
            attr_value_t (*get_children)(conf_object_t *NOTNULL obj,
                                         node_id_t node_id);
            attr_value_t (*get_formatted_properties)(conf_object_t *NOTNULL obj,
                                                     uint64 node_id);
    };
    
    #define OSA_NODE_TREE_QUERY_INTERFACE "osa_node_tree_query"
    

    Execution Context
    Cell Context for all methods.

    osa_parameters

    Description

    Interface implemented by tracker components that support getting and setting their parameters.

    If either method fails it returns a (false, error-string) pair. If get_parameters succeed it returns (true, parameters). If set_parameters succeed it returns (true, nil).

    The parameters you pass to set_parameters and thare are returned by get_parameters should be a pair (tracker-kind, parameters-value), where tracker-kind is a string identifying the kind of tracker and parameters-value is the parameters for that kind of tracker. The parameters for an unconfigured tracker are (tracker-kind, nil).

    The include_children argument of get_parameters is only used for stacked tracker and specifies if parameters for guest trackers should be included or filtered out.

    The is_kind_supported method returns true if the tracker-kind in a parameter set is of the right kind for the tracker. This is no guarantee that setting these parameters will succeed. If the method returns false the parameters will not work.

    SIM_INTERFACE(osa_parameters) {
            attr_value_t (*get_parameters)(conf_object_t *NOTNULL obj,
                                           bool include_children);
            attr_value_t (*set_parameters)(conf_object_t *NOTNULL obj,
                                           attr_value_t parameters);
            bool (*is_kind_supported)(conf_object_t *NOTNULL obj,
                                      const char *kind);
    };
    
    #define OSA_PARAMETERS_INTERFACE "osa_parameters"
    

    Execution Context
    Global Context for all methods.

    osa_tracker_component

    Description

    get_tracker returns the tracker object associated with the component or nil if no such tracker exists.

    get_mapper returns the mapper object associated with the component or nil if no such mapper exists.

    SIM_INTERFACE(osa_tracker_component) {
            conf_object_t *(*get_tracker)(conf_object_t *NOTNULL obj);
            conf_object_t *(*get_mapper)(conf_object_t *NOTNULL obj);
    };
    
    #define OSA_TRACKER_COMPONENT_INTERFACE "osa_tracker_component"
    

    Execution Context
    Cell Context for all methods.

    osa_tracker_control

    Description

    enable and disable are called from the OS Awareness framework, for all trackers that have been set in the top_trackers attribute for the node_tree object, when OS Awareness is enabled or disabled, respectively.

    clear_state is called to clear the trackers state. The tracker should clear all its internal data and its data in the node tree when this is called. This call can only occur while the tracker is disabled.

    add_processor and remove_processor are called to add or remove a processor cpu to/from the tracker which the tracker should start/stop tracking. If the tracker is registered as a top level tracker these methods will be called by the OS Awareness framework for all processors available to the framework when it is enabled or disabled. If the tracker is a guest under a hypervisor the hypervisor should call these methods when a processor becomes available or unavailable to the guest. These functions should return true if a processor was successfully added or removed, otherwise the function should return false.

    SIM_INTERFACE(osa_tracker_control) {
            void (*disable)(conf_object_t *NOTNULL obj);
            bool (*enable)(conf_object_t *NOTNULL obj);
            void (*clear_state)(conf_object_t *NOTNULL obj);
            bool (*add_processor)(conf_object_t *NOTNULL obj,
                                  conf_object_t *NOTNULL cpu);
            bool (*remove_processor)(conf_object_t *NOTNULL obj,
                                     conf_object_t *NOTNULL cpu);
    };
    
    #define OSA_TRACKER_CONTROL_INTERFACE "osa_tracker_control"
    

    Execution Context
    Global Context for enable, disable and clear_state. Cell Context for add_processor and remove_processor.

    osa_tracker_state_admin

    Description

    begin is called from the tracker to start a transaction when modifying an entity in the node tree. The tracker argument specifies the tracker object for which the updates are done for. The initiator argument specifies the processor that initiated the transaction, this can be nil if it was not a processor that caused the transaction to begin, when enabling the tracker as an example. The initiator is passed as an argument to the tracker_updated function in the osa_mapper_admin interface. The function returns an ID that is used when calling end.

    end is called from the tracker to end a transaction. This should be called at the end of a transaction when all entity modifications are done. The transaction_id argument should be the value returned from begin that started the transaction. Stacked calls to begin and end are possible, then the transaction will be ended when the first begin is ended. The begin methods must be ended in the opposite order that they were called. For stacked calls to begin only the initiator of the first call to begin will be used.

    add adds a new entity with ID entity_id to the node tree. The new entity's attributes are set in the attributes argument, which is a dictionary.

    remove removes the entity with ID entity_id for the current tracker from the node tree.

    remove_all removes all entities for the current tracker from the node tree.

    set_attribute adds or updates an attribute key for the entity with ID entity_id. The new value is specified in val.

    update updates or adds one or more attributes for the entity with ID entity_id. The attributes argument is a dictionary with the attributes to be updated.

    In order to remove a property, set the property value to nil when calling update or set_attribute.

    event registers a new event, associated with the given entity_id argument. The event_name argument is the name of the event. The event_data argument is the data associated with the event and it is up to the responsible tracker to document its exact form. An event differes from other properties in the way that they are not persistent.

    Entity attributes have the limitation that the value of the attribute can not be of type data or dictionary. The keys of entity attributes must be of string type.

    SIM_INTERFACE(osa_tracker_state_admin) {
            transaction_id_t (*begin)(conf_object_t *NOTNULL obj,
                                      conf_object_t *NOTNULL tracker,
                                      conf_object_t *initiator);
            void (*end)(conf_object_t *NOTNULL obj, transaction_id_t txid);
            void (*add)(conf_object_t *NOTNULL obj, entity_id_t entity_id,
                        attr_value_t attributes);
            void (*remove)(conf_object_t *NOTNULL obj, entity_id_t entity_id);
            void (*remove_all)(conf_object_t *NOTNULL obj);
            void (*set_attribute)(conf_object_t *NOTNULL obj, entity_id_t entity_id,
                                  const char *key, attr_value_t val);
            void (*update)(conf_object_t *NOTNULL obj, entity_id_t entity_id,
                           attr_value_t attributes);
            void (*event)(conf_object_t *NOTNULL obj, entity_id_t entity_id,
                          const char *event_name, attr_value_t event_data);
    };
    
    #define OSA_TRACKER_STATE_ADMIN_INTERFACE "osa_tracker_state_admin"
    

    Execution Context
    Cell Context for all methods.

    osa_tracker_state_notification

    Description

    subscribe_tracker is called to make mapper receive updates for entities of tracker. When such an update occurs, the function tracker_updated in interface osa_mapper_admin will be called.

    unsubscribe_tracker cancels a subscription of entity updates to mapper> that was started by subscribe_tracker for the specified tracker. A tracker without guest trackers does not need to call this, as it will be automatically done when the framework is disabled. However, a tracker with guest trackers, must call this function when a guest is removed.

    SIM_INTERFACE(osa_tracker_state_notification) {
            void (*subscribe_tracker)(conf_object_t *NOTNULL obj,
                                      conf_object_t *NOTNULL mapper,
                                      conf_object_t *NOTNULL tracker);
            void (*unsubscribe_tracker)(conf_object_t *NOTNULL obj,
                                        conf_object_t *NOTNULL mapper,
                                        conf_object_t *NOTNULL tracker);
    };
    
    #define OSA_TRACKER_STATE_NOTIFICATION_INTERFACE \
            "osa_tracker_state_notification"
    

    Execution Context
    Cell Context for all methods.

    osa_tracker_state_query

    Description

    get_entities returns a dictionary of entities that are stored for tracker. The dictionary maps entity id to properties, which in turn is a dictionary, mapping property name to property value. Returns nil if tracker is not known.

    get_entity returns the properties for the given entity id and tracker, as a dictionary that maps property name to property value. Returns nil if the entity can not be found.

    SIM_INTERFACE(osa_tracker_state_query) {
            attr_value_t (*_deprecated)(conf_object_t *NOTNULL obj);
            attr_value_t (*get_entities)(conf_object_t *NOTNULL obj,
                                         conf_object_t *NOTNULL tracker);
            attr_value_t (*get_entity)(conf_object_t *NOTNULL obj,
                                       conf_object_t *NOTNULL tracker,
                                       entity_id_t id);
    };
    
    #define OSA_TRACKER_STATE_QUERY_INTERFACE "osa_tracker_state_query"
    

    Execution Context
    Cell Context for all methods.

    preference

    Description

    The preference interface is implemented by objects that store preferences on the behalf of other modules. Preferences are settings that are persistent between sessions. Typically there is a single object implementing the preference interface.

    SIM_INTERFACE(preference) {
            attr_value_t
            (*get_preference_for_module_key)(conf_object_t *NOTNULL prefs,
                                             const char *NOTNULL module,
                                             const char *NOTNULL key);
    
            void (*set_preference_for_module_key)(conf_object_t *NOTNULL prefs,
                                                  attr_value_t value,
                                                  const char *NOTNULL module,
                                                  const char *NOTNULL key);
    };
    
    #define PREFERENCE_INTERFACE "preference"
    

    get_preference_for_module_key is called to retrieve a preference for a specified module and key. If no value has been set an invalid attribute is returned.

    set_preference_for_module_key is called to store a preference for a specified module and key. Any attribute type is allowed for the value, including nested types. However, the value may no contain any invalid attributes.

    Execution Context
    Global Context for all methods.

    probe

    Description
    This interface defines a probe in the system. A probe is a mechanism that lets a model expose values of interest to a user. By using this interface, generic tools can extract these values and present them in different forms, like tables and graphs. A probe should always have a meaningful value that can be read at any time during the simulation.

    Probes should be used for user observable values and are not intended for model to model communication.

    The properties() method is typically called once for each tool or use-case to get information about the probe. It should return a key/value attr_value_t list, i.e., list of lists of two values, with probe specific properties. The first value of the inner list represents the property key as an Sim_Val_Integer using the enum probe_key_t type, and the second value is a key specific data item described below. The probe_key_t is defined as:

    typedef enum {
            Probe_Key_Kind = 0,                  /* Identifier of the probe */
            Probe_Key_Name = 0,                  /* Old name of Probe_Key_Kind,
                                                    kept for compatibility */
    
            Probe_Key_Type = 1,                  /* string, any of: {
                                                    "int", "float, "fraction",
                                                    "histogram", "int128", "string"
                                                    } */
            Probe_Key_Categories = 2,            /* list of strings */
            Probe_Key_Cause_Slowdown = 3,        /* bool */
    
            Probe_Key_Owner_Object = 4,          /* object: owner object */
    
            Probe_Key_Display_Name = 5,          /* string: short narrow name */
            Probe_Key_Description = 6,           /* string */
    
            Probe_Key_Float_Percent = 7,
            Probe_Key_Float_Decimals = 8,
            Probe_Key_Metric_Prefix = 9,
            Probe_Key_Unit = 10,
            Probe_Key_Binary_Prefix = 11,
            Probe_Key_Time_Format = 12,
            Probe_Key_Width = 13,
    
            Probe_Key_Value_Notifier = 14,
    
            Probe_Key_Aggregates = 17,   /* Defines new probes which aggregate
                                            over this probe:
                                            [list of [list properties]]
                                            Invalid for Type: "string"
                                         */
            Probe_Key_Aggregate_Scope = 18, /* Aggregate over all probes in the
                                               cells or all probes in the system.
                                               String and of ["global", "cell"] */
            Probe_Key_Aggregate_Function = 19, /* How the aggregation should be
                                                  done:
                                                  "sum",
                                                  "weighted-arith-mean",
                                                  - only fractions
                                               */
            Probe_Key_Definition = 20,         /* string: how the probe is
                                                  calculated */
    } probe_key_t;

    The value() method should return the data for the probe as an attr_value_t in accordance of how the property type has been defined. This method is called each time a tool/user wants to read the latest probe value.

    The property keys are describes here as follows:

    Probe_Key_Kind
    Sets the kind of the probe, as a string (Sim_Val_String). The probe-kinds are what uniquely define the probes in the system.

    There can be many probes associated with the same kind, but they should all represent the same type of measured data.

    The kind should be named so it is humanly possible to understand what you get back when you read it.

    To avoid conflicts, the kind should be an hierarchical name where each level is separated with a dot. Probes falling into the same domain should have logical names according to this. Currently, there are some defined names on the first level that can be used to build the hierarchy. Among them are: cpu. that collects probes related to a CPU, dev. that collects probes for devices, cell. that collects probes related to cells, host. collects probes related to the host environment, and sim. that collects probes having to do with the overall simulation environment.

    Some examples, include: cpu.cycles, cpu.exec_mode.jit_steps, dev.io_access_count, cell.steps, host.swap.used, and sim.slowdown.

    Several objects implementing this interface can use the same probe-kind, for similar probe values. The probe's unique identifier is a string containing the object name then a colon, followed by the probe-kind, e.g., "board.mb.cpu0.cpu[0][0]:cpu.cycles".

    Probe_Key_Display_Name
    Sets a display name for the probe as a string (Sim_Val_String). This is a more human friendly name than the probe name, and a tool can use this name in table headings or graph legends.
    Probe_Key_Type
    Sets the type of the probe as a string (Sim_Val_String). The following types are defined: "int", "float", "string", "fraction", "int128" and "histogram". The attr_value_t value that should be returned by the value method for these types are as follows:

    For the int type, an attr_value_t of type Sim_Val_Integer should be returned.

    For the float type, return a Sim_Val_Floating value.

    The string type is returned by a Sim_Val_String value. The string typically represents some momentarily state. Due to nature of a string, a tool cannot do any calculation on the probe value, only show the current string content.

    The fraction type should use a attr_value_t list of two Sim_Val_Integer or Sim_Val_Floating values. This represent a mathematical fraction value, where the first one is the numerator and and the second value is the denominator value. Note however that a float value can be used for both of them. To get the proper value for this probe the tool/user should divide the numerator with the denominator. Using fraction makes it possible for the tool to calculate a mean value for this probe between any point in time where the probe was read, e.g., say you have a probe that reads the frequency of a simulated processor that varies over time. Then this probe can be defined as a fraction between the cycle count and the elapsed virtual time (cycles/time = frequency). If the tool saves the cycle difference and the time difference between to points in time, it can calculate the mean frequency between those point by dividing the differences.

    For very large numbers the int128 type can be used, the type is represented as a attr_value_t list of two value; the high 64-bit number followed by the low 64-bit number.

    The histogram type is represented by a attr_value_t list of lists of two values. Where the inner list is used as a tuple of a named group as a Sim_Val_String, and its corresponding value as a Sim_Val_Integer or Sim_Val_Floating. A tool can then display an histogram of these groups and/or calculate the difference between two histograms over time and display that.

    .
    Probe_Key_Categories
    The key is a list of string that defines some categories for the probe. This information can be used to search for probes of a specific use case.
    Probe_Key_Cause_Slowdown
    The value for this key is a Sim_Val_Boolean. True means that using the probe can cause a significant slowdown of the simulation. False means it does not cause any particular slowdown.
    Probe_Key_Owner_Object
    The value for this key is a Sim_Val_Object that should be regarded as the owner of the probe instead of the object that implements this interface (which is default). This can be useful if some other objects implements functionality for the main object.
    Probe_Key_Description
    The value for this key is a Sim_Val_String that documents this probe in details.
    Probe_Key_Definition
    "Function" definition string, explaining how the probe is being calculated out from other probes. This is automatically created for probe aggregates and derivatives. Default is an empty string.
    Probe_Key_Float_Decimals
    The value for this key is a Sim_Val_Integer that sets the preferred number of decimals of this is float probe when a value is displayed.
    Probe_Key_Float_Percent
    The value for this key is a Sim_Val_Boolean that sets the preferred representation of a float probe as a percent representation, e.g., a value of 0.176 will be displayed as 17.6% if the number of decimals are one.
    Probe_Key_Metric_Prefix
    The value for this key is a Sim_Val_String describing a unit name. This sets the preferred representation of a float probe to be displayed with a metric prefix for the unit given. Supported metric prefixes are: k, M, G, T, P, E, Z, Y, for values > 1 and m, µ, n, p, f, a, z, y for values < 1. For example if the unit is set to "s" (seconds) and the float value is 0.0000347, then the displayed representation should be "34.7 µs". To omit the unit in the output use the empty string, "", as the unit. If the value is outside the prefix ranges, an scientific E notation will be used.
    Probe_Key_Binary_Prefix
    The value for this key is a Sim_Val_String describing a unit name. This sets the preferred representation of an integer probe to be displayed with a binary prefix for the unit given. Supported prefixes are: ki, Mi, Gi, Ti, Pi, Ei, Zi, and Yi. For example if the unit is set to "B" (representing bytes), and the integer value is 10485760 (10*1024*1024), then the displayed representation should be "10 MiB". .
    Probe_Key_Unit
    The value for this key is a Sim_Val_String that sets the unit for the value. A tool can use this to display the unit for the value.
    Probe_Key_Time_Format
    The value for this key is a Sim_Val_Boolean that sets the preferred representation for a float value to a time format, hh:mm:ss.d, where h is hours, m minutes, s seconds, and d is fractions of a seconds. The raw value returned by the value method is the number of seconds. The Probe_Key_Float_Decimals key/value pair controls the number of digits in the fraction. If the number of seconds represents more than 99 hours, it should continue adding digits for the hours, e.g., 100:44:10.123
    Probe_Key_Width
    The value for this key is a Sim_Val_Integer that sets the preferred width of a probe value in characters. This can be used to determine the best width of columns in a table tool, for instance.
    Probe_Key_Value_Notifier
    The value for this key is a Sim_Val_String that describes a notifier that is triggered when the value changes. This can be used by a tool to track all changes of the value. For performance reasons the value should be changes infrequently.
    Probe_Key_Global_Sum
    Deprecated, use Probe_Key_Aggregates instead.
    Probe_Key_Cell_Sum
    Deprecated, use Probe_Key_Aggregates instead.
    Probe_Key_Aggregates
    Defines lists of new probes which are aggregates of the probe defined. Each list-element defines a new probe, specified as a list of the key-value properties for the aggregate probe. All properties are inherited from the probe being aggregated, except the new name of the aggregate probe which must be defined. Probe keys can be redefined if they appear in the aggregate scope. For example, it is advisable to change the description making it clear what value that is being returned by the aggregate.

    Only in the aggregate scope, the Probe_Key_Aggregate_Scope and Probe_Key_Aggregate_Function key-value pairs are used to further define how the aggregation is done. Note that aggregates depend on the the type of the underlying probe. Some probe types can only be aggregated with certain functions.

    Probe_Key_Aggregate_Scope
    Defines the scope for the aggregate probe. That is, which objects that implements the probe, should be part of the aggregation. Valid values are "cell" or "global". Default is "global", which means that all objects which implements the probe will be part of the aggregate and put in the singleton owner object, such as the 'sim' or 'host' objects.

    Cell-aggregates are put under the available cell objects and will aggregate the probe which belongs to the respective cell object.

    Probe_Key_Aggregate_Function
    Defines how the aggregate should be generated. Valid values are "sum", "min", "max", "arith-mean", "weighted-arith-mean" and "median". Default is "sum".

    For probes of the fraction type, if any denominator contains a zero value (division by zero), the calculated value is undefined and [0, 0] is returned. This applies to all fraction aggregates except weighted-arith-mean, where the zero denominator can be handled.

    sum
    All probe values are summed together. Not supported on "string" probes.
    min
    The lowest value among the probe values is returned. Not supported on "string" and "histogram" probes. For fraction-probes, if any denominator contains a zero value, the calculated sum returned is [0, 0].
    max
    The highest value among probe values is returned. Not supported on "string" and "histogram" probes.
    arith-mean
    The arithmetic mean is calculated for all the probe values. Not supported on "string" and "histogram" probes.
    weighted-arith-mean
    Only supported in fraction type probes. The denominators are used as weights.

    Using these weights implies that the weighted arithmetic mean can be calculated by adding all numerators and denominators, producing a new fraction of these sums.

    For example, when calculating the mean instruction per cycles (IPC) on all processors (where the IPC per processor is represented as a fraction: instructions / cycles). With two processors having [20/30] and [40/50], the total IPC becomes [(20+40)/(30+50)] or [60/80] and the IPC value of 0.75.

    median
    The median among the probe values is returned. Not supported on "fraction", "string" and "histogram" probes.
    object-histogram
    A histogram probe is created using the probe-owner-objects as key and their probe-values value. The type of this aggregate probe must be set to "histogram". Only supported on "int" and "float" probes types.
    class-histogram
    Similar to the object-histogram, but here the histogram uses the classname of the owner-object as key, and the value is the sum of the probe-values with the same class. The type of this aggregate probe must be set to "histogram". Only supported on "int" and "float" probes types.

    All key/value pairs except the Probe_Key_Kind and Probe_Key_Type are optional.

    SIM_INTERFACE(probe) {
            attr_value_t (*value)(conf_object_t *obj);
            attr_value_t (*properties)(conf_object_t *obj);
    };
    #define PROBE_INTERFACE "probe"
    

    Execution Context
    Global Context for all methods.

    probe_array

    Description
    This interface is similar to the probe_index interface, except that an additional all_values() method returns an attr_value_t list of values as individually returned when calling value(idx) on each indexed probe. Using all_values() instead of looping over value(idx) can provide a significant improvement in performance, depending on the number of probes whose values need to be read, starting from a couple of probes. The probe_sampler objects, provided in the probe-monitor extension, make use of the all_values() method to boost their performance when sampling probes implemented with the probe_array interface.

    SIM_INTERFACE(probe_array) {
            int (*num_indices)(conf_object_t *obj);
            attr_value_t (*value)(conf_object_t *obj, int idx);
            attr_value_t (*all_values)(conf_object_t *obj);
            attr_value_t (*properties)(conf_object_t *obj, int idx);
    };
    #define PROBE_ARRAY_INTERFACE "probe_array"
    

    Execution Context
    Global Context for all methods.

    probe_index

    Description
    This interface is similar to the probe interface, except that the indexed version allows multiple probes to be defined with a single interface. The same index corresponds to the same probe for value and properties methods. The amount of probes that the interfaces supports is returned through the num_indices() method, which should be static.

    SIM_INTERFACE(probe_index) {
            int (*num_indices)(conf_object_t *obj);
            attr_value_t (*value)(conf_object_t *obj, int idx);
            attr_value_t (*properties)(conf_object_t *obj, int idx);
    };
    #define PROBE_INDEX_INTERFACE "probe_index"
    

    Execution Context
    Global Context for all methods.

    probe_sampler_cache

    Description
    This interface is implemented by the singleton probes object. The interface is expected to be used by either probe-samplers (enable, disable or by a probe which supports caching (get_generation_id).

    When a probe-sampler calls the enable method, caching can start. Caching depends on a generation id, this is automatically increased by enable.

    With caching enabled, probes can return the previous value back, avoiding expensive calculation, if they are read multiple times (either directly, or indirectly from other probes). It can also be used to avoid probe values to return a slightly different value the next time in the same sample, such as wallclock time.

    A probe which wants to use caching needs to call the get_generation_id method. As long as the generation id is the same as the last time the probe-value was returned, the same probe-value can be returned. Otherwise a new value needs to be returned. Generation id zero, is special, it means that caching is not currently enabled.

    When sampling is finished the probe_sampler calls the disable which will cause the generation id zero to be returned until the next sample begins again.

    SIM_INTERFACE(probe_sampler_cache) {
            void (*enable)(conf_object_t *obj);
            void (*disable)(conf_object_t *obj);
    
            uint64 (*get_generation)(conf_object_t *obj);
    };
    #define PROBE_SAMPLER_CACHE_INTERFACE "probe_sampler_cache"
    

    Execution Context
    Global Context for all methods.

    probe_subscribe

    Description
    This is an optional additional probe interface. This interface should be implemented to prevent any slowdown or unwanted side-effects if there are no listener on the probe. The subscribe() method should increment a reference count on how many subscribers there are, and do any kind of preparation to activate the probe when it is being used.

    Similarly, the unsubscribe() method should decrement the reference count and disable the feature when there is no subscribers left.

    The num_subscribers() method should return the current reference count.

    SIM_INTERFACE(probe_subscribe) {
            void (*subscribe)(conf_object_t *obj);
            void (*unsubscribe)(conf_object_t *obj);
            int  (*num_subscribers)(conf_object_t *obj);
    };
    #define PROBE_SUBSCRIBE_INTERFACE "probe_subscribe"
    

    Execution Context
    Global Context for all methods.

    recorder_v2

    Description
    The recorder_v2 interface is implemented by the recorder, and can be used by any object interacting with the outside world in order to make re-runs of the same simulation behave identically. This is a requirement for reverse execution to work. Objects using this interface must implement the recorded interface themselves.

    An object uses it by calling the record method with itself and the data it wishes to record as parameters. The recorder will then save the data and call the input method in the recorded interface on the object.

    The playback method returns whether the recorder is currently playing back recorded data. It may be used by the object to determine if output to the outside world should be dropped or not.

    SIM_INTERFACE(recorder_v2) {
            void (*record)(conf_object_t *NOTNULL obj,
                           conf_object_t *NOTNULL sender, bytes_t data);
            bool (*playback)(conf_object_t *NOTNULL obj);
    };
    #define RECORDER_V2_INTERFACE "recorder_v2"
    

    The recorded interface is implemented by objects that wish to use the recorder_v2 interface.

    The input method is called with data that has been recorded. The playback parameter is set if the data came from a previous recording, and clear if the data came directly from a call to record in recorder_v2 with live data.

    SIM_INTERFACE(recorded) {
            void (*input)(conf_object_t *NOTNULL obj, bytes_t data, bool playback);
    };
    #define RECORDED_INTERFACE "recorded"
    

    Execution Context
    Cell Context for all methods.

    register_breakpoint

    Description
    This is an optional CPU interface allowing the execution to break upon any register change, both explicit by the software and implicit changes by the model itself.

    The add_breakpoint function adds a new breakpoint. The reg_name is the register name. When register becomes the value, simulator will stop. The break_upon_change means whether simulator should stop upon change of the register value. In this case, value is not used. The mask can be used when only certain bits are of interest.

    The remove_breakpoint function removes a breakpoint with a given id. If the id is -1, then all breakpoints are removed.

    The function get_breakpoints returns a list of defined breakpoints. Each breakpoint in the list is described by a tuple: (breakpoint_id, register_name, break_value, mask). If the breakpoint is triggered upon every register value change, then break_value is NIL.

    SIM_INTERFACE(register_breakpoint) {
            int (*add_breakpoint)(conf_object_t *obj, const char *reg_name,
                                  uint64 value, uint64 mask,
                                  bool break_upon_change);
            bool (*remove_breakpoint)(conf_object_t *obj, int id);
            attr_value_t (*get_breakpoints)(conf_object_t *obj);
    };
    
    #define REGISTER_BREAKPOINT_INTERFACE "register_breakpoint"
    

    Execution Context
    Global Context for all methods.

    screenshot

    Description
    The screenshot interface facilitates storing screenshots. It is implemented by the graphics console.

    All screenshots store current screen data, using 24-bit RGB pixel format.

    SIM_INTERFACE(screenshot) {
            bool (*save_png)(conf_object_t *NOTNULL obj, const char *filename);
            bool (*save_bmp)(conf_object_t *NOTNULL obj, const char *filename);
    };
    #define SCREENSHOT_INTERFACE "screenshot"
    

    Execution Context
    Global Context for all methods

    serial_console_frontend

    Description
    The serial_console_frontend interface can be implemented by devices that want to retrieve the character stream passing through the text console. Objects implementing this interface can be attached to a text console and will receive output in the same way as a telnet connection.

    SIM_INTERFACE(serial_console_frontend) {
            void (*write)(conf_object_t *NOTNULL obj, uint8 value);
    };
    #define SERIAL_CONSOLE_FRONTEND_INTERFACE "serial_console_frontend"
    

    Execution Context
    Cell Context

    table

    Description
    The table interface can be implemented by objects holding data which can be presented in a table by the user interface (through Simics CLI command outputs, Eclipse etc.)

    By properly implementing the table interface, less object specific code is needed to provide the data to the user. Generic Simics commands (associated with the table interface) allows the data to sorted on the desired column and printed in a uniform way. Similarly, the data can be exported to a comma separated value (.csv) file, making it possible to process the result in a spreadsheet program.

    The data() method returns the data as an attr_value_t array where the outer list contains each row and the inner list contains the columns for that row. The number of columns in each row must be exactly the same. The data only holds the actual data, not the headers for each column, which instead is specified in the properties() method. The data can be unsorted, it is up to the user of the interface to sort it in a suitable way.

    The data itself is sufficient for producing a table, but to customize the table layout the properties method can return hints on how the table should be presented more in detail. For example, specifying which column the table should be sorted on by default, or if a column preferably should be printed with hexadecimal numbers instead of decimals. In addition, the properties also contains the name of the columns as well as additional meta-data such as what each column represents, or what the entire table represents.

    The properties also returns an attr_value_t type as a list of key/value pairs. Thus, each list-entry should be exactly two elements long, but the value part can itself be a new list of key/value pairs for some keys.

    The table property keys are of table_key_t type:

    typedef enum {
            /* Table property keys */
            Table_Key_Name = 1,
            Table_Key_Description,
            Table_Key_Default_Sort_Column,
            Table_Key_Columns,
            Table_Key_Extra_Headers,
            Table_Key_Stream_Header_Repeat,
            /* Additional properties might be added in the future.
               Thus, unknown values should be silently ignored. */
    } table_key_t;

    This is the definition for each table property:

    Table_Key_Name String
    A short description of what the table represents.
    Table_Key_Description String
    A longer description what the table represents.
    Table_Key_Default_Sort_Column String
    References the Column_Key_Name (inside the Table_Key_Columns) to tell which column that should be used when sorting the table by default. If the Column_Key_Name contains new-line characters, replace those with spaces. If not specified, the table will be unsorted by default.
    Table_Key_Extra_Headers List of additional header rows
    In addition to the column-headers printed, this property allows additional header rows to be presented before the column headers. These additional header rows can span over multiple columns, providing additional explanation and grouping of columns.

    The format is: list of additional header rows, each identified as a Extra_Header_Key_Row. Each row is defined by a list of the header-elements where each element is a list of the header's key/value pair properties.

    The header property keys are of extra_header_key_t type, this is the definition for each extra header property:

    typedef enum {
            /* Header property keys */
            Extra_Header_Key_Row = 2000,
            Extra_Header_Key_Name,
            Extra_Header_Key_Description,
            Extra_Header_Key_First_Column,
            Extra_Header_Key_Last_Column,
    } extra_header_key_t;

    Extra_Header_Key_Row List of header elements
    Identifies a new header row.
    Extra_Header_Key_Name String
    The name printed for the extra header element.
    Extra_Header_Key_Description String
    Optional additional text describing the header.
    Extra_Header_Key_First_Column String
    A reference to the column the additional header spans from.
    Extra_Header_Key_Last_Column String
    A reference to the column the additional header spans to.

    If there is only one header element on a row, and neither Extra_Header_Key_First_Column and Extra_Header_Key_Last_Column are set, the header will span the entire table, even if additional columns has been added by the system. In all other cases first/last column always needs to be specified.
    Table_Key_Columns List of columns, with key/value pairs
    A list of the columns, where each element consists of key/value pairs defining each column with various properties. The column properties are named with Column_Key_* which are listed below. The list size should match the number of columns in the data. List item 1, represents key/value definitions for column 1 etc.

    The column property keys are of column_key_t type:

    typedef enum {                
            /* Column property keys */
            Column_Key_Name = 1000,       /* Other number series than table-keys */
            Column_Key_Description,
            Column_Key_Alignment,
            Column_Key_Int_Radix,
            Column_Key_Float_Percent,
            Column_Key_Float_Decimals,
            Column_Key_Sort_Descending,
            Column_Key_Hide_Homogeneous,
            Column_Key_Generate_Percent_Column,
            Column_Key_Generate_Acc_Percent_Column,
            Column_Key_Footer_Sum,
            Column_Key_Footer_Mean,
            Column_Key_Int_Grouping,
            Column_Key_Int_Pad_Width,
            Column_Key_Metric_Prefix,
            Column_Key_Binary_Prefix,
            Column_Key_Time_Format,
            Column_Key_Unique_Id,
            Column_Key_Width,
            Column_Key_Word_Delimiters,
            /* Additional properties might be added in the future.
               Thus, unknown values should be silently ignored. */        
    } column_key_t;

    This is the definition for each column property:

    Column_Key_Name String
    The name for the column, displayed on the first row of the table. Preferably these should be as short as possible while still being descriptive. It is possible to break longer strings with a newline character (\n)
    Column_Key_Description String
    A longer descriptive text describing the column content.
    Column_Key_Alignment String: ["left", "right", "center"]
    Specifies if the column data should be aligned to the left, right or centered for the entire table data. If not specified strings are left-aligned and numbers right-aligned.
    Column_Key_Word_Delimiters String
    Overrides the default set of character that will be used for word wrapping of long lines. Default is " -_:,.".
    Column_Key_Int_Radix Integer: [2,10,16]]
    Specifies the default radix which should be used for when displaying integers numbers, 2 means binary, 10 decimal and 16 hexadecimal. If not specified, the integers will be displayed in the default radix, selectable by the output-radix command.
    Column_Key_Int_Grouping Boolean
    If False, the current user preferences for integer grouping will be ignored. For example, instead of 12_345 the output will read 12345. If not specified, default grouping is respected. Grouping is set by the output-radix command.
    Column_Key_Pad_Width Integer
    Zero-extends values up to N characters. This allows similar width of the column data regardless of the value in each cell. For example, with hexadecimal output and 64-bits value printed, the column might be easier to read with a pad-width of 16. If not specified, the default size used 1 (no-padding).
    Column_Key_Float_Percent Boolean
    If True, any float data in the column will be printed as a percent value. For example, 0.1234 will be printed as 12.34%.
    Column_Key_Float_Decimals Integer
    Specifies how many decimal digit that should be printed for any floating point values in the column. If not specified 2 decimals are printed by default.
    Column_Key_Metric_Prefix String
    A metric prefix (m, µ, n, p, f, a, z, y, k, M, G, T, P, E, Z, Y) will be added to the value and the value will be adjusted accordingly. If the string is non-empty the string will be interpreted as a unit that will be added after the prefix for each value.
    Column_Key_Binary_Prefix String
    A binary prefix (ki, Mi, Gi, Ti, Pi, Ei, Zi, Yi) will be added to the value and the value will be adjusted accordingly. If the string is non-empty the string will be interpreted as a unit that will be added after the prefix for each value.
    Column_Key_Time_Format Boolean
    If True the value (in seconds) will be formatted as HH:MM:SS.ss, where only the used parts are shown. The number of seconds decimals formatted is can be controlled by Column_Key_Float_Decimals property. To compact the width, decimals are dropped when hours are displayed.
    Column_Key_Unique_Id String
    If the same name is set for multiple columns in a table, this property sets a unique name for a specific column, needed when referencing the column from extra headers.
    Column_Key_Sort_Descending Boolean
    If True, specifies if a column should be sorted with the highest values first. If not specified, this is automatically set to True for any numbers and False for other types.
    Column_Key_Hide_Homogeneous Integer/Float/String
    If this property is specified and the column consists entirely of the given data, the column will not be shown. For example, if the table has a column which only consists of empty strings (""), the column can be discarded from the resulting table.
    If True, all columns values are summed up and displayed in a footer row, below the actual table.
    If True, an arithmetic mean of the column values are calculated and displayed in a footer row, below the actual table.
    Column_Key_Generate_Percent_Column List of key/value pairs for new column.
    If this property is set, an additional column will be created (to the right of this column) showing the percent values for each row. The list of key/value pairs allows to the created column to be customized, however just giving an empty list should give understandable default values.
    Column_Key_Generate_Acc_Percent_Column List of key/value pairs for new column.
    If this property is set, an additional column will be created (to the right of this column) showing the accumulated percent values for each row. The list of key/value pairs allows to the created column to be customized, however just giving an empty list should give understandable default values.

    SIM_INTERFACE(table) {
            /* Returns all rows and columns in the following format:
               [[[i|f|s|o|n*]*]] where the outer list is the row
               and the inner list is the data for each column. */
            attr_value_t (*data)(conf_object_t *obj);
            
            /* Defines the table structure and meta-data for the table
               using a list of key/value pairs.
               [[[ia]*]*] where the integer is the key taken from the
               table_properties_t. The value is key-specific. */
            attr_value_t (*properties)(conf_object_t *obj);
    
    };
    #define TABLE_INTERFACE "table"
    

    Execution Context
    Global Context for all methods.

    telnet_connection_v2

    Description
    The telnet_connection_v2 interface is used to control the text console telnet server.

    The text console has a built-in telnet server.

    The listening method indicates whether the server is listening for connections.

    The connected method indicates whether there is a connected telnet client.

    The disconnect method forcibly disconnects any connected client.

    SIM_INTERFACE(telnet_connection_v2) {
            bool (*listening)(conf_object_t *NOTNULL obj);
            bool (*connected)(conf_object_t *NOTNULL obj);
            void (*disconnect)(conf_object_t *NOTNULL obj);
    };
    #define TELNET_CONNECTION_V2_INTERFACE "telnet_connection_v2"
    

    Execution Context
    Global Context for all methods

    vnc_server_v2

    Description
    The vnc_server_v2 interface is used to control the graphics console VNC server.

    The graphics console has a built-in VNC server, supporting any number of connected clients.

    The listening method indicates whether the server is listening for connections.

    The num_clients method returns the number of connected clients.

    The disconnect method forcibly disconnects any connected client.

    SIM_INTERFACE(vnc_server_v2) {
            bool (*listening)(conf_object_t *NOTNULL obj);
            int (*num_clients)(conf_object_t *NOTNULL obj);
            void (*disconnect)(conf_object_t *NOTNULL obj);
    };
    #define VNC_SERVER_V2_INTERFACE "vnc_server_v2"
    

    Execution Context
    Global Context for all methods

    9 Processor API

    Refer to the Processor Model Integration Guide for more information.

    9.1 Interfaces

    This section lists the interfaces that can be implemented by the processor model to enable certain Simics features. They are not required, but implementing them will allow user defined processor models to support the same generic feature set as Simics standard processor models. If you intend to plug your model into an existing Simics-provided platform, then many of these interfaces are actually required for such a platform to function.

    Processor Info Interface

    The processor_info_v2 interface is implemented by processors models. The interface has processor generic functions that are architecture independent.

    The disassemble function returns the disassemble string for an instruction at address with opcode according to instruction_data. The instruction_data is an attr_value_t value of data type with the bytes of the opcode. The bytes are in the same order as they are stored in memory. For VLIW architectures, sub_operation is used to select which sub-operation to disassemble. The sub-operations start at zero, and a request for the entire unit including all sub-operations is encoded with sub-operation -1. A request for a sub-operation that is not present (for example when sub-operation is neither 0 nor -1 for non-VLIW architectures) results in the integer part of the return tuple being set to zero. If successful, the function should return a tuple with the size of the instruction in bytes and the disassembly string. The disassembly string should be allocated with MM_MALLOC or similar and is to be freed by the caller. If more bytes are needed, then the function should indicate that by returning a negative number in the tuple where the absolute value of the number is the required number of bytes. The string should be NULL if more bytes are needed. The implementor of processor_info_v2 is allowed to request one additional byte at a time until enough bytes are passed to determine what the instruction is. Illegal instructions should still result in a valid returned tuple, where the integer part will be used by the disassemble command to skip that many bytes before disassembling the next instruction. The address can be used to display absolute destinations of program counter relative branches.

    The set_program_counter function sets the program counter in the processor. The get_program_counter function returns the current program counter.

    The logical_to_physical function translates a logical address to a physical address of the type defined by access_type. The function returns a physical_block_t struct with valid bit and the address. The address is valid when the valid bit is not 0. The logical_to_physical function also returns block_start and block_end. The start and end of a block has the same logical to physical transformation as the translated address. The range is inclusive, so block_end should be the address of the last byte of the block. This information can be used to figure out how often the logical_to_physical function needs to be called. An implementation would typically return the page start and end here, but it is free to return any power of 2 sized block as long as it includes the translated address.

    The current operating mode of the processor is returned with get_processor_mode.

    The processor can be enabled or disabled with the enable_processor or disable_processor functions. The functions should return 0 if the processor changed from enabled to disabled or from disabled to enabled, and 1 if the processor did not change state. The current state is returned by the get_enabled function. Enabled or disabled here refers to the state that the user of the model has put the processor into. In particular, it is independent of the power mode of the processor. A processor that has powered down does not count as disabled in this sense, nor does the enable_processor wake up a processor that is in a power-saving sleep state.

    The endianness of the processor is returned by the get_endian function.

    The physical memory object is returned by the get_physical_memory function. The object returned by get_physical_memory is used to set breakpoints by the global break command, and to read and write physical memory through set, get, load-binary, load-file, and the default implementation of disassemble. The object returned implements the memory_space and breakpoint interfaces. The memory_space interface for the returned object is only be used in inquiry mode corresponding to actions by the simulator itself rather than by the simulated software. An implementation may return NULL from this method, which will lead to the command listed above not being supported when such a processor is selected.

    The get_logical_address_width function returns the number of logical/virtual address bits and the get_physical_address_width function returns the number of physical address bits.

    The processor architecture is returned by calling the architecture function. The architecture should be one of arm, mips32, mips64, ppc32, ppc64, sparc-v8, sparc-v9, x86, x86-64, or something else if none of the listed is a good match.

    All functions in the interface are optional. Each function can be set to NULL if it is not supported.

    SIM_INTERFACE(processor_info_v2) {
            tuple_int_string_t (*disassemble)(conf_object_t *obj,
                                              generic_address_t address,
                                              attr_value_t instruction_data,
                                              int sub_operation);
            void (*set_program_counter)(conf_object_t *obj,
                                        logical_address_t pc);
            logical_address_t (*get_program_counter)(conf_object_t *obj);
            physical_block_t (*logical_to_physical)(conf_object_t *obj,
                                                    logical_address_t address,
                                                    access_t access_type);
            processor_mode_t (*get_processor_mode)(conf_object_t *obj);
            int (*enable_processor)(conf_object_t *obj);
            int (*disable_processor)(conf_object_t *obj);
            int (*get_enabled)(conf_object_t *obj);
    
            cpu_endian_t (*get_endian)(conf_object_t *obj);
            conf_object_t *(*get_physical_memory)(conf_object_t *obj);
    
            int (*get_logical_address_width)(conf_object_t *obj);
            int (*get_physical_address_width)(conf_object_t *obj);
    
            const char *(*architecture)(conf_object_t *obj);
    };
    
    #define PROCESSOR_INFO_V2_INTERFACE "processor_info_v2"
    

    Note that the original version of this interface (processor_info) must also be implemented. The only difference between the two interfaces is that the original version lacks the get_processor_mode function.

    Processor CLI Interface

    Some commands and features in the CLI use the processor_cli interface. Those commands will have limited functionality if the interface is not fully implemented.

    The first argument to each function is the object to act on. This object should implement both the processor_info interface and the processor_cli interface.

    The get_disassembly function is used for the disassemble command as well as to disassemble the next instruction to be executed, when control is returned to the CLI prompt. For most architectures, get_disassembly can be set to NULL, in which case the command will use other interfaces to provide a generic disassembly. The get_disassembly function should return a tuple with the length of the instruction in bytes and the disassembly string. The addr_prefix parameter selects the address type of the address parameter, whether it is a physical address ("p"), a linear address ("l") or a virtual address ("v"), just as returned from get_address_prefix. The address parameter is the program counter for the instruction to disassemble. If print_cpu is non-zero, then the name of the processor should be included first in the disassembly line. If mnemonic is not NULL, then it should be output instead of the instruction disassemble. The mnemonic is used to print exception or interrupt information as returned by the get_pending_exception_string function.

    get_pregs returns the string to output in the CLI for the print-processor-registers command. The all parameter is a boolean corresponding to the -all switch to the print-processor-registers command.

    The diff_regs function is used by the stepi command when the -r flag is used. The diff_regs function returns a list of register names, where each register in that list will be read through the int_register interface before and after an instruction.

    When returning to the CLI prompt, information about the next instruction or step to execute is printed. Normally, that is the disassemble of the instruction at the current program counter. The get_pending_exception_string function is called before the disassembly to find out if the next step will not be an instruction, but rather a taken exception or interrupt. The function should inspect the given cpu (an object implementing processor_info and processor_cli) and return NULL if the next step will be the execution of the instruction at the current program counter. If the next step will instead be the handling of an exception or interrupt, then a string saying that should be returned.

    The get_address_prefix function returns a string with the default address prefix for memory related commands. Simics defines the generic prefixes "v" for virtual addresses, "l" for linear addresses, and "p" for physical addresses. The default if get_address_prefix is NULL is "v" for virtual addresses.

    translate_to_physical translates an address to a physical address. If translate_to_physical is NULL, then the only allowed address prefixes are "v" (virtual) and "p" (physical), and the logical_to_physical function in the processor_info interface will be used to translate virtual addresses.

    SIM_INTERFACE(processor_cli) {
    	tuple_int_string_t (*get_disassembly)(conf_object_t *obj,
                                                  const char *addr_prefix,
                                                  generic_address_t address,
                                                  bool print_cpu,
                                                  const char *mnemonic);
    	char *(*get_pregs)(conf_object_t *cpu,
                               bool all);
    	attr_value_t (*get_diff_regs)(conf_object_t *obj);
    	char *(*get_pending_exception_string)(conf_object_t *obj);
    	char *(*get_address_prefix)(conf_object_t *obj);
    	physical_block_t (*translate_to_physical)(conf_object_t *obj,
                                                      const char *prefix,
                                                      generic_address_t address);
    };
    
    #define PROCESSOR_CLI_INTERFACE "processor_cli"
    

    Processor GUI Interface

    The processor_gui interface is implemented by processors that support displays in the Simics native GUI. It is only registered to indicate support for the displays, and does not contain any actual functionality.

    SIM_INTERFACE(processor_gui) {
            void (*dummy)(conf_object_t *obj);
    };
    
    #define PROCESSOR_GUI_INTERFACE "processor_gui"
    

    Step Interface

    The step interface is typically implemented by processors, but can be implemented by other objects as well. Its purpose is to handle step events using a queue.

    The current number of steps for the queue is returned when calling get_step_count.

    The post_step function will schedule an event that will occur after steps (which must be nonnegative) counted from local current step at queue. An event previously posted can be removed by calling cancel_step. The cancel_step function takes a function pred as argument which is called when a matching event is found. The event is only removed if pred returns 1. The find_next_step takes the same arguments as cancel_step but only returns the number of cycles before the event will occur. The evclass is the event class, obj is the object posting the event, and user_data is pointer to data used as a parameter when calling the callback function defined in the evclass. If no matching event was found, find_next_step returns −1.

    The events method returns a list of all pending events in expiration order. Each element is a four-element list containing the event object, the event class name, the expiration time counted in steps as an integer and the event description as given by the event class describe method, or nil for events whose event class do not define that method.

    The advance function will increment the number of steps for the queue, decrementing the number of steps to the first event to the value defined by steps. The number of steps remaining to the next event is returned. It is an error to advance beyond the next pending event, so the return value is never negative.

    The implementor of the step interface can use any checkpoint representation. The name field in the event class data structure is unique, and the attribute setter function for checkpoint restore can use SIM_get_event_class to get the event class structure corresponding to an event class name.

    SIM_INTERFACE(step) {
            pc_step_t (*get_step_count)(conf_object_t *NOTNULL queue);
            void (*post_step)(
                    conf_object_t *NOTNULL queue,
                    event_class_t *NOTNULL evclass,
                    conf_object_t *NOTNULL obj,
                    pc_step_t steps,
                    lang_void *user_data);
            void (*cancel_step)(
                    conf_object_t *NOTNULL queue,
                    event_class_t *NOTNULL evclass,
                    conf_object_t *NOTNULL obj,
                    int (*pred)(lang_void *data, lang_void *match_data),
                    lang_void *match_data);
            pc_step_t (*find_next_step)(
                    conf_object_t *NOTNULL queue,
                    event_class_t *NOTNULL evclass,
                    conf_object_t *NOTNULL obj,
                    int (*pred)(lang_void *data, lang_void *match_data),
                    lang_void *match_data);
    
            attr_value_t (*events)(conf_object_t *NOTNULL obj);
    
            pc_step_t (*advance)(conf_object_t *queue, pc_step_t steps);
    };
    
    #define STEP_INTERFACE "step"
    

    Step-Cycle-Ratio Interface

    The step_cycle_ratio interface is implemented by processors that support a changeable ratio between steps and cycles. The set-step-rate command uses this interface to set the ratio between steps and cycles.

    The set_ratio sets the ratio between steps and cycles. Note that the introduction of stall cycles can skew the ratio. The get_ratio simply returns the current ratio.

    The cycles and step arguments must be in the range [1..128] and cycles must be a power of two. Implementers of this interface may choose to ignore other values of cycles and step and may log an error.

    typedef struct {
            uint32 steps;
            uint32 cycles;
    } step_cycle_ratio_t;
    
    SIM_INTERFACE(step_cycle_ratio) {
            step_cycle_ratio_t (*get_ratio)(conf_object_t *obj);
            void (*set_ratio)(conf_object_t *obj, uint32 steps, uint32 cycles);
    };
    
    #define STEP_CYCLE_RATIO_INTERFACE "step_cycle_ratio"
    

    Stall Interface

    The stall interface can be implemented by objects that also implement the cycle and step interfaces. The stall interface controls the addition of extra cycles between steps.

    The get_stall_cycles function returns the remaining number of stall cycles. The object will advance that number of cycles before starting with the next step.

    The set_stall_cycles function is used to change the number of stall cycles before the next step. It is legal to first call this function with a large value for cycles and then at a later point reduce the cycle count is resume execution earlier than indicated by the first call.

    The get_total_stall_cycles returns the total accumulated number of stall cycles.

    SIM_INTERFACE(stall) {
            cycles_t (*get_stall_cycles)(conf_object_t *obj);
            void (*set_stall_cycles)(conf_object_t *obj, cycles_t cycles);
            cycles_t (*get_total_stall_cycles)(conf_object_t *obj);
    };
    #define STALL_INTERFACE "stall"
    

    Register Interface

    The int_register interface is used for access to registers in a processor. It can be used to access any kind of integer register, not only the "normal" registers. This includes all kinds of control registers, hidden registers and anything else that might be useful to access as a register. The only limitation is that the register value should be representable as a 64-bit unsigned integer.

    This interface can be implemented by other classes than processors, but it is likely to be found mostly in processors.

    Registers are identified by a number, and there are two functions to translate from register names to register numbers and back. The translation need not be one-to-one, which means that one register can have several names. A register name can, however, only translate to a single register number.

    Often, registers are grouped in register banks, where registers in the bank are numbered from 0 up. Registers in a bank should have consecutive numbers (unless their numbering is very sparse). This allows a user to deduce register numbers by calling get_number for the first register only. The first register numbers should be used for the general-purpose integer registers, if possible (so that integer register rN has number N).

    Using this interface to read or write registers does not cause any side effects, such as triggering interrupts or signalling haps.

    get_number translates a register name to its number. Returns -1 if the register does not exist.

    get_name translates a register number to its canonical name.

    read reads a register value.

    write writes a new register value.

    all_registers returns a list of all register numbers that can be used for this object.

    register_info returns information about a single register. The information return depends on the info parameter.

    Sim_RegInfo_Catchable
    Return 1 if Core_Control_Register_Write and Core_Control_Register_Read are triggered when this register is written or read.
    Return 0 otherwise.

    typedef enum {
            Sim_RegInfo_Catchable
    } ireg_info_t;

    SIM_INTERFACE(int_register) {
            int (*get_number)(conf_object_t *NOTNULL obj,
                              const char *NOTNULL name);
            const char *(*get_name)(conf_object_t *NOTNULL obj, int reg);
            uint64 (*read)(conf_object_t *NOTNULL obj, int reg);
            void (*write)(conf_object_t *NOTNULL obj, int reg, uint64 val);
            attr_value_t (*all_registers)(conf_object_t *NOTNULL obj);
            int (*register_info)(conf_object_t *NOTNULL obj, int reg,
                                 ireg_info_t info);
    };
    
    #define INT_REGISTER_INTERFACE "int_register"
    

    Decoder Interface

    SIM_INTERFACE(decoder) {
            void (*register_decoder)(conf_object_t *obj, 
                                     decoder_t *NOTNULL decoder);
            void (*unregister_decoder)(conf_object_t *obj, 
                                       decoder_t *NOTNULL decoder);
    };

    The decoder interface is implemented by processors that allows connecting user decoders. This allows a user to implement the semantics of instructions that are not available in the standard Simics model or change the semantics of instructions implemented by Simics. This interface replaces SIM_register_arch_decoder and SIM_unregister_arch_decoder functions.

    The register_decoder function adds a decoder and unregister_decoder removes a decoder.

    The decoder is installed/removed for every object of the same class as the obj argument which must be the same object from which the interface was fetched.

    When Simics decodes an instruction, it will first see if any instruction decoders are registered for the current CPU class. For any decoders it finds, Simics will let it try to decode the instruction. The decoders are called in order, starting with the last registered decoder, and if one decoder accepts the instruction, the rest of the decoders will not be called.

    The decoder is specified by the decoder_t data structure that the user supplies:

    typedef struct {
            void *user_data;
            int (*NOTNULL decode)(uint8 *code,
                                  int valid_bytes,
                                  conf_object_t *cpu,
                                  instruction_info_t *ii,
                                  void *user_data);
            tuple_int_string_t (*NOTNULL disassemble)(uint8 *code,
                                                      int valid_bytes,
                                                      conf_object_t *cpu,
                                                      void *user_data);
            int (*NOTNULL flush)(instruction_info_t *ii,
                                 void *user_data);
    } decoder_t;

    The decode function is called to decode an instruction pointed to by code. The first byte corresponds to the lowest address of the instruction in the simulated memory. valid_bytes tells how many bytes can be read. The CPU is given in the cpu parameter. When the decoder has successfully decoded an instruction, it should set the ii_ServiceRoutine, the ii_Arg, and the ii_Type members of the ii structure (see below), and returns the number of bytes used in the decoding. If it does not apply to the given instruction, it should return zero. If the decoder needs more data than valid_bytes it should return a negative number corresponding to the total number of bytes it will need to continue the decoding. The underlying architecture limits the number of bytes that can be requested, e.g. no more than 4 bytes can be requested on most RISC architectures. Simics will call the decoder again when more bytes are available. This process is repeated until the decoder accepts or rejects the instruction. A decoder should never request more data than it needs. For example, if an instructions can be rejected by looking at the first byte, the decoder should never ask for more bytes.

    The instruction_info_t is defined as follows:

    typedef struct instruction_info {
            service_routine_t  ii_ServiceRoutine;
            uint64             ii_Arg;
            unsigned int       ii_Type;
            lang_void         *ii_UserData;
            logical_address_t  ii_LogicalAddress;
            physical_address_t ii_PhysicalAddress;
    } instruction_info_t;

    ii_ServiceRoutine is a pointer to a function that will be called by Simics every time the instruction is executed. It has the following prototype:

    typedef exception_type_t (*service_routine_t)(conf_object_t *cpu, 
                                                  uint64 arg,
                                                  lang_void *user_data);

    The service routine function should return an exception when it is finished to signal its status. If no exception occurs Sim_PE_No_Exception should be returned.

    See exception_type_t in src/include/simics/base/memory.h for the different exceptions available.

    A special return value, Sim_PE_Default_Semantics, can be returned; this signals Simics to run the default semantics for the instruction. This is useful if the semantics of an instruction should be changed but the user routine does not want to handle it all the time.

    Note that in a shared memory multiprocessor, the CPU used in decoding may differ from the CPU that executes the instruction, since the decoded instructions may be cached.

    ii_Arg is the argument arg that will be passed on to the service routine function. Op code bit-fields for the instruction such as register numbers or intermediate values can be stored here. The ii_UserData field can also be used to pass information to the service routine if more data is needed.

    ii_Type is either UD_IT_SEQUENTIAL or UD_IT_CONTROL_FLOW. A sequential type means that the instruction does not perform any branches and the update of the program counter(s) is handled by Simics. In a control flow instruction on the other hand it is up to the user to set the program counter(s).

    ii_LogicalAddress and ii_PhysicalAddress holds the logical and physical addresses of the instruction to be decoded.

    The disassemble function is called to disassemble an instruction. It uses the same code, valid_bytes, and cpu parameters as the decode function. If the disassembly is valid, then the string part of the returned tuple_int_string_t struct should be a MALLOCed string with the disassembly and the integer part should be its length in bytes. The caller is responsible for freeing the disassembly string. The string member should be NULL and the integer part should be zero if the disassembly is not valid. If the disassemble function needs more data than valid_bytes it should return a negative number in the integer part in the same way as the decode function, and set the string part to NULL.

    The flush function is called to free any memory allocated when decoding an instruction and any user data associated with the instruction. It should return zero if it does not recognize the instruction, and non-zero if it has accepted it. Usually, the way to recognize if a decoded instruction is the right one to flush is to compare ii->ii_ServiceRoutine with the function that was set in the decode function. Note that the cpu parameter is the processor that caused the flush. It is more or less an arbitrary processor and should be ignored.

    In addition to the function pointers, the decoder_t structure contains a user_data pointer that is passed to all the functions. This can be used for passing any data to the decoder functions.

    Exception Interface

    The exception interface is used together with the Core_Exception hap to enable inspection abilities for triggered exceptions.

    The exception interface is used to translate exception numbers, as received by the Core_Exception hap, to names, and vice versa.

    The get_number function returns the number associated with an exception name, or -1 if the no exception with the given name exist. The get_name returns the name associated with an exception number. The get_source function is only used on X86 targets and returns the source for an exception, as an exception number can be raised from different sources. The all_exceptions function returns a list of all exceptions numbers.

    The exception numbers are architecturally defined, while their names are defined by the model.

    SIM_INTERFACE(exception) {
            int (*get_number)(conf_object_t *NOTNULL obj,
                              const char *NOTNULL name);
            const char *(*get_name)(conf_object_t *NOTNULL obj, int exc);
            int (*get_source)(conf_object_t *NOTNULL obj, int exc);
            attr_value_t (*all_exceptions)(conf_object_t *NOTNULL obj);
    };
    
    #define EXCEPTION_INTERFACE "exception"
    

    Context Handler Interface

    Note: This interface is not supported, and may change in the future.
    Get and set current context. The set_current_context function returns zero if the passed object is not of the context class, otherwise one is returned.

    SIM_INTERFACE(context_handler) {
            conf_object_t *(*get_current_context)(conf_object_t *obj);
            int (*set_current_context)(conf_object_t *obj, conf_object_t *ctx);
    };
    
    #define CONTEXT_HANDLER_INTERFACE "context_handler"
    

    Exec Trace Interface

    The exec_trace interface is implemented by processor models that support tracing. A trace listener registers itself with the register_tracer call. The tracer callback will be called by the processor model when each instruction is just about to be executed, passing the tracer_data as passed to the register_tracer function in addition to information about the instruction that is executed. Invoke unregister_tracer with the same two pointers to deregister the listener.

    typedef void (*instruction_trace_callback_t)(lang_void *tracer_data,
                                                 conf_object_t *cpu,
                                                 linear_address_t la,
                                                 logical_address_t va,
                                                 physical_address_t pa,
                                                 byte_string_t opcode);

    The pa parameter to the callback will always be valid, but some CPU architectures may not support la or va. The la argument is typically only valid for x86 CPUs. Lastly, the opcode of the instruction is passed in opcode. The opcode is passed without endian conversion, meaning that byte X in opcode corresponds to the byte at pa + X.

    SIM_INTERFACE(exec_trace) {
            void (*register_tracer)(conf_object_t *NOTNULL cpu_obj,
                                    instruction_trace_callback_t tracer,
                                    lang_void *tracer_data);
            void (*unregister_tracer)(conf_object_t *NOTNULL cpu_obj,
                                      instruction_trace_callback_t tracer,
                                      lang_void *tracer_data);
    };
    
    #define EXEC_TRACE_INTERFACE "exec_trace"
    

    Opcode Info Interface

    The opcode_info interface is implemented by processors that need to communicate information about the encoding of instructions to the GUI.

    The get_opcode_length function returns information about instruction encoding in the current operating mode of the processor. The min_alignment field indicates the smallest allowed alignment of instructions, typically 4 for regular RISC architectures. The max_length field specifies the maximum instruction length in bytes. The avg_length is an approximation of the average instruction size.

    typedef struct {
            int min_alignment;
            int max_length;
            int avg_length;
    } opcode_length_info_t;
    
    SIM_INTERFACE(opcode_info) {
            opcode_length_info_t (*get_opcode_length_info)(conf_object_t *obj);
    };
    
    #define OPCODE_INFO_INTERFACE "opcode_info"
    

    Virtual Data Breakpoint Interface

    Add and remove virtual-address (and, on x86, linear-address) read and write breakpoints. On every read access that intersects a read breakpoint's interval, the registered callback function is called with the object that initiated the read, and the address and size of the read. (The interval includes both endpoints; first must be less than or equal to last.) Write breakpoints work exactly the same, except that the callback is given the actual value being written, not just its size.

    The callback is called before the read or write has taken place, but may not intervene. If one or more breakpoint callbacks stop the simulation, the current instruction is completed before the stop takes effect. If more than one breakpoint is triggered by the same read or write, the implementation may call their callbacks in any order.

    On x86, the Virtual_Breakpoint_Flag_Linear flag causes the breakpoint to use linear rather than virtual addresses. (Adding a breakpoint with unsupported flags is illegal.)

    Note: This interface is preliminary and may change without prior notice.
    typedef enum {
            Virtual_Breakpoint_Flag_Linear = 1
    } virtual_breakpoint_flags_t;

    SIM_INTERFACE(virtual_data_breakpoint) {
            virtual_data_bp_handle_t *NOTNULL (*add_read)(
                    conf_object_t *NOTNULL obj,
                    generic_address_t first, generic_address_t last,
                    void (*NOTNULL callback)(
                            cbdata_call_t data, conf_object_t *NOTNULL initiator,
                            generic_address_t address, unsigned size),
                    cbdata_register_t data, uint32 flags);
            virtual_data_bp_handle_t *NOTNULL (*add_write)(
                    conf_object_t *NOTNULL obj,
                    generic_address_t first, generic_address_t last,
                    void (*NOTNULL callback)(
                            cbdata_call_t data, conf_object_t *NOTNULL initiator,
                            generic_address_t address, bytes_t value),
                    cbdata_register_t data, uint32 flags);
            void (*remove)(conf_object_t *NOTNULL obj,
                           virtual_data_bp_handle_t *NOTNULL bp_handle);
    };
    #define VIRTUAL_DATA_BREAKPOINT_INTERFACE "virtual_data_breakpoint"
    

    Virtual Instruction Breakpoint Interface

    Add and remove virtual-address (and, on x86, linear-address) instruction breakpoints. Every time the processor executes an instruction that intersects the breakpoint's interval, the callback function is called with the processor, and the address and size of the instruction. (The interval includes both endpoints; first must be less than or equal to last.)

    The callback is called before the instruction is executed. If one or more breakpoint callbacks stop the simulation, the stop takes effect before the instruction is run. (This means that once the simulation starts again, the same breakpoints will trigger immediately again. The callback can use VT_step_stamp to detect re-triggering.) If more than one breakpoint is triggered by the same instruction, the implementation may call their callbacks in any order.

    If the filter function is non-null and returns false, the callback is not called. The filter function is supplied with the instruction opcode (the raw bytes of the instruction) and a processor (which may not be the same processor that the breakpoint is set on, but is guaranteed to be of the same class). The filter may base its decision only on the opcode bytes and the string obtained by asking the processor to disassemble the instruction; this allows the implementation to cache the result and omit future calls to the filter function where the opcode and disassembly string would be the same.

    On x86, the Virtual_Breakpoint_Flag_Linear flag causes the breakpoint to use linear rather than virtual addresses. Calling with unsupported flags is illegal.

    Note: This interface is preliminary and may change without prior notice.
    typedef enum {
            Virtual_Breakpoint_Flag_Linear = 1
    } virtual_breakpoint_flags_t;

    SIM_INTERFACE(virtual_instruction_breakpoint) {
            virtual_instr_bp_handle_t *NOTNULL (*add)(
                    conf_object_t *NOTNULL obj,
                    generic_address_t first, generic_address_t last,
                    bool (*filter)(cbdata_call_t filter_data,
                                   conf_object_t *NOTNULL cpu, bytes_t opcode),
                    cbdata_register_t filter_data,
                    void (*NOTNULL callback)(
                            cbdata_call_t callback_data, conf_object_t *NOTNULL cpu,
                            generic_address_t address, unsigned size),
                    cbdata_register_t callback_data, uint32 flags);
            void (*remove)(conf_object_t *NOTNULL obj,
                           virtual_instr_bp_handle_t *NOTNULL bp_handle);
    };
    #define VIRTUAL_INSTRUCTION_BREAKPOINT_INTERFACE \
            "virtual_instruction_breakpoint"
    

    Describe Registers Interface

    This interface is used by the Simics debugger to get certain information from a processor.

    The first_child function returns the first description in the sequence of child descriptions of parent or NULL if parent has no children. Groups can have both registers and groups as children, registers can only have fields as children and fields cannot have any children. If parent is NULL, return the first description in the sequence of top-level descriptions.

    Use next_description to deallocate the previous description and return the next description in the sequence or NULL if there are no more descriptions in the current sequence.

    The free_description function is used to free the description without returning the next one in the sequence.

    The first_named_value function returns the first named value in the sequence of named values for parent or NULL if there are no named values for parent. Only fields and registers can have named values.

    Use next_named_value to deallocate the previous named value and return the next named value or NULL if there are no more named values in this sequence.

    Use free_named_value to free the named value without returning the next one in the sequence.

    The get and set functions are used to get and set the value of the register. To set the value pass in a bytes_t for the value. The value passed in must be long enough to contain the full value of the register. If the bytes_t is too long it will be truncated. To get the value pass in a buffer_t which is long enough to contain the register's value. The value is encoded in little endian byte order.

    typedef enum {
            Description_Type_Group,
    
            Description_Type_Int_Reg,
            Description_Type_Float_Reg,
            Description_Type_Fields_Reg,
    
            Description_Type_Int_Field,
            Description_Type_Float_Field,
    } description_type_t;

    typedef enum {
            Reg_Role_None, /* No special role for the register. */
            Reg_Role_Program_Counter /* The register is the program counter. */
    } reg_role_t;

    typedef enum {
            Reg_Bitorder_Little_Endian,
            Reg_Bitorder_Big_Endian
    } reg_bitorder_t;

    typedef struct {
            const char *name;
            const char *description;
            const bytes_t value; /* Little endian byte order */
    } named_value_t;

    typedef struct {
            /* Common fields */
            description_type_t type;
            const char *name;
            const char *description;
    
            /* Register and field fields */
            int16 dwarf_id;            /* id used by dwarf for this register
                                          or -1 if no such id is defined. This
                                          is ABI specific, but the CPU will
                                          give the ids for the most common ABI
                                          for that architecture. */
            reg_bitorder_t bitorder;   /* Bitorder convention used in the
                                          documentation for this register or
                                          field. */
            reg_role_t role;           /* Role of this register in the ABI/HW. */
            bool memory_mapped;        /* True if the register is memory mapped. */
            uint64 offset;             /* Offset into the bank for memory mapped
                                          registers. */
            bool catchable;            /* True if Core_Control_Register_Write and
                                          Core_Control_Register_Read are triggered
                                          when this register is written or read. */
            int msb, lsb;              /* Most and least significant bit of the
                                          register or field. Always given in le
                                          bitorder. For groups msb == -1 and
                                          lsb == 0. */
            int regsize;               /* Number of bits in the register, or the
                                          register this field is a part of. */
            int reg_id;                /* For registers and fields the id to pass
                                          to the get and set methods to access the
                                          register's value. Fields have the same
                                          reg_id as the register they are a part
                                          of. Not valid for groups.*/
    } description_t;

    SIM_INTERFACE(describe_registers) {
            const description_t *(*first_child)(
                    conf_object_t *NOTNULL obj, const description_t *parent);
            const description_t *(*next_description)(
                    conf_object_t *NOTNULL obj, const description_t *prev);
            void (*free_description)(conf_object_t *NOTNULL obj,
                                     const description_t *desc);
            const named_value_t *(*first_named_value)(
                    conf_object_t *NOTNULL obj, const description_t *parent);
            const named_value_t *(*next_named_value)(
                    conf_object_t *NOTNULL obj, const named_value_t *prev);
            void (*free_named_value)(conf_object_t *NOTNULL obj,
                                     const named_value_t *nv);
            void (*get)(conf_object_t *NOTNULL obj, int reg_id, buffer_t dest);
            void (*set)(conf_object_t *NOTNULL obj, int reg_id, bytes_t value);
    };
    
    #define DESCRIBE_REGISTERS_INTERFACE "describe_registers"
    

    9.2 Simics API Functions

    This section lists Simics API functions that a processor model may need to use beyond what is described in other parts of this document. Simics API SIM_register_clock is described in API Reference Manual.

    NAME
    VT_check_async_events — check for asynchronous events
    SYNOPSIS
    bool
    VT_check_async_events();
    

    DESCRIPTION
    Check if any async events are pending and if so, make the current executing object exit in order for them to be handled. Return nonzero if there are pending events.

    The Simics platform will check for asynchronous events between invocations of the run method in the execute. If significant time passes between such invocations, which will typically be the case unless there are multiple simulated CPUs that are switched between, then the implementor of execute needs to either call this method or exit pre-maturely from run to allow asynchronous events to be handled. If neither is performed, then interactive performance will suffer as user input would be waiting significant time before being processed.

    If only the async event state is requested, the faster VT_async_events_pending should be used instead.

    EXECUTION CONTEXT
    Cell Context

    NAME
    VT_new_code_block — inform platform of new code block
    SYNOPSIS
    void
    VT_new_code_block(void *start, size_t len);
    

    DESCRIPTION
    This function informs the Simics platform that there is a len bytes block at start that can be executed from. The call should be made before the passed code area is executed from. This information is used by Simics to communicate with systems like Pin or Valgrind that do not automatically detect run-time generated code. If modifications are done to a block, then a new call to this function is needed to inform the platform of that.
    EXECUTION CONTEXT
    Cell Context

    NAME
    VT_set_object_clock — set clock association for object
    SYNOPSIS
    void
    VT_set_object_clock(conf_object_t *NOTNULL obj, conf_object_t *clock);
    

    DESCRIPTION
    The simulation infrastructure keeps track of clock associations for every object. For most objects, this is initialized through the queue attribute.

    An object that is itself a clock needs to call this function to initialize the clock coupling to itself. The call to initialize the coupling should be made from the init method registered for the class in its class_info_t (or init_object if registered using class_data_t).

    EXECUTION CONTEXT
    Global Context

    NAME
    VT_clock_frequency_about_to_change — inform before clock frequency change
    SYNOPSIS
    void
    VT_clock_frequency_about_to_change(conf_object_t *obj);
    

    DESCRIPTION
    To be called by a clock prior to a clock frequency change, with events and cycles reflecting the frequency before the change.
    EXECUTION CONTEXT
    Cell Context

    NAME
    VT_clock_frequency_change — inform after clock frequency change
    SYNOPSIS
    void
    VT_clock_frequency_change(conf_object_t *obj, uint64 cycles_per_second);
    

    DESCRIPTION
    To be called by a clock when the clock frequency has changed, with events and cycles reflecting the frequency after the change.
    EXECUTION CONTEXT
    Cell Context

    NAME
    VT_stop_event_processing — stop event processing
    SYNOPSIS
    void
    VT_stop_event_processing(conf_object_t *clock);
    

    DESCRIPTION
    This method is to be called by a clock when it has received a stop request through the execute interface and the clock is about to return from the run method in the execute interface.

    In the future, the simulation framework may keep track of this thus relieving the clock from the duty of having to call this method.

    EXECUTION CONTEXT
    Cell Context

    10 Python API

    This chapter contains a description of the part of the Simics API that is available in Python only. The Python modules described here may contain functions, classes, types and similar than are not documented although visible when inspecting the modules. If not documented, they are internal to Simics and not part of the supported API.

    10.1 Simics Types in Python

    When writing code in Python, almost all Simics API functions can be used. Since not all C/C++ types are available in Python, Simics supplies the following special type mappings.

    C/C++ Python
    attr_value_t (string) str (a Python string)
    attr_value_t (integer) int or long
    attr_value_t (floating) float
    attr_value_t (list) list
    attr_value_t (data) tuple of integers (bytes)
    attr_value_t (nil) None
    attr_value_t (object) An object from the conf namespace.
    attr_value_t (dict) dict
    attr_value_t (boolean) bool
    conf_class_t * A conf_class_t object
    conf_object_t * An object from the conf namespace

    10.2 Command Line Interface

    CLI Arguments Types

    addr_t

    Accepts a target machine address, optionally with an address space prefix, such as v: for virtual addresses or p: for physical.

    bool_t(true_str, false_str)

    Generator function for boolean arguments. A boolean argument accepts the strings "TRUE" and "FALSE", as well as boolean integers (that is, the values 0 and 1). In addition, if the optional strings true_str and false_str are given, the boolean argument will accept them as well. The argument passes True or False to the command function depending on which string (or value) was given.

    filename_t(dirs=False, exist=False, simpath=False, checkpoint=False)

    Generator function for filename arguments. If the dirs argument is false (which is default), no directories will be accepted. The exist flag, when set, forces the file to actually exist. If simpath is true, files will be checked for existence using SIM_lookup_file(), searching the Simics search path. simpath implies exist. On Windows, if Cygwin path conversion is performed (see SIM_native_path() for details), the filename will be converted to host native format. The checkpoint flag will constrain the argument to checkpoints, and treat existing checkpoints as opaque entities.

    flag_t

    Passes True to command function when flag is provided, False when flag is not provided.

    float_t

    Accepts floating-point numbers.

    int16_t

    Accepts any unsigned integer that fits in 16 bits, modulo-reducing values outside into that range.

    int32_t

    Accepts any unsigned integer that fits in 32 bits, modulo-reducing values outside into that range.

    int64_t

    Accepts any unsigned integer that fits in 64 bits, modulo-reducing values outside into that range.

    int8_t

    Accepts any unsigned integer that fits in 8 bits, modulo-reducing values outside into that range.

    int_t

    Accepts any integer (regardless of size).

    integer_t

    Accepts any unsigned integer that fits in 64 bits, modulo-reducing values outside into that range.

    ip_port_t

    Accepts integers that are valid IP port numbers (that is, integers between 0 and 65535 inclusive).

    list_t

    Accepts a comma separated list of CLI types. Can also be given to any CLI argument that accepts more than one value as input.

    nil_t

    Nil argument. Accepts NIL, zero or the empty string, and passes None to the command function. Not so usable by itself, but see e.g. poly_t.

    obj_t(desc, kind = None, want_port = False)

    Returns an argument which accepts any object.

    desc is the string returned as a description of the argument. kind can be used to limit the accepted objects to only allow objects of a certain kind. This parameter can either be a class name that the object should be an instance of, or the name of an interface that the object must implement, or a tuple of kinds. want_port indicates whether it should be allowed to specify an object and a port name, separated with a colon. If a port is wanted, the argument will be a list [obj, port] instead of only the object.

    poly_t(desc, type1, type2, ...)

    Generates an argument with the given description that will match any of the given types; they will be tried one by one, in the order specified, and the first one that accepts the input will be used.

    range_t(min, max, desc, modulo=False)

    Returns an argument which accepts any integer x between min and max inclusively. desc is the string returned as a description of the argument.

    Values outside the interval cause an error to be signalled if modulo is false, and a modulo-reduction to the specified interval otherwise.

    sint16_t

    Accepts any signed integer that fits in 16 bits, modulo-reducing values outside into that range.

    sint32_t

    Accepts any signed integer that fits in 32 bits, modulo-reducing values outside into that range.

    sint64_t

    Accepts any signed integer that fits in 64 bits, modulo-reducing values outside into that range.

    sint8_t

    Accepts any signed integer that fits in 8 bits, modulo-reducing values outside into that range.

    str_t

    Accepts any one word or quoted string.

    string_set_t(strings)

    Accepts only strings from the given set. strings can be any iterable, such as a tuple, list, or set, in which case the return value is the exact string the user gave; or a dictionary mapping acceptable user input strings to return values.

    The optional parameter visible is a list of strings. If given, only strings in this list will be suggested by the expander.

    uint16_t

    Accepts any unsigned integer that fits in 16 bits, modulo-reducing values outside into that range.

    uint32_t

    Accepts any unsigned integer that fits in 32 bits, modulo-reducing values outside into that range.

    uint64_t

    Accepts any unsigned integer that fits in 64 bits, modulo-reducing values outside into that range.

    uint8_t

    Accepts any unsigned integer that fits in 8 bits, modulo-reducing values outside into that range.

    uint_t

    Accepts any unsigned (that is, non-negative) integer (regardless of size).

    CLI Classes and Functions

    cli.CliError

    NAME
    CliError — error in CLI command
    SYNOPSIS
    CliError(args)

    DESCRIPTION
    This exception can be raised whenever a command can not complete successfully.

    cli.arg

    NAME
    arg — class defining a command argument
    SYNOPSIS
                arg(handler, name = "", spec = "1", default = None,
                data = None, doc = "", expander = None, pars = [])

    DESCRIPTION
    Define a CLI command argument when using new_command. A complete explanation of new_command and arg is available in Simics Model Builder User's Guide, in the Adding New Commands chapter.

    cli.command_quiet_return

    NAME
    command_quiet_return — suppress interactive messages from commands
    SYNOPSIS
    command_quiet_return(value)

    DESCRIPTION
    Use this class to return from a command that returns a value but should not print anything when used interactively.

    value should either be the value returned, or a function taking no arguments that returns the actual value.

    Note that value can only be of types directly supported by CLI.

    SEE ALSO
    cli.command_return

    cli.command_return

    NAME
    command_return — return interactive messages from commands
    SYNOPSIS
                command_return(message = None, value = None)

    DESCRIPTION
    Use this class to return from a command that returns one value (value) but (may) print something else (message) when run interactive.

    message and value may both be functions that take no arguments and return the message (a string) or a value, respectively.

    If it is a function, message is only evaluated if needed.

    Note that value (or, when a function, its return value) can only be of types directly supported by CLI.

    SEE ALSO
    cli.command_quiet_return, cli.command_verbose_return

    cli.command_verbose_return

    NAME
    command_verbose_return — always print return messages from commands
    SYNOPSIS
    command_verbose_return(message = None, value = None)

    DESCRIPTION
    Use this class to return from a command that returns a value or message that should be printed even when used non-interactively, but not when used in an expression.

    The value and message parameters are identical to the same as for cli.command_return.

    SEE ALSO
    cli.command_return

    cli.get_available_object_name()

    NAME
    get_available_object_name — return a non-allocated object name
    SYNOPSIS
    get_available_object_name(prefix)

    DESCRIPTION
    Return an object name suitable for creating a new object (i.e., that has not been used yet) by adding a suffix to prefix.

    cli.get_component_object()

    NAME
    get_component_object — return an object in a component
    SYNOPSIS
    get_component_object(cmp_obj, slot)

    DESCRIPTION
    Return the object named slot inside the cmp_obj component. The slot parameter is the name by which the component knows the object, not the global name of the object.

    The function will raise a CliError if the object can not be found in the component.

    RETURN VALUE
    object or pre-object

    cli.global_cmds

    NAME
    global_cmds — Namespace with functions to run global CLI commands
    SYNOPSIS
    global_cmds.wrapper_function(...)

    DESCRIPTION
    The namespace provides wrapper Python functions to run global Simics CLI commands. A wrapper function name is usually the same as a name of the command it executes with hyphens replaced with underscores. The parameters of the wrapper functions are the same as of the corresponding command (again, with hyphens replaced with underscores). Command flags (the names of the corresponding function parameters start with an underscore) could be passes as Python Boolean values. In the rare cases that a wrapper function name or a wrapper function parameter name turns out to be a Python keyword, the _cmd suffix is added to the wrapper function name and the function parameter gets the _ suffix. Wrapper functions return the value returned by the command which they execute.

    Please consult the docstring of the wrapper function and the respective command documentation for the information about function arguments and the returned value.

    cli.interactive_command()

    NAME
    interactive_command — check if current command is run interactively
    SYNOPSIS
    interactive_command()

    DESCRIPTION
    Returns true if the current command was run interactively by the user and false if run from a script. This function may only be called by CLI commands.

    cli.new_command()

    NAME
    new_command — define a new CLI command
    SYNOPSIS
    new_command(name, fun, args = [], **kwargs)

    DESCRIPTION
    Define a new CLI command. A complete explanation of new_command and its parameters is available in Simics Model Builder User's Guide, in the Adding New Commands chapter.

    cli.new_info_command()

    NAME
    new_info_command — define a new info command
    SYNOPSIS
    new_info_command(cls, get_info, ctype = None, doc = None)

    DESCRIPTION
    Define a new info command for a given object. cls is the class for which the info command should be registered. get_info is a function returning the information to be printed. get_info() should return a data structure of the following kind:
      [(SectionName1, [(DataName1.1, DataValue1.1),
                       (DataName1.2, DataValue1.2), ...]),
       (SectionName2, [(DataName2.1, DataValue2.1),
                       (DataName2.2, DataValue2.2), ...]),
       ...]

    Each section will be printed separately. Each piece of data will be printed on one line. If no sections are necessary, just provide None as the only section's name, followed by the list of data.

    SEE ALSO
    cli.new_status_command

    cli.new_status_command()

    NAME
    new_status_command — define a new status command
    SYNOPSIS
    new_status_command(cls, get_status, ctype = None, doc = None)

    DESCRIPTION
    Define a new status command for a given object. cls is the class for which the status command should be registered. get_status is a function returning the information to be printed. get_status() should return a data structure of the same kind as in new_info_command().
    SEE ALSO
    cli.new_info_command

    cli.new_tech_preview_command()

    NAME
    new_tech_preview_command — define a new CLI tech preview command
    SYNOPSIS
    new_tech_preview_command(name, feature, fun, args=[], doc="", **kwargs)

    DESCRIPTION
    Define a new tech preview CLI command.

    cli.new_unsupported_command()

    NAME
    new_unsupported_command — define a new unsupported CLI command
    SYNOPSIS
    new_unsupported_command(name, feature, fun, args = [], doc = "", **kwargs)

    DESCRIPTION
    Define a new unsupported CLI command.

    cli.number_str()

    NAME
    number_str — return a ready-to-print representation of a number
    SYNOPSIS
    number_str(val, radix=None, group=None, use_prefix=True, precision=1)

    DESCRIPTION
    Return a ready-to-print representation of the number val in a given base (radix) or the current base by default, using the current settings for number representation as set by the output-radix and digit-grouping commands.

    The default digit grouping can be overridden with the group parameter, where 0 means no grouping. The radix prefix can be removed by specifying use_prefix as False.

    The minimum number of digits to be printed is specified by precision. If precision is negative, the precision is taken to be zero. Regardless of the radix, a value of zero with zero precision will always return the empty string.

    Negative numbers that fit in a signed 64-bit integer are treated as such. Other negative numbers are prefixed with a minus ("-").

    RETURN VALUE
    A string representing the number.
    SEE ALSO
    cli.str_number

    cli.object_expander()

    NAME
    object_expander — standard expander for an object argument
    SYNOPSIS
    object_expander(kind)

    DESCRIPTION
    For command writing: standard expander that can be use to provide argument completion on all objects of a given class or matching a given interface (kind).

    For example, to expand a string with the list of processor available in the machine, you would write:

      arg(str_t, "cpu", expander =  object_expander("processor_info"))
    

    To expand a string to all gcache objects:

      arg(str_t, "cache", expander = object_expander("gcache"))
    

    cli.quiet_run_command()

    NAME
    quiet_run_command — run a CLI command and return output
    SYNOPSIS
    quiet_run_command(text, output_mode = output_modes.formatted_text)

    DESCRIPTION
    Runs a CLI command, or a CLI expression, as if it has been entered at the prompt. Errors are reported using CliError exception.

    The quiet_run_command function is similar to run_command but returns a tuple with the command return value as first entry, and the command output text as the second. Please note that sometimes unrelated output might be included, e.g., for commands that advance the virtual time or in some other way may allow other commands to run in parallel with them.

    Set 'output_mode' to one of the output modes:

    output_modes.regular
    formatted text with Simics-internal markup
    output_modes.formatted_text
    formatted text without markup
    output_modes.unformatted_text
    unformatted text without markup

    cli.register_command_category()

    NAME
    register_command_category — register a command category
    SYNOPSIS
    register_command_category(name = None)

    DESCRIPTION
    Register a command category for the 'type' argument given to the new_command function. Command categories are optional but may be useful if many commands are defined for a particular use case that is of general interest.

    name should be at least 3 characters long and preferably just one capitalized word, a noun.

    Notice: Do not register any command category for a class, as those are listed on the class itself.

    Invoke this function without any argument to print the standard categories, assuming no modules or targets have been loaded.

    cli.run_command()

    NAME
    run_command — run a CLI command
    SYNOPSIS
    run_command(text)

    DESCRIPTION
    Runs a CLI command, or a CLI expression, as if it has been entered at the prompt. Errors are reported using CliError exception, and any return value from the command is returned by this function to Python.

    Use quiet_run_command if you need to suppress or catch messages printed.

    cli.simenv

    NAME
    simenv — CLI variable namespace
    SYNOPSIS
    simenv.variable

    DESCRIPTION
    The simenv namespace provides access to the CLI variables in the Simics Python interpreter. If the variable $foo was defined in CLI, simenv.foo will represent the same variable in Python.

    Running del simenv.foo will unset that variable. The return value from the dir function will also include defined variables. The repr function will return the dictionary of variable and value pairs as a string.

    cli.str_number()

    NAME
    str_number — convert a string to a number
    SYNOPSIS
    str_number(text)

    DESCRIPTION
    Converts a string returned from number_str back to an integer.

    Raises ValueError for invalid arguments.

    RETURN VALUE
    A number representing the string.
    SEE ALSO
    cli.number_str

    10.3 Configuration

    pyobj Python Module

    pyobj.Attribute

    NAME
    Attribute — a Simics attribute
    DESCRIPTION
    The pyobj.Attribute class defines an attribute that will be registered for the containing ConfObject class. The attribute will be registered with Simics using the SIM_register_attribute function. See documentation for SIM_register_attribute for detailed information about attributes.

    The arguments to SIM_register_attribute is taken from the class members. The attrattr member is an attr_attr_t type and its default value is Sim_Attr_Optional. The attrtype member is a string defining the type of the attribute, default value is 'a'.

    The class methods named getter and setter will be used as get_attr and set_attr functions when registering the attribute. The methods are optional. An attribute without a getter can not be read. An attribute without a setter can not be written.

    The attribute description is the same as the Python class description.

    The _initialize method can be defined if special initialization behavior is required. This can for instance be used to set the default value.

    EXAMPLE
    class wee(pyobj.Attribute):
        """Documentation for the attribute goes here."""
        attrattr = simics.Sim_Attr_Pseudo
        attrtype = 'i'
        def _initialize(self):
            self.val = 4711
        def getter(self):
            self.val += 3
            return self.val
        def setter(self, val):
            self.val = val

    SEE ALSO
    pyobj.SimpleAttribute, pyobj.ClassAttribute, pyobj.ConfObject

    pyobj.ClassAttribute

    NAME
    ClassAttribute — a Simics class attribute
    DESCRIPTION
    The pyobj.ClassAttribute class defines an attribute that will be registered for the containing ConfObject class. The attribute will be registered with Simics using the SIM_register_class_attribute function. See documentation for SIM_register_class_attribute for detailed information about class attributes.

    The value stored in the class should always be stored in the attribute named val. This is to avoid problems when a class that defines a pyobj.Attribute class is inherited by more than one class.

    The pyobj.ClassAttribute class is very similar to the pyobj.Attribute class. See the documentation for the pyobj.Attribute class for how to use this class.

    EXAMPLE
    class wee(pyobj.ClassAttribute):
        """Documentation for the attribute goes here."""
        attrtype = 'i'
        val = 4711
        @classmethod
        def getter(cls): return cls.val
        @classmethod
        def setter(cls, val): cls.val = val

    SEE ALSO
    pyobj.Attribute, pyobj.ConfObject

    pyobj.ConfObject

    NAME
    ConfObject — a Simics configuration object
    DESCRIPTION
    The pyobj.ConfObject class defines a new Simics class using the SIM_register_class function. You could call SIM_register_class and all the related functions for attribute and interface registration yourself, but ConfObject will make your code much more concise.

    The name of the Simics class is identical to the Python class. The class description is the same as the Python class description.

    The class implements the methods _initialize, _finalize, _pre_delete, _info, and _status. All of these methods can be overridden if required.

    The _initialize method is called when an object of the class is instantiated. The _finalize method is called when the object is finalized. The _pre_delete method is called right before an object of the class is deleted.

    The _info and _status methods provide data for the class's info and status commands; the format of their return value is documented with cli.new_info_command and cli.new_status_command.

    If you need to get hold of the Simics conf_object_t object associated with a ConfObject instance—for example, in order to call a Simics API function—you can find it in the obj member.

    The pyobj.ConfObject class can contain inner classes that define attributes, interfaces, etc. See pyobj.Port, pyobj.Attribute, pyobj.ClassAttribute, and pyobj.Interface for more documentation. An inner class has a reference to the class that contains it in its _up member.

    By default, a Simics class is registered automatically whenever a subclass of pyobj.ConfObject is declared. Sometimes this is not desirable; e.g., the class may be a base class, or you may want to allow importing the containing Python file without side-effects. The automatic registration of a Simics class can then be suppressed by setting the member _do_not_init to object(). That will cause it to not be registered as a Simics class (but its subclasses will be, unless they too employ the same trick).

    The class method register may be called once on each pyobj.ConfObject subclass, to register the Simics class. For a class that doesn't suppress automatic registration, the method currently does nothing.

    In future Simics versions, a Simics class will no longer be registered automatically, and an explicit call to the register method will be required for that.

    The _class_kind member tells Simics whether objects of this class should be saved when a checkpoint is created. The value is passed to SIM_register_class, as the kind field of the class_data_t structure. The default value is Sim_Class_Kind_Vanilla. See the documentation of SIM_register_class for details.

    EXAMPLE
    class foo(pyobj.ConfObject):
        """This is the long-winded documentation for this Simics class.
        It can be as long as you want."""
        _class_desc = 'One-line doc for the class'
    
        def _initialize(self):
            super()._initialize()
            self.my_val = 4711
    
        def _info(self):
             return [("Python device info", [("my_val", self.my_val)])]
    
        def _status(self):
             return [("Python device status",
                      [("woot", self.woot.val),
                       ("signal", self.signal.val)])]
    
        class woot(pyobj.SimpleAttribute(0, 'i|n')):
            """A four-letter attribute"""
    
        class lost(pyobj.Attribute):
            """A pseudo attribute"""
            attrattr = simics.Sim_Attr_Pseudo
            def getter(self):
                return self._up.my_val
    
        class signal(pyobj.Interface):
            def signal_raise(self): self.val = True
            def signal_lower(self): self.val = False
            def _initialize(self): self.val = False

    pyobj.Event

    NAME
    Event — a Simics event
    DESCRIPTION
    pyobj.Event defines an event that will be registered for the containing ConfObject class. Internally, registration is done with SIM_register_event; see the documentation for that API function for detailed information.

    Events are posted with the post(clock, data, <duration>) method. clock determines which clock the event is posted on, and data is the event data. The duration is the number of seconds, cycles, or steps until the event triggers, specified with the appropriate keyword argument:

    ev.post(a_clock, some_data, seconds=4.711)
    ev.post(a_clock, some_data, cycles=4711)
    ev.post(a_clock, some_data, steps=4711)
    

    Events can be cancelled before they trigger with either cancel_time(clock, match_fun) or cancel_step(clock, match_fun) (depending on whether the event duration was specified in steps or not). The match_fun argument is optional: if given, it should be a function that accepts an event data parameter, and returns true for the events that should be cancelled; if not given, all events are cancelled.

    A subclass may define the following methods:

    callback(data)
    Called when the event triggers. Overriding this method is not optional.
    destroy(data)
    Called when the event is removed from the queue without being called. The method is not allowed to use any event API calls; it is mainly intended for freeing event data.
    get_value(data) and set_value(val)
    Converts the given event data to an attr_value_t value, and the other way around. If the event carries no data that needs checkpointing, you may omit these methods.
    describe(data)
    Called to generate a human-readable description of the event to be used in the print-event-queue command. If you do not supply this method, the event's name will be used.

    Additionally, it may set the flags parameter to Sim_EC_Notsaved, if the event should not be checkpointed. In this case, neither get_value nor set_value should be defined.

    EXAMPLE
    class foo(pyobj.ConfObject):
        class ev1(pyobj.Event):
            def callback(self, data):
                do_something(data)
        class ev2(pyobj.Event):
            def callback(self, data):
                self.do_something_else(data)
            def get_value(self, data):
                return str(data)
            def set_value(self, val):
                return int(val)
            def describe(self, data):
                return 'ev2 with %s' % data
        class ev3(pyobj.Event):
            flags = simics.Sim_EC_Notsaved
            def callback(self, data):
                self._up.do_this_third_thing(data)

    SEE ALSO
    SIM_register_event, pyobj.ConfObject

    pyobj.Interface

    NAME
    Interface — a Simics interface
    DESCRIPTION
    The pyobj.Interface class implements a Simics interface for the containing ConfObject class. The interface is registered using the SIM_register_interface function. The interface name is taken from the class name.

    The _initialize method can be overridden if special initialization behavior is required.

    To implement port interfaces instead of regular interfaces, place one or more pyobj.Interface subclasses inside a pyobj.Port class.

    EXAMPLE
    class signal(pyobj.Interface):
        def signal_raise(self): self.val = True
        def signal_lower(self): self.val = False
        def _initialize(self): self.val = False

    SEE ALSO
    pyobj.Port, pyobj.ConfObject

    pyobj.Port

    NAME
    Port — a Simics port
    DESCRIPTION
    To have your ConfObject-based Simics object implement port interfaces, put a subclass of pyobj.Port as an inner class of your ConfObject, and put one or more pyobj.Interface subclasses inside it. The pyobj.Interface subclasses will work just as if they were at the top level, except that they will be registered with SIM_register_port_interface instead of SIM_register_interface.

    The _initialize method can be overridden if special initialization behavior is required.

    EXAMPLE
    class wee(pyobj.Port):
        class signal(pyobj.Interface):
            def signal_raise(self): self.val = 2
            def signal_lower(self): self.val = 1
            def _initialize(self): self.val = 0

    SEE ALSO
    pyobj.Interface, pyobj.ConfObject

    pyobj.PortObject

    NAME
    PortObject — a Simics port object
    DESCRIPTION
    The pyobj.PortObject class defines a port object class that will be registered as a port object for the containing ConfObject class.

    The port object will be registered with the name "port.<name>", but this can be changed by defining namespace to something other than "port". One possibility is the empty string.

    If classname is set, then the port object will be an instance of this external class rather than defining the class locally. The external class cannot be modified by adding e.g. an interface definition inside the PortObject definition.

    EXAMPLE
    class portname(pyobj.PortObject):
        """Documentation for the port object goes here."""
        class signal(pyobj.Interface):
            def signal_raise(self): self.val = 2
            def signal_lower(self): self.val = 1
            def _initialize(self): self.val = 0

    SEE ALSO
    pyobj.ConfObject

    pyobj.SimpleAttribute()

    NAME
    SimpleAttribute — a simple Simics attribute
    SYNOPSIS
    SimpleAttribute(init, type = 'a', attr = simics.Sim_Attr_Optional)

    DESCRIPTION
    The pyobj.SimpleAttribute function returns a new subclass of pyobj.Attribute, with predefined getter and setter functions that simply store and retrieve the value without further side effects. The value is stored in the val member.

    The init argument is the initial value, type is the attribute type string, attr is the attribute type. If init is callable, it will be called, and the return value is the initial value; otherwise, init itself is the initial value.

    The attribute value is stored in the val member of the class.

    RETURN VALUE
    pyobj.Attribute class
    EXAMPLE
    class wee(pyobj.SimpleAttribute(17, 'i')):
        """Documentation for the attribute goes here."""

    SEE ALSO
    pyobj.Attribute, pyobj.ConfObject

    comp Python Module

    comp.ConfigAttribute

    NAME
    ConfigAttribute — component configuration attribute
    DESCRIPTION
    The ConfigAttribute class inherits the pyobj.Attribute class. The ConfigAttribute class just adds the special property to the pyobj.Attribute class that it is a config attribute.

    A config attribute defines how the component should be configured. Therefore, all config attributes are also arguments to the new- and create- commands that are used to instantiate the component.

    Because of this, the config attribute must always be documented and the default value of the attrattr member is Sim_Attr_Optional.

    The ConfigAttribute class contains the valid member, which is a list of valid values for the config attribute. The list gives the user a hint about valid values when creating a component. There is no check that the value written to the attribute is a value in the list of valid values. The list of valid value(s) does not need to contain the default initial value for the config attribute, but it usually does. The valid list should at least contain one valid value even if several values are valid.

    EXAMPLE
    class foo(ConfigAttribute):
        """The foo attribute."""
        valid = [667, 4711]
        def _initialize(self): self.val = 4711
        def getter(self): return self.val
        def setter(self, val): self.val = val

    SEE ALSO
    pyobj.Attribute

    comp.SimpleConfigAttribute()

    NAME
    SimpleConfigAttribute — simple component configuration attribute
    SYNOPSIS
    SimpleConfigAttribute(init, type, attr = simics.Sim_Attr_Optional, val = [])

    DESCRIPTION
    The pyobj.SimpleConfigAttribute method creates an attribute using the comp.ConfigAttribute class. The purpose of the method is to make it easier and faster to create a simple config attribute.

    A config attribute defines how the component should be configured. Therefore, all config attributes are also arguments to the new- and create- commands that are used to instantiate the component.

    The init argument is the initial value for the attribute. The type of the attribute is defined by the type string (currently objects 'o' and dictionaries 'D' are not supported). The attr argument sets the attribute kind. The default value for attr is Sim_Attr_Optional. The valid value(s) for the comp.ConfigAttribute class is set by the val argument. See the documentation for SIM_register_attribute for more information about the arguments.

    RETURN VALUE
    comp.ConfigAttribute class
    EXAMPLE
    class cpu_frequency(SimpleConfigAttribute(
            None, 'i', simics.Sim_Attr_Required)):
        """Processor frequency in MHz."""

    SEE ALSO
    pyobj.Attribute, pyobj.ConfObject

    comp.StandardComponent

    NAME
    StandardComponent — base class for components
    DESCRIPTION
    The StandardComponent class is the base class for components written in Python. It is a subclass of pyobj.ConfObject.

    The class will automatically register the required component attributes. Any attribute may be overridden; however, overriding the internal attributes is not recommended.

    The automatically registered attributes are:

    basename
    String to prepend to component name when creating components when not specifying name.
    component_icon
    String with the name of the component icon.
    component_queue
    The default queue object for this component.
    top_level
    Default set to False.
    system_icon
    The system icon.
    machine_icon
    The machine icon.
    cpu_list
    List of processors in the component tree.
    static_slots
    Internal.
    dynamic_slots
    Internal.
    object_list
    Internal.
    object_prefix
    Internal.
    top_component
    Internal.
    instantiated
    Internal.
    pending_cell_object_factories
    Internal.
    config_attributes
    Internal.
    system_info
    Internal.
    components
    Internal.
    domain
    Internal.

    The class will automatically implement the component interface. The individual methods of this interface are user-overridable.

    Components will automatically get new- and create- commands that can be used to create and instantiate the component. It is possible to override this by setting _no_create_command or _no_new_command to object() to avoid to automatically get create- or new- commands.

    EXAMPLE
    class my_comp(StandardComponent):
        """The my_comp component."""
        _class_desc = "my_comp"
    
        class bar(SimpleConfigAttribute(
                None, 'i', simics.Sim_Attr_Required)):
            """My favorite bar."""
    
    class my_comp(StandardComponent):
        """The my_comp component."""
        _class_desc = "my_comp"
        _no_create_command = object()

    SEE ALSO
    pyobj.ConfObject

    comp.StandardComponent Methods

    comp.StandardComponent.add_component()

    NAME
    add_component — add sub component to component
    SYNOPSIS
    add_component(self, slot, cls, attr, name = '')

    DESCRIPTION
    Add a subcomponent or arrays of subcomponents to the component. The subcomponent(s) will be created immediately when the method is called.

    The slot argument is the slot name concatenated with a nested array string, defining the number of subcomponents to create. Setting slot to foo will create one subcomponent in the slot foo, setting slot to foo[3] will create an array of three subcomponents in the slot foo, setting slot to foo[3][2] will create an array of three arrays of two arrays with subcomponents in the slot foo.

    The cls is the component class, attr is arguments to the component, and name is an optional name.

    RETURN VALUE
    arrays of conf_object_t component object

    comp.StandardComponent.add_connector()

    NAME
    add_connector — add connector to component
    SYNOPSIS
    add_connector(self, slot, type, hotpluggable, required,
                  multi, direction)

    DESCRIPTION
    Add a connector or nested array of connectors to the component. The connector(s) will be created immediately when the method is called.

    The slot argument is the slot name concatenated with a nested array string, defining the number of connectors to create. Setting slot to foo will create one connector in the slot foo, setting slot to foo[3] will create an array of three connectors in the slot foo, setting slot to foo[3][2] will create an array of three arrays of two arrays with connectors in the slot foo.

    The type is the type of connection as a string, hotpluggable is True or False depending on whether the connector is hot-pluggable, required is True if the connector must be connected before the component is instantiated, multi is True if the connector supports multiple connections, direction is a connector_direction_t which is up, down, or any.

    RETURN VALUE
    arrays of conf_object connector objects
    SEE ALSO
    comp.StandardComponent.get_slot

    comp.StandardComponent.add_pre_obj()

    NAME
    add_pre_obj — add pre_conf_obj to component
    SYNOPSIS
    add_pre_obj(self, slot, cls, name = '', **attr)

    DESCRIPTION
    Add pre conf objects to the component. The pre conf objects will be converted to regular conf objects when the component is instantiated.

    The slot argument is the slot name concatenated with a nested array string, defining the number of pre objects to create. Setting slot to foo will create one pre object in the slot foo, setting slot to foo[3] will create an array of three pre objects in the slot foo, setting slot to foo[3][2] will create an array of three arrays of two arrays with pre objects in the slot foo. The cls argument is the type of object class to create. The name argument is deprecated. The attr argument is optional attribute values for the object(s).

    RETURN VALUE
    arrays of pre conf objects

    comp.StandardComponent.add_slot()

    NAME
    add_slot — add slot to component
    SYNOPSIS
    add_slot(self, slot, val)

    DESCRIPTION
    Add a slot to the component. slot is the slot name and val is the value. The value must be a conf object, a pre conf object, or None, or nested lists of these types.
    RETURN VALUE
    new slot value, i.e. val

    comp.StandardComponent.connect()

    NAME
    connect — connect connectors
    SYNOPSIS
    connect(self, cnt0, cnt1)

    DESCRIPTION
    Connect two connectors cnt0 and cnt1. The connectors must be connector objects. A CompException exception will be raised if the connection failed.

    comp.StandardComponent.copy_connector()

    NAME
    copy_connector — copy connector to component
    SYNOPSIS
    copy_connector(self, slot, src)

    DESCRIPTION
    Copy connectors from another component. The slot argument is the new slot name for the connector in this component. The src argument is the name of the slot with connectors to copy. The src can be a relative slot name, see the get_slot method.
    RETURN VALUE
    arrays of conf_object connector objects
    SEE ALSO
    comp.StandardComponent.get_slot

    comp.StandardComponent.del_slot()

    NAME
    del_slot — delete slot in component
    SYNOPSIS
    del_slot(self, slot)

    DESCRIPTION
    Delete slot in component. The slot argument is the slot name. The function returns the slot value if the slot exists. All connectors in the slot will be converted to pre conf objects and the original connectors will be deleted when returning the slot value. A CompException exception will be raised if the slot does not exist, the slot contains non connector conf objects, or the slot contains connectors that have been copied with the copy_connector method. Slots with sub components can not be deleted.

    comp.StandardComponent.get_slot()

    NAME
    get_slot — get slot from component
    SYNOPSIS
    get_slot(self, slot)

    DESCRIPTION
    Get a slot from the component. slot is the slot name. slot can be a slot in this component or a hierarchical slot; e.g., looking up foo.bar will return the slot bar from the component in slot foo from this component. If the lookup fails, a CompException exception will be raised.
    RETURN VALUE
    slot value

    comp.StandardConnectorComponent

    NAME
    StandardConnectorComponent — convenience class for connector components
    DESCRIPTION
    The StandardConnectorComponent is a convenience class for connector components. It is a subclass of comp.StandardComponent and implements the component_connector interface.
    SEE ALSO
    comp.StandardComponent

    comp.StandardConnectorComponent Methods

    comp.StandardConnectorComponent.add_connector()

    NAME
    add_connector — create a connector component
    SYNOPSIS
    add_connector(self, slot, cls)

    DESCRIPTION
    Create a connector component.

    The slot argument is the slot name for the connector.

    The cls argument is an instance of a connector class.

    RETURN VALUE
    the conf_object connector component

    Checkpoints

    update_checkpoint.SIM_register_class_update()

    NAME
    SIM_register_class_update — register a class update function
    SYNOPSIS
    SIM_register_class_update(build_id, classname, function)

    DESCRIPTION
    Register the class update function function for class classname, to be run when updating a checkpoint to build-id build_id.

    The function acts on a single object of a given class. It will be called for all matching objects with the current object as argument. It doesn't need to return anything, however it can't create or destroy objects, only change the attributes of the object it got as parameter, except the object name.

    update_checkpoint.SIM_register_generic_update()

    NAME
    SIM_register_generic_update — register a generic update function
    SYNOPSIS
    SIM_register_generic_update(build_id, function)

    DESCRIPTION
    Register the generic update function function to be run when updating a checkpoint to build-id build_id. The function acts on one or several objects of various classes, and may rename, create or destroy objects. When the checkpoint reaches the required build-id, the function will be called once with the complete set of objects that constitute the checkpoint as a parameter. It is expected to return three lists of pre_conf_objects: (deleted objects, changed objects, added objects). Deleted objects must have been removed from the configuration, changed objects can have any attribute changed (including their class or their name). Added objects must have been added to the configuration.

    When renaming an object, the function is expected to remove the object from the checkpoint set under its old name and to add it again under its new name. The object should be reported in the changed object list.

    update_checkpoint.SIM_register_post_update()

    NAME
    SIM_register_post_update — register a generic update function
    SYNOPSIS
    SIM_register_post_update(function)

    DESCRIPTION
    Register the generic update function function to be run when updating a checkpoint to build-id build_id. after all build-id based update functions have run, but before the checkpoint is loaded. The function should behave as functions added with SIM_register_generic_update.

    update_checkpoint.all_objects()

    NAME
    all_objects — return all objects of a given class
    SYNOPSIS
    all_objects(set, classname)

    DESCRIPTION
    This function should only be used while updating checkpoints, as described in Model Builder User's Guide, in the Checkpoint Compatibility chapter.

    Return a list of all objects of class classname present in the checkpoint set.

    update_checkpoint.for_all_objects()

    NAME
    for_all_objects — apply a function on all objects of a given class
    SYNOPSIS
    for_all_objects(set, classname, function)

    DESCRIPTION
    This function should only be used while updating checkpoints, as described in Model Builder User's Guide, in the Checkpoint Compatibility chapter.

    Apply the function function on all objects of class classname present in set. function is defined as:

    function(config, object)

    where config is the Python dictionary containing all objects, and object is an object of class classname.

    update_checkpoint.remove_attr()

    NAME
    remove_attr — remove an attribute
    SYNOPSIS
    remove_attr(obj, name)

    DESCRIPTION
    This function should only be used while updating checkpoints, as described in Model Builder User's Guide, in the Checkpoint Compatibility chapter.

    Remove the attribute name from the object obj.

    update_checkpoint.remove_class()

    NAME
    remove_class — remove all instances of a class
    SYNOPSIS
    remove_class(set, classname)

    DESCRIPTION
    This function should only be used while updating checkpoints, as described in Model Builder User's Guide, in the Checkpoint Compatibility chapter.

    In the checkpoint set, remove all objects of class classname.

    update_checkpoint.remove_class_attr()

    NAME
    remove_class_attr — remove a class attribute
    SYNOPSIS
    remove_class_attr(set, classname, name)

    DESCRIPTION
    This function should only be used while updating checkpoints, as described in Model Builder User's Guide, in the Checkpoint Compatibility chapter.

    In the checkpoint set, remove the class attribute name from all objects of class classname.

    update_checkpoint.rename_attr()

    NAME
    rename_attr — rename an attribute
    SYNOPSIS
    rename_attr(obj, new_attr, old_attr)

    DESCRIPTION
    This function should only be used while updating checkpoints, as described in Model Builder User's Guide, in the Checkpoint Compatibility chapter.

    Rename the attribute old_attr to new_attr in the object obj.

    configuration.OBJ

    NAME
    OBJ — class for referring to another object, existing or not
    SYNOPSIS
    OBJ(name)

    DESCRIPTION
    OBJ is only used together with the SIM_set_configuration API function. OBJ is used when a configuration attribute needs to refer to another object. The other object can either be present in an existing configuration, or it can be an object that will be created as a result of the same call to SIM_set_configuration. See SIM_set_configuration for an example.
    SEE ALSO
    SIM_set_configuration

    simics.pre_conf_object

    NAME
    pre_conf_object — class for Simics configuration object to instantiate
    SYNOPSIS
    pre_conf_object(object_name, class_name, build_id = None)

    DESCRIPTION
    A class representing a future Simics configuration object named object_name, of class class_name. If object_name is None, a unique name will be generated.

    The build-id of the object can be specified when using the pre_conf_object class during checkpoints update. Refer to Model Builder User's Guide for more information.

    Future configuration attributes are set using normal Python class members:

      a = pre_conf_object("test_object", "test-class")
      a.value = 42

    After using a pre_conf_object object to create a configuration object, the created object can be obtained by passing the pre_conf_object's name member to SIM_get_object().

    10.4 Hypersim

    10.4.1 hypersim_patterns.add()

    NAME
    add — register a hypersim-pattern
    SYNOPSIS
    add(name, arch,
        target_list = None,
        own_info_cmd = False,
        own_status_cmd = False)

    DESCRIPTION
    The simics_start.py script for all pattern modules should call this function to register its pattern classes. The patterns will be automatically installed on the processor types it supports.

    Function arguments:

    name
    class name
    arch
    architecture it supports (cpu->architecture ppc32, ppc64)
    target_list
    optional list of classnames that are supported. If target_list is omitted or None, the pattern will be used by all CPUs of arch architecture.
    own_info_cmd
    Legacy parameter, must always be overridden to True
    own_status_cmd
    Legacy parameter, must always be overridden to True

    10.4.2 hypersim_patterns.register_std_info_command()

    NAME
    register_std_info_command — register standard info command
    SYNOPSIS
    register_std_info_command(cls)

    DESCRIPTION
    Register a basic info command implementation for the hypersim pattern class named cls

    10.4.3 hypersim_patterns.register_std_status_command()

    NAME
    register_std_status_command — register standard status command
    SYNOPSIS
    register_std_status_command(cls)

    DESCRIPTION
    Register a basic status command implementation for the hypersim pattern class named cls

    10.5 Flash Memory

    Flash Memory Classes and Functions

    flash_memory.flash_add_model()

    NAME
    flash_add_model — add a new flash model
    SYNOPSIS
    flash_add_model(product_no, config, complete_func)

    DESCRIPTION
    Adds a new flash model. Instances of the new flash can then be created with the flash_create_memory and flash_create_memory_anon functions.

    These are the arguments:

    product_no
    Product number; e.g., "28F___C3_". Underscores act as wild cards and will match any character.
    config
    Dictionary containing attribute: value pairs. These attributes are generic-flash-memory attributes; information on available attributes and how to configure them can be found in the reference manual.
    complete_fun
    Function of type complete_fun(product_no, config) that will be called just before a flash memory is instantiated. product_no is the product number specified by the user. config is the same config dictionary as passed to the flash_add_model function. The complete_fun can modify the attribute values, add new attributes or remove attributes from the configuration, based on e.g. the product_no. The complete_fun should return either an error message (i.e. a string), or a tuple (updated_config, size) where size is the size of one flash chip, in bytes.

    RETURN VALUE
    True if the flash model was successfully added, or False if it failed.

    flash_memory.flash_create_memory()

    NAME
    flash_create_memory — create a list of objects representing a flash memory
    SYNOPSIS
    flash_create_memory(name, product_no, interleave, bus_width,
                        files = [],
                        queue = None,
                        accept_smaller_reads = 1,
                        accept_smaller_writes = 0,
                        big_endian = 0)

    DESCRIPTION
    Returns a list of pre_objects suitable as input for SIM_add_configuration and the total size in bytes of the flash memory. The list and the size is returned as a tuple.

    The flash objects will be named, which makes them suitable for use in legacy components. New components should use the function flash_create_memory_anon instead.

    Function arguments:

    name
    Base name for all objects (flash, ram, and image).
    product_no
    Product name; e.g., "28F160C3T".
    interleave
    Byte interleaving; one of 1, 2, 4, and 8.
    bus_width
    Bus width; one of 8, 16, 32, and 64.
    files
    Same as the file attribute of image objects. Defaults to the empty list.
    queue
    Queue object to use.
    accept_smaller_reads
    If 1 (default), the flash device will accept reads smaller than the bus width. if 0, the flash device will complain when receiving smaller reads.
    accept_smaller_writes
    If 1, the flash device will accept writes smaller than the bus width. If 0 (default), the flash device will complain when receiving smaller writes.
    big_endian
    If set, the flash device will behave as a big endian device. If not set (default), it will behave as a little endian device.

    RETURN VALUE
    tuple(object dict, total size in bytes)

    flash_memory.flash_create_memory_anon()

    NAME
    flash_create_memory_anon — create a list of objects representing a flash memory
    SYNOPSIS
    flash_create_memory_anon(product_no, interleave, bus_width,
                             files = [],
                             queue = None,
                             accept_smaller_reads = 1,
                             accept_smaller_writes = 0,
                             big_endian = 0)

    DESCRIPTION
    Returns an list of pre_objects suitable as input for SIM_add_configuration and the total size in bytes of the flash memory. The list and the size is returned as a tuple.

    The flash objects will be anonymous, which makes them suitable for use in new components. Legacy components should use the function flash_create_memory instead.

    Function arguments:

    product_no
    Product name; e.g., "28F160C3T".
    interleave
    Byte interleaving; one of 1, 2, 4, and 8.
    bus_width
    Bus width; one of 8, 16, 32, and 64.
    files
    Same as the file attribute of image objects. Defaults to the empty list.
    queue
    Queue object to use.
    accept_smaller_reads
    If 1 (default), the flash device will accept reads smaller than the bus width. if 0, the flash device will complain when receiving smaller reads.
    accept_smaller_writes
    If 1, the flash device will accept writes smaller than the bus width. If 0 (default), the flash device will complain when receiving smaller writes.
    big_endian
    If set, the flash device will behave as a big endian device. If not set (default), it will behave as a little endian device.

    RETURN VALUE
    tuple(object list, total size in bytes)

    10.6 System Panel

    The System Panel API is a set of Python functions and classes that is used to create system panels. Further documentation can be found in the Model Builder User's Guide, chapter Creating a System Panel.

    The API section covers the generic API for the system panel infrastructure and a couple of helper functions; the Widget Types section describes the specifics of each type of widget that can be included in a panel.

    API

    Standard Widgets Colors

    NAME
    standard color names
    NAMESPACE
    systempanel.widgets
    DESCRIPTION
    The standard widgets colors are used for creating LED widgets with different colors.
    SYNOPSIS
    systempanel.widgets.BLUE
    systempanel.widgets.GREEN
    systempanel.widgets.PURPLE
    systempanel.widgets.RED
    systempanel.widgets.WHITE
    systempanel.widgets.YELLOW
        

    SEE ALSO
    systempanel.widgets.Led

    systempanel.SystemPanel

    NAME
    SystemPanel — Base class for system panel components
    DESCRIPTION
    A base class for system panels. A system panel class should inherit from this and set the 'layout' class variable to describe the contents of the panel.

    systempanel.SystemPanelException

    NAME
    SystemPanelException — System panel error
    DESCRIPTION
    Exception thrown for various errors in the system_panel module

    Widget Types

    systempanel.widgets.BitfieldImageOutput

    NAME
    BitfieldImageOutput — Multiple two-state image outputs driven by a single integer state
    SYNOPSIS
    BitfieldImageOutput(obj_name, contents)

    DESCRIPTION
    An output consisting of multiple two-state images, driven by a single integer state. such that each two-state image is driven by a single bit in the integer. Useful e.g. when creating 7-segment displays.

    The contents parameter is a list of tuples (mask, x, y, [off_filename, on_filename]), where the integer mask is a power of two, x and y are integer offsets, and off_filename and on_filename are file names given on the same form as in the Image class. The off_filename image is shown at the given offset whenever the bit indicated by mask is 0; on_filename is shown otherwise.

    systempanel.widgets.BitmapButton

    NAME
    BitmapButton — A bitmap-based button
    SYNOPSIS
    BitmapButton(obj_name, off_bitmap, on_bitmap)

    DESCRIPTION
    A bitmap-based button. Similar to the standard Button class, but can be put inside a Canvas, and the appearance is based on custom images. The bitmap parameters are filenames of the same type as in the Image class.

    systempanel.widgets.BitmapLed

    NAME
    BitmapLed — A bitmap-based LED
    SYNOPSIS
    BitmapLed(obj_name, off_bitmap, on_bitmap)

    DESCRIPTION
    A bitmap-based LED. Same as the standard Led class, but can be put inside a Canvas, and custom images can be supplied. The bitmap constructor parameters are file names of the same type as in the Image class.

    systempanel.widgets.BitmapToggleButton

    NAME
    BitmapToggleButton — A bitmap-based toggle button
    SYNOPSIS
    BitmapToggleButton(obj_name, off_bitmap, on_bitmap)

    DESCRIPTION
    A bitmap-based toggle button. Similar to the standard ToggleButton class, but can be put inside a Canvas, and the appearance is based on custom images. The bitmap parameters are file names of the same type as in the Image class.

    systempanel.widgets.Button

    NAME
    Button — A standard button
    SYNOPSIS
    Button(obj_name, label)

    DESCRIPTION
    A button, that can be pressed. The button state is propagated using the signal interface, and can be raised or lowered. Raising and lowering the signal is frontend specific.

    systempanel.widgets.Canvas

    NAME
    Canvas — A canvas (i.e bitmap container)
    SYNOPSIS
    Canvas(contents)

    DESCRIPTION
    A canvas for painting bitmap-based widgets. A canvas contains multiple bitmap-based widgets, each drawn at a specified offset. The contents parameter is a list of elements on the form (x, y, widget). Here x and y are integers, and widget is an instance of one of Image, BitmapLed, BitmapButton, BitmapToggleButton, MultiImageOutput, Canvas, or a subclass thereof. The items are rendered in the same order as they appear in the list; this means that if any widgets overlap, the last one will be drawn on top.

    systempanel.widgets.Column

    NAME
    Column — A one-dimensional widget container
    SYNOPSIS
    Column(contents)

    DESCRIPTION
    A container for normal (non bitmap-based) widgets. The Column container is a special case of Grid container; the contained widgets are laid out vertically.

    systempanel.widgets.Empty

    NAME
    Empty — An empty widget
    SYNOPSIS
    Empty()

    DESCRIPTION
    An empty widget, used to fill containers for layout purposes.

    systempanel.widgets.Grid

    NAME
    Grid — A two-dimensional widget container
    SYNOPSIS
    Grid(contents, columns)

    DESCRIPTION
    A two-dimensional widget container. Containers are used to group other widgets, and enforce a specific layout scheme. The contents constructor parameter is a list of widget objects; it can contain any other widget except for bitmap-based ones. Widgets are laid out from left to right, top to bottom. Use the Empty class to fill empty cells. The number of rows in a Grid container is implicitly defined by the length of the contents list and the number of columns specified when creating the container. See also the Column and Row containers, which are convenience classes for the one-dimensional cases. Containers can contain other containers.

    systempanel.widgets.Image

    NAME
    Image — An image
    SYNOPSIS
    Image(filename)

    DESCRIPTION
    An image, that can be put inside a Canvas class. Currently the only supported file format is PNG, but with full support for transparency. See Canvas class for more information.

    systempanel.widgets.Label

    NAME
    Label — An label
    SYNOPSIS
    Label(label)

    DESCRIPTION
    A label, used to present static text.

    systempanel.widgets.LabeledBox

    NAME
    LabeledBox — A container with a label and box drawn around it
    SYNOPSIS
    LabeledBox(label, container)

    DESCRIPTION
    A single-element container with a text label and a box drawn around it. The single widget given by the container parameter can be of any widget type, but it is typically of a container type.

    systempanel.widgets.Led

    NAME
    Led — A standard LED
    SYNOPSIS
    Led(obj_name, color=None)

    DESCRIPTION
    A LED, which can be on or off. Driven by the signal interface. The parameter color specifies the color of the LED, all supported colors are described in Standard Widgets Colors. The look-and-feel of the LED is frontend specific.
    SEE ALSO
    Standard Widgets Colors

    systempanel.widgets.MultiImageOutput

    NAME
    MultiImageOutput — A bitmap-based output that toggles between multiple images
    SYNOPSIS
    MultiImageOutput(obj_name, images)

    DESCRIPTION
    An output that toggles between multiple custom images. This can be used, among other things, for multi-coloured LEDs or seven-segment display elements. The images parameter is a list of paths to image filenames, each one given on the same form as in the Image class. Numeric input to the panel object via the uint64_state interface is used as a 0-based index in the image list.

    systempanel.widgets.NumberInput

    NAME
    NumberInput — An input text field for integer numbers
    SYNOPSIS
    NumberInput(obj_name)

    DESCRIPTION
    An input text field for integer numbers, provided by the panel user. The value is propagated to the model using the uint64_state interface.

    systempanel.widgets.NumberOutput

    NAME
    NumberOutput — An output text field for integer numbers
    SYNOPSIS
    NumberOutput(obj_name)

    DESCRIPTION
    An output text field for integer numbers, presenting integer state from the model. Driven by the uint64_state interface.

    systempanel.widgets.Row

    NAME
    Row — A one-dimensional widget container
    SYNOPSIS
    Row(contents)

    DESCRIPTION
    A container for normal (non bitmap-based) widgets. The Row container is a special case of Grid container; the contained widgets are laid out horizontally.

    systempanel.widgets.ToggleButton

    NAME
    ToggleButton — A toggle button
    SYNOPSIS
    ToggleButton(obj_name, label)

    DESCRIPTION
    A toggle button, that can be pressed or released. The button state is propagated using the signal interface. When button is pressed, signal is raised. When button is released, signal is lowered. The button must have a label indicating its purpose.

    10.7 Testing

    10.7.1 stest

    Utilities for testing simics.

    fail

    Synopsis
    fail(msg)

    Description
    Signal a failure in a test.

    Takes a string describing the failure as its single argument. If called in collect failures mode this will collect the failure for later checking with check_failures. If called outside collect failures mode it will immediately raise a TestFailure exception instead.

    collect_failures

    Synopsis
    collect_failures()

    Description
    Change the behavior of stest to collect failures instead of terminating on the first failure detected.

    If you use this you have to call check_failures at the end of your test script to check if it signaled any failures.

    check_failures

    Synopsis
    check_failures()

    Description
    Check if any failures have occurred and leave collect failures mode.

    If any failures have occurred this function will report the failures and raise a TestFailure exception. If called outside collect failures mode this function will fail.

    trap_log

    Synopsis
    trap_log(logtype, obj = None)

    Description
    Configure Simics to trap a type of log messages, and cause Simics to quit with a test failure on any such log message.

    By default the stest trap 'error' and 'spec-viol' log messages.

    trap_log without an object sets the default handling for the given log type. Object specific settings always take precedence over the default handling.

    Arguments:

    logtype
    the type of log messages to trap, one of 'info', 'error', 'undef', 'spec-viol', and 'unimpl'
    obj
    the configuration object whose log messages to trap, defaults to None, which means that all log messages of the right type are trapped

    untrap_log

    Synopsis
    untrap_log(logtype, obj = None)

    Description
    Explicitly allow messages of a given log type. Can be used to undo a previous trap_log or to filter objects from a default trap.

    untrap_log without an object sets the default behavior for the given log type. Object specific settings always take precedence over the default handling.

    Arguments:

    logtype
    the type of log messages to untrap, one of 'info', 'error', 'undef', 'spec-viol', and 'unimpl'
    obj
    the configuration object whose log messages to untrap, defaults to None, which means that all log messages of the right type are untrapped

    expect_true

    Synopsis
    expect_true(cond, msg = 'expectation failed')

    Description
    Check if a condition is true and cause a test failure if it is not.

    Arguments:

    cond
    the condition to test
    msg
    a message explaining the failure

    expect_false

    Synopsis
    expect_false(cond, msg = 'expectation failed')

    Description
    Check if a condition is false and cause a test failure if it is not.

    Arguments:

    cond
    the condition to test
    msg
    a message explaining the failure

    expect_equal

    Synopsis
    expect_equal(got, expected, msg = 'expectation failed')

    Description
    Checks if a value is equal to an expectation and cause a test failure if it is not.

    Arguments:

    got
    the value to check
    expected
    what to compare the value with
    msg
    a message explaining the failure

    expect_different

    Synopsis
    expect_different(got, unexpected, msg = 'expectation failed')

    Description
    Checks if a value is different to an expectation and cause a test failure if it is not.

    Arguments:

    got
    the value to check
    unexpected
    what to compare the value with
    msg
    a message explaining the failure

    expect_log

    Synopsis
    expect_log(fun, args = [], obj = None, log_type = 'error', msg = None, regex = '', with_log_level = None)

    Description
    Call a function and verify that a particular log message is emitted. Returns the called function's return value. Arguments:
    fun
    the function to be called
    args
    the arguments with which to call fun
    All other arguments are identical to expect_log_mgr

    expect_log_mgr

    Synopsis
    expect_log_mgr(*args, **kwds)

    Description
    Context manager, verifying that, on exit from the with-statement, a particular log message has been emitted. Arguments:
    obj
    optional object from which a log is expected, default is None which accepts any object
    log_type
    optional log type which the emitted log must belong to, one of "error" (default), "unimpl", "info", "spec-viol" or "undefined"
    msg
    optional message emitted on failure
    regex
    optional regular expression object or a string containing a regular expression suitable for use by re.search(), which the emitted log must match
    with_log_level
    optional log level to apply inside the context

    Example usage:

    with stest.expect_log_mgr(log_type="spec-viol",
                              msg="Check warning on read-only fields"):
        reg_compute_units.write(0xffff_ffff_ffff_ffff)
     

    expect_exception

    Synopsis
    expect_exception(fun, args, exc, regex = '')

    Description
    Call function fun with arguments args, and verify that it raises an exception of type exc. If fun does not raise exc, cause a failure.

    expect_exception_mgr

    Synopsis
    expect_exception_mgr(*args, **kwds)

    Description
    Context manager verifying that the body of with-statement throws an exception of the specified type.

    Arguments:

    exc
    exception type
    regex
    optional regular expression object or a string containing a regular expression suitable for use by re.search(), which the string representation of raised exception must match

    Example usage:

    with stest.expect_exception_mgr(simics.SimExc_AttrNotWritable):
        dev.read_only_attribute = False
     

    deprecation_level

    Synopsis
    deprecation_level(*args, **kwds)

    Description
    Context manager for temporarily setting a deprecation level and restore it when exiting the context.

    Arguments:

    level
    deprecation level in context

    Example usage:

     with stest.deprecation_level(2)
        stest.expect_equal(conf.sim.deprecation_level, 2)
     

    TestFailure

    Superclasses
    builtins.Exception
    Description
    Exception class used to signal failures in Simics tests.

    Use the fail function instead of raising this exception yourself.

    10.7.2 dev_util

    A Python module for writing device model tests. Has three major parts: classes for accessing device registers, classes for writing device stubs, and classes for handling simulated memory and data structures in it. It also contains some auxiliary utilities.

    It uses the Simics API and can only be used by Python code running in Simics.

    bank_regs

    Synopsis
    bank_regs(bank, inquiry = False, prefix = '')

    Description
    Given a bank object, return a structure containing objects to access its registers. The returned structure can be a hierarchy of objects; e.g., if a register instance is named "g[2][3].r[1]", and the returned structure is o, then the corresponding register object can be obtained as o.g[2][3].g[1]. The set of registers is extracted using the register_view interface, and uses offsets and bitfields as returned by that interface. The inquiry argument is deprecated and should not be used. If prefix is given, then the returned structure will only contain registers whose full name matches this prefix.

    The returned register objects have methods read() and write() that work like their AbstractRegister counterparts, reading and writing the register with side-effects. The register value can be read and written without side-effects objects by getting and setting a property .val, or by calling a method set(). The latter accepts keyword arguments for fields just like the write() method; bits not covered by fields are retrieved by reading .val. The positional argument of the write() method is required and may be either an integer, or READ to denote that previous values are retrieved using read(), or VAL to denote that they are retrieved using .val.

    In addition to the val property and set, read and write methods mentioned above, register objects also have the following properties:

    • bank: The Simics configuration object of the bank
    • size, offset: the register's location within the bank
    • bitfield: a dev_util.Bitfield describing the
    • name: the name of the register, relative to the bank.

    Objects that represent the fields of a register can be retrieved as reg.field.FIELDNAME; e.g., if a register reg has a field named "a.b[2]" then the field object is accessed as reg.field.a.b[2]. The field object has one method read() for performing a full-register read with side-effects and returning the bits corresponding to the field, and a property .val that allows side-effect free access to the field's bits. Field objects provide a read method, which reads the parent register and returns the bits corresponding to the field, but it does not have a write method; writes must be done from the register object to ensure that remaining bits are explicitly specified. Field objects also provide the following properties:

    • reg: The parent register object
    • lsb, bits: the bit range within the parent register
    • name: the name of the field, relative to the parent register

    iface

    Synopsis
    iface(name)

    Description
    Deprecated.

    value_to_tuple_be

    Synopsis
    value_to_tuple_be(val, bytes)

    Description
    Deprecated, use tuple(val.to_bytes(bytes, 'big')) instead.

    value_to_tuple_le

    Synopsis
    value_to_tuple_le(val, bytes)

    Description
    Deprecated, use tuple(val.to_bytes(bytes, 'little')) instead.

    tuple_to_value_be

    Synopsis
    tuple_to_value_be(t)

    Description
    Deprecated, use int.from_bytes(t, 'big') instead.

    tuple_to_value_le

    Synopsis
    tuple_to_value_le(t)

    Description
    Deprecated, use int.from_bytes(t, 'little') instead.

    Error

    Superclasses
    builtins.Exception
    Description
    Baseclass of all exceptions specified in this module.

    InvalidBitfieldException

    Superclasses
    dev_util.Error
    Description
    Signals that a bitfield's parameters are invalid.

    RangeError

    Superclasses
    dev_util.Error
    Constructor
    RangeError(msg, re = None)

    Description
    Signals that a value is out of range for a bitfield.

    MemoryError

    Superclasses
    dev_util.Error
    Description
    Signals that a memory operation failed.

    Bitfield

    Superclasses
    builtins.object
    Constructor
    Bitfield(fields = None, ones = 0, little_endian = True, bits = None, **kwargs)

    Description
    Utility for bitfield manipulations. Constructor arguments:
    fields
    a dict on the following format, where sub-field is of type fields:
     {'field-name' : bit-number,
      'field-name' : (start-bit, stop-bit),
      'field-name' : (start-bit, sub-field)
     }
     

    ones
    a bitmask that will be OR:ed in the complete bitfield value
    little-endian
    set to True for a little-endian bitorder field and False for big-endian bitorder fields
    bits
    the total size (in bits) of the fields; required by, as well as only allowed for, big-endian fields
    **kwargs
    as fields, but specified using keyword arguments

    fields

    Synopsis
    obj.fields(value)

    Description
    Returns a dict consisting of all fields and their values, taken from the value argument.

    mask

    Synopsis
    obj.mask(**dict)

    Description
    Returns a mask from the fields in dict.

    mk_bitfield_map

    Synopsis
    obj.mk_bitfield_map(m, prefix = '', oset = 0)

    Description
    Convert a nested layout type to a map suitable for construction of a dev_util.Bitfield object.

    value

    Synopsis
    obj.value(*args, **kwargs)

    Description
    Returns the value of the fields given by **kwargs. For example, pass foo=5 to return the value when field "foo" is 5. If the value is a list or dict rather than an integer, then a field array is assumed; e.g. foo=[1,2] is a shorthand for setting field "foo[0]" to 1 and field "foo[1]" to 2, and foo={1:4} is a shorthand for setting field "foo[1]" to 4.

    An optional positional argument can be supplied, to provide the values of bits not covered by the given fields.

    Bitfield_LE

    Superclasses
    dev_util.Bitfield
    Constructor
    Bitfield_LE(fields = None, ones = 0, **kwargs)

    Description
    Constructor arguments:
    fields
    a dict on the following format, where sub-field is of type fields:
     {'field-name' : bit-number,
      'field-name' : (start-bit, stop-bit),
      'field-name' : (start-bit, sub-field)
     }
     

    ones
    a bitmask that will be OR:ed in the complete bitfield value
    **kwargs
    as fields, but specified using keyword arguments

    Bitfield_BE

    Superclasses
    dev_util.Bitfield
    Constructor
    Bitfield_BE(fields = None, ones = 0, bits = None, **kwargs)

    Description
    Bit-endian bitfield. Constructor arguments:
    fields
    a dict on the following format, where sub-field is of type fields:
     {'field-name' : bit-number,
      'field-name' : (start-bit, stop-bit),
      'field-name' : (start-bit, sub-field)
     }
     

    ones
    a bitmask that will be OR:ed in the complete bitfield value
    bits
    the total size (in bits) of the fields; required by big-endian fields
    **kwargs
    as fields, but specified using keyword arguments

    AbstractRegister

    Superclasses
    builtins.object
    Constructor
    AbstractRegister(size = 4, bitfield = None, little_endian = True)

    Description
    Abstract register class.

    This class handles generic register stuff, like bitfield mapping and value construction/deconstruction. It depends on a subclass to implement the backend for data storage.

    Subclasses are expected to implement two functions:

    raw_read(self)
    should return a byte string from storage
    raw_write(self, bytes)
    should write the bytes byte string to storage

    Optionally, a bitfield can be applied to a register. For such a register, a specific field can be read through reg.field.FIELDNAME.read(). The write() method also has support for bitfields. Please see the documentation for write() for more information.

    There is an alternative deprecated shorthand for accessing fields: reg.FIELDNAME triggers a read that filters out the given field, and similarly, reg.FIELDNAME = value reads the field, adjusts the given field, and writes back the value. This syntax is deprecated, because it is not consistent with the API exposed by register objects that both support accesses with and without side-effects.

    Constructor arguments:

    size
    the size in bytes of the register
    bitfield
    optional, if set should be an instance of Bitfield
    little_endian
    should be set to True for a little-endian byte-order register, or False for a big-endian register

    fields

    Synopsis
    obj.fields()

    Description
    Shortcut to read the bitfield representation of a device register.

    read

    Synopsis
    obj.read()

    Description
    Read value.

    write

    Synopsis
    obj.write(*args, **fields)

    Description
    Write value. The value will be truncated to the register size.

    You can either pass a single integer, or pass the fields as arguments, i.e., write(field0=1, field1=23). For field arrays, the syntax write(field=[1,23]) or write(field={0: 1, 1: 23}) can be used to set the fields named field[0] and field[1].

    If only a subset of fields is given, a positional arg should also be passed for the base value, which defines what to write to remaining bits. The value READ denotes that the read() method is called to retrieve the base value.

    Register

    Superclasses
    dev_util.AbstractRegister
    Constructor
    Register(*args, **kwargs)

    Description
    This class allows you to easily access a device register. The bank argument is normally the bank object. However, for backward compatibility it can also be a tuple (obj, bank, ofs); in this case the offset argument should be left out. The tuple denotes:
    obj
    the (simics) object implementing the register
    bank
    the port-name or function number of the bank containing the register (function 0 if omitted).
    offset
    the register offset in said bank

    The tuple syntax was useful in old Simics versions where banks were not separate objects. It should be avoided in new versions.

    The initiator argument denotes the initiator of transactions accessing the register. See the AbstractRegister documentation for information about the rest of the parameters.

    raw_read

    Synopsis
    obj.raw_read()

    Description
    Read raw data from the register.

    raw_write

    Synopsis
    obj.raw_write(val)

    Description
    Write raw data to the register.

    Register_LE

    Superclasses
    dev_util.Register
    Constructor
    Register_LE(*args, **kwargs)

    Description
    Little-endian device register. All arguments have the same semantics as in dev_util.Register.

    Register_BE

    Superclasses
    dev_util.Register
    Constructor
    Register_BE(*args, **kwargs)

    Description
    Big-endian device register. All arguments have the same semantics as in dev_util.Register.

    GRegister

    Superclasses
    dev_util.AbstractRegister
    Constructor
    GRegister(size = 4, bitfield = None, init = 0)

    Description
    This class allows provides a standalone register.

    raw_read

    Synopsis
    obj.raw_read()

    Description
    Reads the raw contents of the register.

    raw_write

    Synopsis
    obj.raw_write(value)

    Description
    Write the raw contents of the register.

    IRegister

    Superclasses
    dev_util.AbstractRegister
    Constructor
    IRegister(data, size = None, bitfield = None)

    Description
    This class allows you to easily access registers through the int_register interface. If the object obj does not implement the processor_info you have to specify the size in size.

    raw_read

    Synopsis
    obj.raw_read()

    Description
    Reads the raw contents of the register.

    raw_write

    Synopsis
    obj.raw_write(value)

    Description
    Write the raw contents of the register.

    Dev

    Superclasses
    builtins.object
    Constructor
    Dev(iface_list = [], create_sim_obj = True, name = None)

    Description
    A Simics class with a single instance. Implements zero or more interfaces based on instances of Iface. Presents zero or more ports, implementing one or more interfaces each.

    The obj attribute contains the instance of the Simics class, and the cls_name attribute contains the name of the Simics class. Constructor arguments:

    iface_list
    a list of interface classes or pairs of (port, interface-class)
    create_sim_obj
    if False, no Simics object will be created, but the class will be registered along with all the interfaces, useful e.g. when loading a checkpoint containing fake objects
    name
    if given, specifies the name to use for the fake class and the fake object; otherwise a name will be guessed based on the implemented interfaces

    Each interface will be instantiated and can be accessed through dev.iface-name, or dev.port.iface-name.

    Example:

     dev = Dev([SimpleInterrupt,
                ('sreset', Signal),
                ('hreset', Signal)])
    
     dev.simple_interrupt
     dev.sreset.signal
     dev.hreset.signal
     

    configure_pre_object

    Synopsis
    obj.configure_pre_object(pre_obj)

    Description
    Called before SIM_add_configuration. Override to e.g. set attributes.

    finalize

    Synopsis
    obj.finalize()

    Description
    Called after the Simics object has been instantiated.

    register_simics_class

    Synopsis
    obj.register_simics_class()

    Description
    Register the Simics class created by this object.

    Iface

    Superclasses
    dev_util_internal.BasicIface
    Constructor
    Iface()

    Description
    Base class for fake interfaces. To create an interface, inherit this class, define a class variable iface to the interface name, and define all methods that the interface defines.

    fail

    Synopsis
    obj.fail(msg)

    Description
    Signal a failure when running an interface method.

    Called by the default method stubs.

    Memory

    Superclasses
    builtins.object
    Constructor
    Memory()

    Description
    Deprecated. Legacy wrapper around an instance of the sparse-memory class. Provides an interface compatible with the deprecated Memory class.

    The obj attribute contains an instance of memory-space, mapping to the memory. The real_obj attribute contains an instance of the 'sparse-memory' class. The mem attribute is an alias to the mem attribute of real_obj.

    clear

    Synopsis
    obj.clear(*args)

    Description
    Clear the contents of the memory.

    is_range_touched

    Synopsis
    obj.is_range_touched(start, length)

    Description
    Return True if any of this memory's slots in the range contain data.

    read

    Synopsis
    obj.read(addr, n)

    Description
    Read bytes from this memory.

    Arguments:

    addr
    the start address of the range to read
    n
    length in bytes of the range to read

    Throws an exception if any byte in the read range is empty.

    write

    Synopsis
    obj.write(addr, data)

    Description
    Write bytes to this memory.

    Arguments:

    addr
    the start address of the range to write
    data
    the bytes to write

    Fills in empty slots in the memory and overwrites already existing data.

    Layout

    Superclasses
    builtins.object
    Constructor
    Layout(mem, ofs, regs, little_endian)

    Description
    This class implements a memory layout.

    Testing devices that does DMA transfers usually requires setting up DMA descriptors. These can often be seen as register sets located in memory. This class allows you to define the layout of those registers, including bitfields within the registers.

    Registers without bitfields can be accessed through:

    layout.reg-name

    while registers with bitfields can be accessed through:

    layout.reg-name.field-name

    or

     layout.reg-name.read(),
     layout.reg-name.write()
     

    Layouts are mapped ontop of Memory, i.e. NOT ontop of normal Simics RAM. Constructor arguments:

    mem
    An object that is a valid "map target"
    ofs
    the byte offset (i.e. the location of the layout)
    little_endian
    determines the byte order of the registers in the layout
    regs
    a dictionary on the following form:
     {'reg-name' : (offset, size),
      'reg-name' : (offset, size, bitfield)}
     

    offset
    the register offset into the layout
    size
    the size in bytes of the register
    bitfield
    optional and should be an instance of Bitfield

    clear

    Synopsis
    obj.clear()

    Description
    Set all of the fields in this layout to 0.

    read

    Synopsis
    obj.read(ofs, size)

    Description
    Returns the value at ofs.

    write

    Synopsis
    obj.write(ofs, value, size)

    Description
    Writes value to ofs.

    Layout_LE

    Superclasses
    dev_util.Layout
    Constructor
    Layout_LE(mem, ofs, regs)

    Description
    Little-endian layout.

    Layout_BE

    Superclasses
    dev_util.Layout
    Constructor
    Layout_BE(mem, ofs, regs)

    Description
    Big-endian layout.

    10.7.3 dev_util_internal

    Internal and/or legacy classes removed from dev_util.py

    iface

    Synopsis
    iface(name)

    Description
    Returns an Iface subclass which implements the interface name.

    All the interface methods in the class will raise an exception when called. Convenient when creating a fake device that is required to implement an interface, but you know that the interface should be unused in the given test.

    Dev

    Superclasses
    builtins.object
    Constructor
    Dev(iface_list = [], create_sim_obj = True, name = None)

    Description
    A Simics class with a single instance. Implements zero or more interfaces based on instances of Iface. Presents zero or more ports, implementing one or more interfaces each.

    The obj attribute contains the instance of the Simics class, and the cls_name attribute contains the name of the Simics class. Constructor arguments:

    iface_list
    a list of interface classes or pairs of (port, interface-class)
    create_sim_obj
    if False, no Simics object will be created, but the class will be registered along with all the interfaces, useful e.g. when loading a checkpoint containing fake objects
    name
    if given, specifies the name to use for the fake class and the fake object; otherwise a name will be guessed based on the implemented interfaces

    Each interface will be instantiated and can be accessed through dev.iface-name, or dev.port.iface-name.

    Example:

     dev = Dev([SimpleInterrupt,
                ('sreset', Signal),
                ('hreset', Signal)])
    
     dev.simple_interrupt
     dev.sreset.signal
     dev.hreset.signal
     

    configure_pre_object

    Synopsis
    obj.configure_pre_object(pre_obj)

    Description
    Called before SIM_add_configuration. Override to e.g. set attributes.

    finalize

    Synopsis
    obj.finalize()

    Description
    Called after the Simics object has been instantiated.

    register_simics_class

    Synopsis
    obj.register_simics_class()

    Description
    Register the Simics class created by this object.

    Iface

    Superclasses
    dev_util_internal.BasicIface
    Constructor
    Iface()

    Description
    Base class for fake interfaces. To create an interface, inherit this class, define a class variable iface to the interface name, and define all methods that the interface defines.

    fail

    Synopsis
    obj.fail(msg)

    Description
    Signal a failure when running an interface method.

    Called by the default method stubs.

    Memory

    Superclasses
    dev_util_internal.Dev
    Constructor
    Memory(test = False)

    Description
    A Simics memory space in which every slot can contain a byte, or be empty.

    Each byte sized slot in this memory can either contain a byte of data or be empty. Empty slots cannot be read.

    The obj attribute contains the object implementing the Simics interface to the memory. It implements the memory_space interface. Constructor arguments:

    test
    set to True to not create any Simics objects, optional, defaults to False

    clear

    Synopsis
    obj.clear()

    Description
    Clear the contents of the memory.

    is_range_touched

    Synopsis
    obj.is_range_touched(start, length)

    Description
    Return True if any of this memory's slots in the range contain data.

    read

    Synopsis
    obj.read(addr, n)

    Description
    Read bytes from this memory.

    Arguments:

    addr
    the start address of the range to read
    n
    length in bytes of the range to read

    This method throws an exception if any byte in the read range is empty.

    write

    Synopsis
    obj.write(addr, bytes)

    Description
    Write bytes to this memory.

    Arguments:

    addr
    the start address of the range to write
    n
    the bytes to write

    Fills in empty slots in the memory and overwrites already existing data.

    10.8 Script branches

    The Script Branch API is a set of Python functions for controlling script branches. This API is used when implementing CLI commands that make use of script branches, and also when waiting for simulator events via corresponding wait-for- CLI commands. See the Simics User's Guide for an introduction and examples of using the API.

    script_branch Python Module

    script_branch.sb_create()

    NAME
    sb_create — create a script branch
    SYNOPSIS
    sb_create(func, desc = None)

    DESCRIPTION
    Create a script branch that will start executing func (which should not take any arguments). The sb_create function returns a unique script-branch identifier, that can be used with sb_interrupt_branch. It may be called from a script branch to create a new parallel branch. The current branch will resume execution when the new script branch is suspended.

    The optional desc argument will be displayed by list-script-branches as a description of the script branch.

    RETURN VALUE
    script-branch identifier
    SEE ALSO
    script_branch.sb_wait, script_branch.sb_interrupt_branch, script_branch.sb_run_in_main_branch
    EXECUTION CONTEXT
    Global Context

    script_branch.sb_get_wait_id()

    NAME
    sb_get_wait_id — obtain script branch wait ID
    SYNOPSIS
    sb_get_wait_id()

    DESCRIPTION
    Return a new unique script-branch wait-identifier that can be used when suspending a script-branch using sb_wait.
    RETURN VALUE
    script branch wait-identifier
    SEE ALSO
    script_branch.sb_wait, script_branch.sb_signal_waiting

    script_branch.sb_in_main_branch()

    NAME
    sb_in_main_branch — indicate if the main branch is running
    SYNOPSIS
    sb_in_main_branch()

    DESCRIPTION
    Return true if the main branch is currently active, and not one of the script branches.
    SEE ALSO
    script_branch.sb_run_in_main_branch

    script_branch.sb_interrupt_branch()

    NAME
    sb_interrupt_branch — interrupt suspended script branch
    SYNOPSIS
    sb_interrupt_branch(branch_id)

    DESCRIPTION
    Interrupt a script branch that is currently suspended. The branch_id should be the script-branch identifier (returned by sb_create) of a suspended script branch, otherwise an exception is raised.

    As a side effect, the sb_wait function called in the script branch will raise a CliQuietError exception.

    SEE ALSO
    script_branch.sb_create, script_branch.sb_wait

    script_branch.sb_run_in_main_branch()

    NAME
    sb_run_in_main_branch — run function in the main thread
    SYNOPSIS
    sb_run_in_main_branch(command, func)

    DESCRIPTION
    Schedule func (which should not take any arguments) to run in the main thread and block the calling script-branch thread until the function has run. A CliError exception will be raised if an error occurs while running func, otherwise its return value is returned.
    RETURN VALUE
    return value of func
    SEE ALSO
    script_branch.sb_create, script_branch.sb_in_main_branch

    script_branch.sb_signal_waiting()

    NAME
    sb_signal_waiting — wake up a suspended script branch
    SYNOPSIS
    sb_signal_waiting(wait_id)

    DESCRIPTION
    Wake up a suspended script-branch, with wait_id as wait identifier, letting it run again.
    SEE ALSO
    script_branch.sb_wait, script_branch.sb_get_wait_id

    script_branch.sb_wait()

    NAME
    sb_wait — suspend a script branch
    SYNOPSIS
    sb_wait(command, wait_id, reverse=None, always=None, wait_data=None,
            use_obj=None)

    DESCRIPTION
    Suspend a script branch in the command command (a descriptive string) until sb_signal_waiting is called with wait_id as argument. The reverse and always should not be used. The wait_data argument is a string describing the data being waited for, or None. The use_obj argument is deprecated and should never be specified.
    SEE ALSO
    script_branch.sb_create, script_branch.sb_get_wait_id, script_branch.sb_signal_waiting

    10.9 Probes

    The probes Python package allows convenient methods for accessing all probes which has been registered in Simics.

    When probes are enabled with the enable-probes command the probe framework will create Python ProbeProxy objects for all existing probes in the system. Any additional created objects with probes will also automatically get ProbeProxy objects.

    Probes Python Module

    probes.CellFormatter

    NAME
    CellFormatter — helper object for various format properties
    DESCRIPTION
    Helper Class for summary-probe formatting. Simply holds various formatting properties together, in one class object.

    probes.ProbeProxy

    NAME
    ProbeProxy — wrapper class of probes that exists in Simics
    DESCRIPTION
    The ProbeProxy class represents a Python object for the detected probes in the system. The object wrapping allows easier access to the probe objects through the different probe interfaces.

    Object implementing the indexed probe interface, will get a dedicated ProbeProxy object per index.

    The formatting of the different types of probes are also automatically handled by this class.

    probes.get_all_probe_kinds()

    NAME
    get_all_probe_kinds — get all registered probe-kinds in the system
    SYNOPSIS
    get_all_probe_kinds()

    DESCRIPTION
    Returns all registered probe-kinds in the system. The probe-kind is the unique probe identifier, not including the objects associated with it.
    SEE ALSO
    probes.get_probes, probes.get_all_probes

    probes.get_all_probes()

    NAME
    get_all_probes — get all ProbeProxy instances
    SYNOPSIS
    get_all_probes()

    DESCRIPTION
    Returns all Python 'ProbeProxy' objects that exists currently. These objects can be used to access the probe interfaces in a convenient way by using methods in them.
    SEE ALSO
    probes.get_all_probe_kinds, probes.get_probes

    probes.get_probe_by_object()

    NAME
    get_probe_by_object — get the ProbeProxy instance for an object
    SYNOPSIS
    get_probe_by_object(kind, obj)

    DESCRIPTION
    Returns the 'ProbeProxy' Python object for a probe-kind in a specific conf object.
    SEE ALSO
    probes.get_all_probe_kinds, probes.get_probes

    probes.get_probes()

    NAME
    get_probes — get hold of all ProbeProxy instances implementing a specific probe-kind
    SYNOPSIS
    get_probes(kind)

    DESCRIPTION
    Returns the Python 'ProbeProxy' objects, for probes matching the specific probe-kind. These objects can be used to access the probe interfaces in a convenient way by using methods in them.
    SEE ALSO
    probes.get_all_probe_kinds, probes.get_all_probes

    probes.register_probe_delete_cb()

    NAME
    register_probe_delete_cb — request a callback when a probe is deleted
    SYNOPSIS
    register_probe_delete_cb(cb)

    DESCRIPTION
    Register a function which will be called when a probe is deleted from the system. The function only takes a single argument; the ProbeProxy instances that is about to be deleted.
    SEE ALSO
    probes.unregister_probe_delete_cb

    probes.unregister_probe_delete_cb()

    NAME
    unregister_probe_delete_cb — cancel a callback for probe deletion
    SYNOPSIS
    unregister_probe_delete_cb(cb)

    DESCRIPTION
    Unregister a function callback when probes are deleted. Typically needed when a python module itself is removed.
    SEE ALSO
    probes.register_probe_delete_cb

    10.10 Other

    Other Python-specific Classes and Functions

    simics.CriticalErrors

    NAME
    CriticalErrors — represents critical errors caused by C code called from Python
    SYNOPSIS
    CriticalErrors(args)

    DESCRIPTION
    This exception is raised when returning to Python from a C function that directly or indirectly caused one or more serious, but recoverable, errors. Elaborate error descriptions are printed when the errors occur, but because of error recovery, the C function will be able to continue without being aware of the error.

    A C function can cause more than one error; all these are combined into a single Python exception. The main purpose of the exception is to aid debugging, usually by providing a nice Python traceback.

    table.column_names()

    NAME
    column_names — get hold of column names from a property list
    SYNOPSIS
    column_names(prop_list)

    DESCRIPTION
    Help function to retrieve the column names embedded in the list of table properties.
    SEE ALSO
    table.show

    table.default_table_args()

    NAME
    default_table_args — get default table arguments
    SYNOPSIS
    default_table_args(set_dict={})

    DESCRIPTION
    Return the tuple representing the default table arguments. The set_dict can contain key/value elements overriding the default value. The key is the same as the name of the table argument in the command.
    SEE ALSO
    table.new_table_command, table.get

    table.get()

    NAME
    get — fetch the formatted table
    SYNOPSIS
    get(properties, data, *table_args)

    DESCRIPTION
    Similar to the table.show but this function returns the table as a multi-line string.
    SEE ALSO
    table.new_table_command, table.get

    table.get_table_arg_value()

    NAME
    get_table_arg_value — retrieve the value for a table command argument
    SYNOPSIS
    get_table_arg_value(arg, table_values)

    DESCRIPTION
    Allows the user command to look at a certain named parameter to get its value. For example, to internally make use of the -verbose flag. The arg argument specifies the argument to fetch the value of. The table_values argument is the tuple of table arguments received in the table.new_table_command() callback function.

    table.new_table_command()

    NAME
    new_table_command — register a new command which prints a table
    SYNOPSIS
    new_table_command(command_name,
                      cmd_func,
                      args = None,
                      doc = "",
                      sortable_columns = None,
                      **kwargs)

    DESCRIPTION
    Register a specific command for printing the table, with all the command arguments from the <table>.print-table commands, but extendable with personalized argument handling. For example, a dedicated command could print out additional data, or filter out certain rows from the table and only print those.

    All arguments here are similar to the cli.new_command() function except the sortable_columns argument.

    The cmd_func function will be called with additional table argument last. The function should use the table.show() to produce the table output according to the user arguments.

    If the sortable_columns argument is supplied, it should contain a list of the column namnes which can be used for sorting. This is only used for the expander function. If this argument is not set, the default expander will try to use the table interface to retrieve the column names.

    SEE ALSO
    cli.new_command, table.show

    table.show()

    NAME
    show — format and print the table
    SYNOPSIS
    show(properties, data, *table_args)

    DESCRIPTION
    This function should be used from a command function registered through the table.new_table_command() function to print out the table according to the user arguments. The properties argument is a list of key/value pairs setting table properties for the table. The data argument contains the two-dimensional data to be printed where the inner list contains the columns and the outer list the rows of the table. See the table interface for more information.

    The *table_args argument represents the standard table arguments, received last in the table.new_table_command() callback function.

    SEE ALSO
    table.new_table_command, table.get

    11 Complete List

    ATOM_completiontransaction atom's constructor
    ATOM_datatransaction atom's constructor
    ATOM_flagstransaction atom's constructor
    ATOM_initiatortransaction atom's constructor
    ATOM_list_endtransaction atom's constructor
    ATOM_sizetransaction atom's constructor
    MM_FREEfree allocation
    MM_MALLOCallocate memory
    MM_REALLOCreallocate memory
    MM_STRDUPduplicate a string
    SIMLINK_config_remove_valueremove a link configuration parameter
    SIMLINK_config_update_valueupdate a link configuration parameter
    SIMLINK_endpoint_clockreturn endpoint's clock
    SIMLINK_endpoint_dev_namereturn the name of the device or snooper to which an endpoint is connected
    SIMLINK_endpoint_devicereturn the device to which an endpoint is connected
    SIMLINK_endpoint_disconnectdisconnect an endpoint object
    SIMLINK_endpoint_finalizefinalize an endpoint object
    SIMLINK_endpoint_idreturn endpoint's ID
    SIMLINK_endpoint_initinitialize an endpoint object
    SIMLINK_endpoint_is_devicereturn whether an endpoint is connected to a device
    SIMLINK_endpoint_linkreturn endpoint's link
    SIMLINK_endpoint_portreturn the device's port to which an endpoint is connected
    SIMLINK_finalizefinalize a link object
    SIMLINK_find_endpoint_by_idreturn an endpoint object given its ID
    SIMLINK_initinitialize a link object
    SIMLINK_init_libraryinitialize the link library
    SIMLINK_init_messageinitialize a link message
    SIMLINK_pre_deleteclean-up before link deletion
    SIMLINK_register_classregister a link class
    SIMLINK_register_endpoint_classregister a link endpoint class
    SIMLINK_register_snoop_endpoint_classregister a link snoop endpoint class
    SIMLINK_send_messagesend a link message
    SIMLINK_send_message_multisend a link message to multiple recipients
    SIMLINK_snoop_endpoint_createcreate a snoop endpoint object
    SIM_ASSERT_CELL_CONTEXTassert Cell Context
    SIM_ASSERT_OBJECT_LOCKassert thread domain is held
    SIM_STC_flush_cacheflush or remove entries in the STCs of a cpu
    SIM_acquire_cellenter Cell Context
    SIM_acquire_objectacquire thread domain
    SIM_acquire_object_for_executionacquire object lock for execution
    SIM_acquire_targetconditionally enter Cell Context
    SIM_add_configurationset configuration from Python
    SIM_add_directoryadd directory to search path
    SIM_add_global_notifieradd a global notifier callback
    SIM_add_global_notifier_onceadd a global notifier callback
    SIM_add_module_diradd loadable module search path
    SIM_add_notifieradd a notifier callback
    SIM_add_output_handleradd or remove output handler
    SIM_alloc_attr_dictcreate empty attribute dictionary
    SIM_alloc_attr_listcreate uninitialized attribute list
    SIM_arm_mem_trans_from_genericconvert generic transaction to CPU specific
    SIM_ascanfparse list attribute values
    SIM_attr_booleanextract values stored in attr_value_t values
    SIM_attr_copycopy attribute value
    SIM_attr_dataextract values stored in attr_value_t values
    SIM_attr_data_sizeextract values stored in attr_value_t values
    SIM_attr_dict_keyextract values stored in attr_value_t values
    SIM_attr_dict_resizeresize dict attribute value
    SIM_attr_dict_set_itemset dict attribute element
    SIM_attr_dict_sizeextract values stored in attr_value_t values
    SIM_attr_dict_valueextract values stored in attr_value_t values
    SIM_attr_floatingextract values stored in attr_value_t values
    SIM_attr_freefree attribute
    SIM_attr_integerextract values stored in attr_value_t values
    SIM_attr_is_booleanattr_value_t type predicates
    SIM_attr_is_dataattr_value_t type predicates
    SIM_attr_is_dictattr_value_t type predicates
    SIM_attr_is_floatingattr_value_t type predicates
    SIM_attr_is_int64attr_value_t type predicates
    SIM_attr_is_integerattr_value_t type predicates
    SIM_attr_is_invalidattr_value_t type predicates
    SIM_attr_is_listattr_value_t type predicates
    SIM_attr_is_nilattr_value_t type predicates
    SIM_attr_is_objectattr_value_t type predicates
    SIM_attr_is_stringattr_value_t type predicates
    SIM_attr_is_uint64attr_value_t type predicates
    SIM_attr_listextract values stored in attr_value_t values
    SIM_attr_list_itemextract values stored in attr_value_t values
    SIM_attr_list_resizeresize list attribute value
    SIM_attr_list_set_itemset list attribute element
    SIM_attr_list_sizeextract values stored in attr_value_t values
    SIM_attr_objectextract values stored in attr_value_t values
    SIM_attr_object_or_nilextract values stored in attr_value_t values
    SIM_attr_scanfparse list attribute values
    SIM_attr_stringextract values stored in attr_value_t values
    SIM_attr_string_detachextract values stored in attr_value_t values
    SIM_attribute_errorspecify reason for attribute error
    SIM_break_cycleinsert breakpoint in time queue
    SIM_break_messagestop the simulation
    SIM_break_simulationstop the simulation
    SIM_break_stepset a step breakpoint
    SIM_breakpointset breakpoint
    SIM_breakpoint_removedelete breakpoint range
    SIM_c_attribute_errorspecify reason for attribute error
    SIM_c_get_class_interfaceget interface
    SIM_c_get_class_port_interfaceget interface
    SIM_c_get_interfaceget interface
    SIM_c_get_mem_op_value_bufget value for a memory operation
    SIM_c_get_port_interfaceget interface
    SIM_c_hap_occurredtrigger a hap occurrence
    SIM_c_hap_occurred_alwaystrigger a hap occurrence
    SIM_c_hap_occurred_always_varargtrigger a hap occurrence
    SIM_c_hap_occurred_varargtrigger a hap occurrence
    SIM_c_set_mem_op_value_bufset value for a memory operation
    SIM_call_python_functioncall a Python named function
    SIM_cancel_realtime_eventcancel callback in host time
    SIM_cbdata_dataget cbdata data pointer
    SIM_cbdata_typeget cbdata type pointer
    SIM_class_has_attributecheck if class implements attribute
    SIM_class_has_notifierquery class for notifier
    SIM_class_portcheck if class has specified port object
    SIM_clear_augmentation_bitconvenience functions to work with augmented memory bits
    SIM_clear_directoriesclear the search path
    SIM_clear_exceptionclear pending exception
    SIM_complete_transactioncomplete a deferred transaction
    SIM_continuerun the simulation
    SIM_copy_classcreate a copy of an existing class
    SIM_copyrightget Simics version and license/copyright information
    SIM_create_classcreate class
    SIM_create_objectcreate and initialize object
    SIM_current_checkpoint_dirdirectory of checkpoint being loaded
    SIM_current_clockreturn current clock
    SIM_cycle_countread cycle counter
    SIM_defer_owned_transactiondefer transaction completion using an existing transaction
    SIM_defer_transactiondefer transaction completion
    SIM_delete_breakpointdelete breakpoint
    SIM_delete_global_notifierdelete global notifier callback
    SIM_delete_notifierdelete notifier callback
    SIM_delete_objectdelete a list of objects
    SIM_delete_objectsdelete a list of objects
    SIM_delete_snapshotdelete a snapshot
    SIM_describe_notifierset short description
    SIM_describe_pseudo_exceptionreturn pseudo exception description
    SIM_disable_breakpointdisable breakpoint
    SIM_disassemble_addressdisassemble address
    SIM_drop_thread_domainstemporarily release all held thread domains
    SIM_enable_breakpointdisable breakpoint
    SIM_ensure_partial_attr_orderensure attribute order
    SIM_event_cancel_stepcancel an event before expiration
    SIM_event_cancel_timecancel an event before expiration
    SIM_event_class_flagsget event class flags
    SIM_event_find_next_cyclefind event expiration time
    SIM_event_find_next_stepfind event expiration time
    SIM_event_find_next_timefind event expiration time
    SIM_event_post_cyclepost an event
    SIM_event_post_steppost an event
    SIM_event_post_timepost an event
    SIM_extend_classextend class with contents from an extension class
    SIM_extension_dataget class extension data
    SIM_flushtext output routines
    SIM_flush_D_STC_logicalflush or remove entries in the STCs of a cpu
    SIM_flush_D_STC_physicalflush or remove entries in the STCs of a cpu
    SIM_flush_I_STC_logicalflush or remove entries in the STCs of a cpu
    SIM_flush_I_STC_physicalflush or remove entries in the STCs of a cpu
    SIM_flush_all_cachesclear Simics's internal caches
    SIM_flush_cell_cachesclear internal caches for a given cell
    SIM_free_attributefree attribute
    SIM_free_cbdatafree cbdata
    SIM_free_map_targetfree a map target
    SIM_get_all_classesget list of all loaded classes
    SIM_get_all_failed_modulesreturn a list of all modules that failed to load
    SIM_get_all_hap_typesget list of all hap types
    SIM_get_all_modulesreturn a list of all modules
    SIM_get_all_objectsget list of all objects
    SIM_get_all_processorsget list of all processors
    SIM_get_api_functionreturn an API function by name
    SIM_get_attributeget attribute
    SIM_get_attribute_attributesget attribute flags
    SIM_get_attribute_idxget attribute
    SIM_get_augmentation_bitconvenience functions to work with augmented memory bits
    SIM_get_batch_modereturn setting of the batch-mode
    SIM_get_classget class
    SIM_get_class_attributeget class attribute
    SIM_get_class_attribute_idxget class attribute
    SIM_get_class_dataget class data
    SIM_get_class_interfaceget interface
    SIM_get_class_nameget class name
    SIM_get_class_port_interfaceget interface
    SIM_get_debuggerreturn the debugger object
    SIM_get_directoriesget the current search path
    SIM_get_event_classget the event class
    SIM_get_global_messageobtain current global message
    SIM_get_init_arg_booleanget an argument that the Simics core was initialized with
    SIM_get_init_arg_stringget an argument that the Simics core was initialized with
    SIM_get_interfaceget interface
    SIM_get_mem_op_exceptionget/set transaction exception
    SIM_get_mem_op_ini_typeget/set transaction initiator
    SIM_get_mem_op_initiatorget/set transaction initiator
    SIM_get_mem_op_inquiryget/set transaction inquiry flag
    SIM_get_mem_op_page_crossdetect transaction split
    SIM_get_mem_op_physical_addressget or set transaction address
    SIM_get_mem_op_sizeget transaction size
    SIM_get_mem_op_typeget type of transaction
    SIM_get_mem_op_type_nameget name of memory operation type
    SIM_get_mem_op_user_dataget/set transaction user data
    SIM_get_mem_op_value_beget value for a memory operation
    SIM_get_mem_op_value_bufget value for a memory operation
    SIM_get_mem_op_value_cpuget value for a memory operation
    SIM_get_mem_op_value_leget value for a memory operation
    SIM_get_mem_op_virtual_addressget or set transaction address
    SIM_get_objectget object
    SIM_get_pending_exceptionget current pending exception
    SIM_get_port_interfaceget interface
    SIM_get_processorget processor pointer from number
    SIM_get_processor_numberget the number of a processor
    SIM_get_python_interface_typeget Python interface type
    SIM_get_quietreturn setting of the quiet flag
    SIM_get_snapshot_infoget information about a snapshot
    SIM_get_transaction_bytesget transaction data payload
    SIM_get_transaction_bytes_offsget transaction data payload
    SIM_get_transaction_idobtain checkpoint ID for a deferred a transaction
    SIM_get_transaction_value_beget transaction data payload
    SIM_get_transaction_value_leget transaction data payload
    SIM_get_verboseget the verbose flag
    SIM_hap_add_callbackinstall callback on a hap
    SIM_hap_add_callback_indexinstall callback on a hap
    SIM_hap_add_callback_objinstall callback on a hap
    SIM_hap_add_callback_obj_indexinstall callback on a hap
    SIM_hap_add_callback_obj_rangeinstall callback on a hap
    SIM_hap_add_callback_rangeinstall callback on a hap
    SIM_hap_add_typeregister a new hap type
    SIM_hap_delete_callbackdelete installed hap callback
    SIM_hap_delete_callback_iddelete installed hap callback
    SIM_hap_delete_callback_objdelete installed hap callback
    SIM_hap_delete_callback_obj_iddelete installed hap callback
    SIM_hap_get_nameget hap name by number
    SIM_hap_get_numberget hap number by name
    SIM_hap_is_activecheck if hap has callbacks
    SIM_hap_is_active_objcheck if hap has callbacks
    SIM_hap_is_active_obj_idxcheck if hap has callbacks
    SIM_hap_occurredtrigger a hap occurrence
    SIM_hap_occurred_alwaystrigger a hap occurrence
    SIM_hap_remove_typeremove a hap type
    SIM_has_notifierquery object for notifier
    SIM_init_command_lineinitialize the Simics command line
    SIM_init_environmentperform early initialization of the simulator
    SIM_init_simulator2perform initialization of the simulator
    SIM_inspect_address_routingtrack the route of a transaction through memory hierarchy
    SIM_inspect_breakpointsfind out breakpoints that a transaction would trigger
    SIM_is_loading_micro_checkpointobsolete API function
    SIM_is_restoring_snapshotcheck if a snapshot is currently being restored
    SIM_is_restoring_statecheck if state restoring phase
    SIM_issue_read_transactionfunctions for issuing transaction_t transactions
    SIM_issue_transactionissue transaction
    SIM_issue_write_transactionfunctions for issuing transaction_t transactions
    SIM_iter_addrIterate over address profile counters
    SIM_iter_freeIterate over address profile counters
    SIM_iter_nextIterate over address profile counters
    SIM_last_errorget error message from last frontend exception
    SIM_licenseget Simics version and license/copyright information
    SIM_license_fileget Simics version and license/copyright information
    SIM_list_snapshotslist snapshots
    SIM_load_binaryread an executable file into memory
    SIM_load_fileread a file into memory
    SIM_load_moduleload a module
    SIM_load_targetload Simics target from file
    SIM_log_criticaloutput log message
    SIM_log_erroroutput log message
    SIM_log_infooutput log message
    SIM_log_levelset and get log level
    SIM_log_messageoutput log message
    SIM_log_message_varargoutput log message
    SIM_log_register_groupsregister names of log groups
    SIM_log_spec_violationoutput log message
    SIM_log_unimplementedoutput log message
    SIM_lookup_filefind a file using simics search path
    SIM_main_looprun the Simics main loop
    SIM_make_attr_booleanmake boolean attribute
    SIM_make_attr_datacreate raw data attribute
    SIM_make_attr_data_adoptcreate raw data attribute
    SIM_make_attr_floatingmake floating point attribute
    SIM_make_attr_int64make integer attribute
    SIM_make_attr_invalidmake invalid attribute
    SIM_make_attr_listmake list attribute
    SIM_make_attr_list_varargmake list attribute
    SIM_make_attr_nilmake nil attribute
    SIM_make_attr_objectmake object attribute
    SIM_make_attr_stringmake string attribute
    SIM_make_attr_string_adoptmake string attribute
    SIM_make_attr_uint64make integer attribute
    SIM_make_cbdatacreate cbdata
    SIM_make_mem_op_readcreate a memory transaction
    SIM_make_mem_op_writecreate a memory transaction
    SIM_make_simple_cbdatacreate untyped cbdata
    SIM_map_target_flushensure that old translations are not used
    SIM_map_target_objectinspect a map target
    SIM_map_target_portinspect a map target
    SIM_map_target_targetinspect a map target
    SIM_marked_for_deletionis object being deleted
    SIM_mem_op_ensure_future_visibilityrequest transaction visibility
    SIM_mem_op_is_atomicdetect transaction atomicity
    SIM_mem_op_is_controltransaction control predicates
    SIM_mem_op_is_datatransaction data/instruction predicates
    SIM_mem_op_is_from_cacheCache initiated transaction
    SIM_mem_op_is_from_cpuCPU initiated transaction
    SIM_mem_op_is_from_cpu_archCPU initiated transaction
    SIM_mem_op_is_from_deviceDevice initiated transaction
    SIM_mem_op_is_instructiontransaction data/instruction predicates
    SIM_mem_op_is_prefetchtransaction control predicates
    SIM_mem_op_is_readtransaction read/write predicates
    SIM_mem_op_is_writetransaction read/write predicates
    SIM_mem_op_may_stalldetect transaction stall possibility
    SIM_mips_mem_trans_from_genericconvert generic transaction to CPU specific
    SIM_module_list_refreshrefresh list of loadable modules
    SIM_monitor_chained_transactionmonitor a transaction for deferred completion
    SIM_monitor_transactionmonitor a transaction for deferred completion
    SIM_native_pathconvert path to its native form
    SIM_new_map_targetcreate a map target
    SIM_notifier_descriptionset short description
    SIM_notifier_typeget notifier type
    SIM_notifytrigger notification callbacks
    SIM_notify_on_descriptorregister notification on host I/O events
    SIM_notify_on_objectregister notification on host I/O events
    SIM_notify_on_socketregister notification on host I/O events
    SIM_number_processorsnumber of processors
    SIM_object_classget object class
    SIM_object_clockget object clock
    SIM_object_dataget object-specific data pointer
    SIM_object_descendantreturn a descendant of the specified object
    SIM_object_idget object identifier
    SIM_object_is_configuredget/set configured status
    SIM_object_is_processortest if object is a processor
    SIM_object_iteratorstart object iteration
    SIM_object_iterator_for_classstart class instance iteration
    SIM_object_iterator_for_interfacestart class instance iteration
    SIM_object_iterator_nextget next object
    SIM_object_nameget object name
    SIM_object_parentget object parent
    SIM_pci_mem_trans_from_genericconvert generic transaction to CPU specific
    SIM_picosecond_clockget object picosecond clock
    SIM_poll_transactioncheck if a transaction has completed
    SIM_port_object_parentget object parent
    SIM_ppc_mem_trans_from_genericconvert generic transaction to CPU specific
    SIM_printftext output routines
    SIM_printf_errorprint error message
    SIM_printf_error_varargprint error message
    SIM_printf_varargtext output routines
    SIM_printf_warningprint warning message
    SIM_printf_warning_varargprint warning message
    SIM_process_pending_workrun the Simics main loop
    SIM_process_workrun the Simics main loop
    SIM_processor_privilege_levelreturn the current privilege level for a processor
    SIM_putchartext output routines
    SIM_putstext output routines
    SIM_quitquit Simics
    SIM_reacquire_thread_domainstemporarily release all held thread domains
    SIM_read_byteread/write byte from a memory space
    SIM_read_configurationread configuration
    SIM_read_phys_memoryread data from a physical address
    SIM_read_phys_memory_tagsaccess auxiliary bits in physical memory
    SIM_realtime_eventschedule callback in host time
    SIM_reconnect_transactionregister that a deferred transaction has been restored
    SIM_register_attributeregister attribute
    SIM_register_attribute_with_user_dataregister attribute
    SIM_register_classregister class
    SIM_register_class_aliasregister class alias
    SIM_register_class_attributeregister attribute
    SIM_register_class_attribute_with_user_dataregister attribute
    SIM_register_clockregister mandatory interface and attributes for clock objects
    SIM_register_compatible_interfacesregister earlier versions of interface
    SIM_register_context_handlerregister mandatory interface and attribute for context handler objects
    SIM_register_copyrightregister copyright information
    SIM_register_eventregister an event
    SIM_register_interfaceregister interface
    SIM_register_notifierregister notifier
    SIM_register_portregister port class
    SIM_register_port_interfaceregister interface
    SIM_register_python_atom_typeregister an atom type which takes plain Python objects
    SIM_register_simple_portregister port
    SIM_register_tracked_notifierregister notifier
    SIM_register_typed_attributeregister attribute
    SIM_register_typed_class_attributeregister attribute
    SIM_register_workregister function to be called in Global Context
    SIM_release_cellenter Cell Context
    SIM_release_objectacquire thread domain
    SIM_release_targetconditionally enter Cell Context
    SIM_remove_output_handleradd or remove output handler
    SIM_replace_transactionreplace transaction
    SIM_require_objectmake sure an object is fully configured
    SIM_reset_processorreset the processor
    SIM_restore_snapshotrestore a snapshot of the configuration state
    SIM_run_aloneregister function to be called in Global Context
    SIM_run_async_worklaunch asynchronous work in a separate thread
    SIM_run_commandevaluate a CLI command
    SIM_run_command_fileread CLI commands from file
    SIM_run_command_file_paramsread CLI commands from file
    SIM_run_in_threadrun function in a separate thread
    SIM_run_pythonrun a Python expression
    SIM_run_unrestrictedrun callback after current instruction
    SIM_set_attributeset attribute
    SIM_set_attribute_defaultset default value for an attribute in a child object
    SIM_set_attribute_idxset attribute
    SIM_set_augmentation_bitconvenience functions to work with augmented memory bits
    SIM_set_class_attributeset class attribute
    SIM_set_class_attribute_idxset class attribute
    SIM_set_class_dataset class data
    SIM_set_configurationset configuration from data
    SIM_set_frontend_contextregister a stack context buffer for Simics to longjmp back to
    SIM_set_log_levelset and get log level
    SIM_set_mem_op_exceptionget/set transaction exception
    SIM_set_mem_op_initiatorget/set transaction initiator
    SIM_set_mem_op_inquiryget/set transaction inquiry flag
    SIM_set_mem_op_physical_addressget or set transaction address
    SIM_set_mem_op_reissuerequest transaction reissue
    SIM_set_mem_op_typeset type of transaction
    SIM_set_mem_op_user_dataget/set transaction user data
    SIM_set_mem_op_value_beset value for a memory operation
    SIM_set_mem_op_value_bufset value for a memory operation
    SIM_set_mem_op_value_cpuset value for a memory operation
    SIM_set_mem_op_value_leset value for a memory operation
    SIM_set_mem_op_virtual_addressget or set transaction address
    SIM_set_object_configuredget/set configured status
    SIM_set_quietenable/disable quiet mode
    SIM_set_transaction_bytesset transaction data payload
    SIM_set_transaction_bytes_constantset transaction data payload
    SIM_set_transaction_bytes_offsset transaction data payload
    SIM_set_transaction_value_beset transaction data payload
    SIM_set_transaction_value_leset transaction data payload
    SIM_set_verboseenable/disable verbose mode
    SIM_shallow_object_iteratorstart object iteration
    SIM_shutdownshutdown Simics
    SIM_simics_is_runningcheck if simulation is running
    SIM_source_pythonexecute Python source file
    SIM_source_python_in_moduleexecute Python source file
    SIM_stallstall execution a specified number of cycles
    SIM_stall_countget number of cycles a processor has been stalled
    SIM_stall_cyclestall execution a specified number of cycles
    SIM_stalled_untilquery how many cycles that remains of stall
    SIM_step_countget step count
    SIM_take_snapshottake snapshot of the current configuration
    SIM_thread_safe_callbackregister function to be called in Global Context
    SIM_timeget current simulated time
    SIM_transaction_flagsreturn transaction type
    SIM_transaction_initiatorreturn transaction initiator
    SIM_transaction_is_deferrablecheck if a transaction can be deferred for later completion
    SIM_transaction_is_fetchreturn transaction type
    SIM_transaction_is_inquiryreturn transaction type
    SIM_transaction_is_readreturn transaction type
    SIM_transaction_is_writereturn transaction type
    SIM_transaction_sizereturn transaction size
    SIM_transaction_waitwait for transaction completion
    SIM_translation_changedensure that old translations are not used
    SIM_trigger_global_messagequeue up a global message
    SIM_versionget Simics version and license/copyright information
    SIM_version_baseget Simics version and license/copyright information
    SIM_version_majorget Simics version and license/copyright information
    SIM_vmxmon_versionget Simics version and license/copyright information
    SIM_writetext output routines
    SIM_write_byteread/write byte from a memory space
    SIM_write_configuration_to_filewrite configuration
    SIM_write_persistent_statesave persistent state
    SIM_write_phys_memorywrite data to a physical address
    SIM_write_phys_memory_tagsaccess auxiliary bits in physical memory
    SIM_x86_mem_trans_from_genericconvert generic transaction to CPU specific
    SIM_yield_thread_domainsyield held thread domains
    VT_check_async_eventscheck for asynchronous events
    VT_clock_frequency_about_to_changeinform before clock frequency change
    VT_clock_frequency_changeinform after clock frequency change
    VT_new_code_blockinform platform of new code block
    VT_set_object_clockset clock association for object
    VT_stop_event_processingstop event processing
    dbuffer_appendAdd data to a dbuffer
    dbuffer_append_external_dataAdd static data
    dbuffer_append_valueAdd data with uniform content
    dbuffer_cloneMake a full copy of another buffer
    dbuffer_copy_appendCopy data from a dbuffer
    dbuffer_copy_prependCopy data from a dbuffer
    dbuffer_freeRelease a dbuffer
    dbuffer_insertAdd data to a dbuffer
    dbuffer_lenGet the size of a dbuffer
    dbuffer_prependAdd data to a dbuffer
    dbuffer_prepend_external_dataAdd static data
    dbuffer_prepend_valueAdd data with uniform content
    dbuffer_readExtract data for reading
    dbuffer_read_allExtract data for reading
    dbuffer_read_someExtract data for reading
    dbuffer_removeRemove data from a dbuffer
    dbuffer_remove_headRemove data from a dbuffer
    dbuffer_remove_tailRemove data from a dbuffer
    dbuffer_replaceReplace data
    dbuffer_replace_allReplace data
    dbuffer_replace_someReplace data
    dbuffer_splitSplit a dbuffer
    dbuffer_updateExtract data for updating
    dbuffer_update_allExtract data for updating
    dbuffer_update_someExtract data for updating
    frags_addadd data to a frags_t
    frags_add_from_fragsappend an existing frags_t to another
    frags_extractextract the contents of a frags_t
    frags_extract_8extract a value
    frags_extract_allocreturn a copy of the contents of a frags_t
    frags_extract_be16extract a value
    frags_extract_be32extract a value
    frags_extract_be64extract a value
    frags_extract_le16extract a value
    frags_extract_le32extract a value
    frags_extract_le64extract a value
    frags_extract_sliceextract a slice of a frags_t
    frags_extract_slice_allocreturn a partial copy of the contents of a frags_t
    frags_initinitialize a frags_t
    frags_init_addinitialize a frags_t with an initial value
    frags_init_add_from_fragsinitialize a frags_t from another
    frags_itreturn an iterator
    frags_it_datareturn the data of the current fragment
    frags_it_endreturn whether an iterator is finished
    frags_it_lenreturn the length of the current fragment
    frags_it_nextreturn the next fragment's iterator
    frags_lenreturn the total data length
    frags_prefixprefix a frags_t with a header
    frags_suffixappend a suffix to a frags_t
    new_dbufferCreate a new dbuffer

    12 Haps

    Arinc429_Word

    Description
    This hap is triggered on every word sent on a arinc429_bus object. In the hap handler, the last_word attribute can be read or modified. Setting it to -1 will drop the packet.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    CLI_Command_Added

    Description
    Triggered when a CLI command is defined.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, char *command_name);

    Component_Change

    Description
    Internal: Similar to Component_Hierarchy_Change but also triggered for components that are not part of any complete hierarchy including non-instantiated components.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Component_Hierarchy_Change

    Description
    Internal: Triggered when an instantiated component hierarchy is modified. The hap is associated with the top-level component of the modified hierarchy.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, 
             conf_object_t *top_level_component);

    Console_Break_String

    Description
    Triggered when the output matches a string set to break on. The break_id is the number associated with the string breakpoint.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, char *break_string);

    Index
    break_id

    Core_Address_Not_Mapped

    Description
    Triggered when an access to a memory-space has no target and the access does not match any entry in the outside_memory_whitelist CPU attribute. The default handler for this hap will signal an error and stop the simulation.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, 
             int64 physical_address, int64 access_type, 
             int64 size);

    Core_Asynchronous_Trap

    Description
    SPARC: Triggered when an asynchronous trap occurs. This is either an external interrupt trap number == 0x60 or interrupt level n trap number 0x41 - 0x4F, or an asynchronous trap initiated by the user calling trap_cpu in the sparc-interrupt interface. The Core_External_Interrupt can also be used to catch interrupts, the difference is that Core_Asynchronous_Trap is only triggered if interrupts are enabled.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 trap_number);

    Index
    trap_number

    Core_At_Exit

    Description
    Triggered, typically by SIM_quit, when Simics exits. The Simics API is not allowed to be used in the hap callbacks (see the Core_Clean_At_Exit hap description if access to the Simics API is needed).
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Breakpoint_Change

    Description
    Triggered on an object when breakpoints attached to that object are inserted, deleted or changed in any way.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Breakpoint_Memop

    Description
    Triggered when a breakpoint is triggered. breakpoint_number is the breakpoint number (as returned by SIM_breakpoint). If there are multiple breakpoints on an instruction then all installed haps will be run before control is transferred to the frontend (when applicable). The supplied memop can be used to figure out details about the transaction.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, 
             int64 breakpoint_number, 
             generic_transaction_t *memop);

    Index
    breakpoint_number

    Core_Clean_At_Exit

    Description
    Triggered, typically by SIM_quit, if Simics exits cleanly, i.e. in Global Context. The Simics API is available. Cleanup code should typically run in the Core_At_Exit hap callbacks instead if possible.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Conf_Class_Register

    Description
    Triggered when a new configuration class has been registered. Called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, char *class_name);

    Core_Conf_Class_Unregister

    Description
    Triggered when a configuration class has been unregistered. Called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, char *class_name);

    Core_Conf_Clock_Change_Cell

    Description
    Triggered when a clock object changes cell
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, 
             conf_object_t *old_cell, conf_object_t *new_cell);

    Core_Conf_Object_Change_Clock

    Description
    Triggered when an object's reference clock is changed
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, 
             conf_object_t *old_clock, 
             conf_object_t *new_clock);

    Core_Conf_Object_Create

    Description
    Triggered when a new configuration object's init_object method returns successfully, but before the object's attributes are set and before the object's finalize_instance method is called. Since the object is not fully created hap callbacks must not access any of the object's attributes or call any methods on the object's interfaces. Callbacks are called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Conf_Object_Created

    Description
    Triggered when a configuration object has been created and finalized. This hap will always be followed by a Core_Conf_Objects_Created hap, but this hap can be triggered for more than one object before the Core_Conf_Objects_Created hap.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Conf_Object_Delete

    Description
    Triggered after a configuration object has been deleted. Called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, char *object_name);

    Core_Conf_Object_Pre_Delete

    Description
    Triggered just before a configuration object is deleted. Called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Conf_Object_Rename

    Description
    Triggered after an object's name has changed. Called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, char *old_name);

    Core_Conf_Objects_Created

    Description
    Triggered if and only if at least one Core_Conf_Object_Created hap has been triggered.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Conf_Objects_Deleted

    Description
    Triggered when one or more objects have been deleted from the configuration after the Core_Conf_Object_Delete hap has been triggered for all of the objects. Called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Configuration_Loaded

    Description
    Triggered when a configuration has been loaded. This hap can be triggered several times during a session since it is possible to append a new configuration to the existing one. In most cases it is better to use the finalize_instance function in the class_data_t instead. That function is called when the object creation is finished. Callbacks are called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Context_Activate

    Description
    Triggered when this context replaces another context as the current context of a processor.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, 
             conf_object_t *other_ctx, conf_object_t *cpu);

    Core_Context_Change

    Description
    Triggered when the context is set to the current context for a processor.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, conf_object_t *cpu);

    Core_Context_Deactivate

    Description
    Triggered when another context replaces this context as the current context of a processor.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, 
             conf_object_t *other_ctx, conf_object_t *cpu);

    Core_Context_Updated

    Description
    Triggered when the context is updated in some way.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Continuation

    Description
    Triggered at the (re)start of the simulation. The Core_Simulation_Stopped hap is called when the simulation is stopped. Callbacks are called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Control_Register_Read

    Description
    Triggered when a control register is read. The hap is called before the read is performed; thus no registers have been modified.

    Note that if the callback routine breaks to the frontend by raising an exception, the instruction will be replayed possibly causing repeated memory operations.

    For x86 processors, this hap is triggered when a control register is read using a mov or smsw instruction (i.e. only explicit reads). Also the hap is triggered when MSRs are read with rdmsr, rdtsc or rdtscp instructions.

    For PowerPC processors, this hap is triggered by the mfspr, mfmsr mfsr and mfsrin instructions (i.e. only explicit reads).

    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 register_number);

    Index
    register_number

    Core_Control_Register_Write

    Description
    Triggered when a control register is written. Note that value is not (necessarily) the final contents in the register. When the callback is called, the processor register has not yet been updated with the new value.

    If the callback routine breaks to the frontend by raising an exception, the instruction will be replayed possibly causing repeated memory operations.

    For x86 processors, this hap is triggered by clts, lmsw, and mov. Also the hap is triggered when MSRs are written with wrmsr instruction. Page fault updates of CR2 should be caught with the Core_Exception hap.

    For PowerPC processors, this hap is triggered by the mtspr, mtmsr, mtsr and mtsrin instructions (i.e. only explicit writes).

    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 register_number, 
             int64 value);

    Index
    register_number

    Core_Device_Access_Memop

    Description
    Triggered when a device access is performed.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, 
             generic_transaction_t *memop);

    Core_DSTC_Flush_Counter

    Description
    Triggered when the DSTC flushes a line's hit counter. It reports how many hits the STC recorded since the line was inserted.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 type, 
             int64 virtual_address, int64 physical_address, 
             int64 counter);

    Core_Exception

    Description
    Triggered when an exception/trap is taken by a processor. The hap occurs before side-effects, control transfers included, have taken place.

    Interrupting the simulation by calling SIM_break_simulation inside the hap will cause the simulation to stop right before the exception (and the trapping instruction, if any). The simulation state will then be as it was prior to the execution of the instruction or exception. Continuing the simulation will then re-run the exception, this time without calling hap functions.

    Depending on the processor model, some state may actually have changed in an idempotent way when the hap occurs, but this should not be relied upon.

    The exact meaning of the exception number depends on the simulated processor architecture. The exception interface can be used to translate the number to an exception name.

    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, 
             int64 exception_number);

    Index
    exception_number

    Core_Exception_Return

    Description
    Triggered when an exception/trap handler finishes execution. The hap is triggered before any processor state has changed.

    The following instructions trigger this hap (by processor class):

    MIPS: eret and deret

    PowerPC (32): rfi and rfci

    PowerPC (64): rfi, rfid and hrfid

    SH: rte

    SPARC: done and retry

    x86/x86-64: The iret family.

    The exception_number parameter is only valid for SPARC processors.

    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, 
             int64 exception_number);

    Index
    exception_number

    Core_External_Interrupt

    Description
    (SPARC only) Triggered when a processor receives an external interrupt. The trigger object is the receiving cpu, and source_mid is the mid of the sending cpu/device. The hap will be triggered even if interrupts are disabled, but not if the interrupt logic is busy.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 source_mid);

    Index
    source_mid

    Core_Frequency_Changed

    Description
    Triggered when the frequency of a cycle queue has changed. Parameters are the old and new frequencies in Hz.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 old_freq, 
             int64 new_freq);

    Core_Hap_Callback_Installed

    Description
    Triggered before a callback is installed. The callback called by this hap is not allowed to install any hap callbacks.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 hap_number, 
             int64 range_low, int64 range_high);

    Index
    hap_number

    Core_Hap_Callback_Removed

    Description
    Triggered after a callback has been unregistered. The callback called by this hap is not allowed to remove any hap callbacks.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 hap_number, 
             int64 range_low, int64 range_high);

    Index
    hap_number

    Core_Hap_Type_Added

    Description
    Triggered when a new hap type is added to the simulator. The hap is not triggered for the initial set of core haps. Callbacks called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, char *hap_name);

    Core_Image_Activity

    Description
    Triggered on I/O activity in an image object.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int type, int onoff);

    Core_Log_Groups_Change

    Description
    Triggered when the active log groups of an object changes
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int log_group_mask);

    Core_Log_Level_Change

    Description
    Triggered when the log level of an object changes
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int new_log_level);

    Core_Log_Message

    Description
    Triggered when a log message is registered that is supposed to be logged, i.e. with matching type and group(s) and level.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int type, 
             char *message);

    Index
    log type

    Core_Log_Message_Always

    Description
    Triggered always when a log message is registered regardless of the current log level
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int type, 
             char *message, int level, int64 group);

    Core_Log_Message_Extended

    Description
    Triggered when a log message is registered that is supposed to be logged according to the log level.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int type, 
             char *message, int level, int64 group);

    Core_Log_Message_Filtered

    Description
    Triggered when a log message is registered that is supposed to be logged, i.e. with matching type and group(s) and level.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int type, 
             char *message, int level, int64 group);

    Core_Magic_Instruction

    Description
    Triggered when Simics executes a magic instruction. The parameter is taken from the instruction and is architecture-dependent.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 parameter);

    Index
    parameter

    Core_Memory_Space_Map_Changed

    Description
    Experimental
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Mode_Change

    Description
    Triggered when a processor changes privilege mode for whatever reason; usually an exception or return from an exception. The hap occurs after the processor has changed mode but before any instructions have been executed in the new mode.

    For x86 processors, the modes are Sim_CPU_Mode_User for CPL 3, and Sim_CPU_Mode_Supervisor for CPL 0-2.

    For other processors, the modes are Sim_CPU_Mode_User or Sim_CPU_Mode_Supervisor. Some processors also has the Sim_CPU_Mode_Hypervisor mode.

    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 old_mode, 
             int64 new_mode);

    Core_Module_Loaded

    Description
    Triggered when a module is loaded into Simics. Called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, char *module_name);

    Core_Multicore_Acceleration_Changed

    Description
    Triggered when the multicore-accelerator feature is enabled or disabled.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int on/off);

    Core_Multithreading_Changed

    Description
    Triggered when multithreaded simulation is enabled or disabled.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int on/off);

    Core_Not_Implemented

    Description
    Triggered when the simulator encounters unimplemented functionality.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int line, char *file, 
             char *rcsid, char *message, int64 data);

    Core_Preferences_Changed

    Description
    Triggered when an attribute in the prefs object is written. Called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Processor_Schedule_Changed

    Description
    Triggered when the scheduling order of the processors has changed. Called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Project_Changed

    Description
    Triggered when a new Simics project directory is selected. Called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_Simulation_Mode_Change

    Description
    Triggered when the simulation mode for the processor has changed.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int simulation_mode);

    Index
    simulation_mode

    Core_Simulation_Stopped

    Description
    Triggered when the simulation stops. The exception argument will always be SimExc_No_Exception, and error_string will always be NULL. After this hap, simulation will not advance (triggering Core_Continuation) until SIM_continue is called again. Callbacks are called in Global Context.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 exception, 
             char *error_string);

    Index
    exception

    Core_Sync_Instruction

    Description
    Triggered when an synchronizing instruction is executed. The type parameter describe what kind of instruction is executing. Its encoding is specific to each architecture.

    For SH, this hap is triggered when a synco instruction is executed. The type contains 0.

    For SPARC-V9, this hap is triggered when a membar or stbar instruction is executed. For membar, the type contains the 7-bit field cmask|mmask specified in the instruction. For stbar, the type is 8 (equivalent to membar #StoreStore).

    For x86, this hap is triggered when a fence instruction is executed. The type is set from the list provided by the x86_sync_instruction_type_t enum.

    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 type);

    Index
    type

    Core_Timing_Model_Change

    Description
    Triggered on an object when a timing model or snoop device is inserted, deleted, or changed.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Core_User_Comments_Changed

    Description
    Triggered when the list of user comments for a session has changed
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Eth_Injector_Pcap_Eof

    Description
    Triggered by the eth_injector object when all contents of the pcap file has been sent. The callback function will have the pcap file name, next packet index, total number of packets in the pcap file, and auto-restart as arguments.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, char *pcap_file, 
             int num_injected, int pcap_num_pkgs, 
             int auto_restart);

    Firewire_Reset

    Description
    Triggered when the bus is reset. It is invoked after calculating the default topology. During the hap the self_ids attribute can be used to change the self id packets sent to the devices on the bus. The connected_devices attribute can also be changed to modify the mapping from physical id to device.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Firewire_Transfer

    Description
    Triggered when an packet travels through a firewire bus. During the hap handler the current_transfer attribute of the bus can be used to inspect and/or change the current transfer. If you set it to NULL the transfer is aborted and Firewire_V2_Ack_No_Ack is returned to the initiator of the transfer.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Gfx_Break

    Description
    Triggered when a graphical breakpoint matches the screen. break_id is the number returned when a breakpoint is set.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 gfx_break);

    Index
    break_id

    Internal_Break_IO

    Description
    Simics internal. Triggered on a break-io access.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int break-id);

    Internal_Device_Reg_Access

    Description
    Simics internal. Triggered on an access to a device register traced with trace-io command.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, 
             generic_transaction_t *memop, char *port, int idx, 
             int func, int64 offset);

    Internal_SB_Wait

    Description
    Simics internal
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Index
    id

    Internal_Time_Quantum_Changed

    Description
    Simics internal. Triggered when the time quantum has changed. The hap is supported in Simics 5 even though it is marked as internal.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);

    Realtime_Enabled

    Description
    Internal: Notifies change of realtime enabled status
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int enabled);

    RTC_Nvram_Update

    Description
    This hap is triggered when the DS12887-c NVRAM memory is changed.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 index, 
             int64 old_value, int64 new_value);

    Index
    index

    SCSI_Disk_Command

    Description
    Triggered when a SCSI command is received by a SCSI device. The parameters start and len are only used for read and write commands.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 command_number, 
             int64 start, int64 len);

    Index
    command_number

    SN_NAPT_Enabled

    Description
    Triggered when NAPT is enabled or disabled in a service-node.The argument is 0 when disabled and 1 when enabled.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int enabled);

    TLB_Fill_Data

    Description
    Triggered when a TLB entry is filled after a table walk. Page size encoding: 0==4k, 1==2M, 2==4M, 3==1G.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 linear, 
             int64 physical, int64 page_size);

    Index
    page_size

    TLB_Fill_Instruction

    Description
    Triggered when a TLB entry is filled after a table walk. Page size encoding: 0==4k, 1==2M, 2==4M, 3==1G.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 linear, 
             int64 physical, int64 page_size);

    Index
    page_size

    TLB_Invalidate_Data

    Description
    Triggered when a TLB entry is invalidated. The invalidation can be caused by an INVLPG instruction, a write to CR3, or by changes to paging bits in CR0 and CR4. Page size encoding: 0==4k, 1==2M, 2==4M, 3==1G.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 linear, 
             int64 physical, int64 page_size);

    Index
    page_size

    TLB_Invalidate_Instruction

    Description
    Triggered when a TLB entry is invalidated. The invalidation can be caused by an INVLPG instruction, a write to CR3, or by changes to paging bits in CR0 and CR4. Page size encoding: 0==4k, 1==2M, 2==4M, 3==1G.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 linear, 
             int64 physical, int64 page_size);

    Index
    page_size

    TLB_Miss_Data

    Description
    Triggered when a DTLB miss occurs.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 linear_address);

    Index
    linear_address

    TLB_Miss_Instruction

    Description
    Triggered when an ITLB miss occurs.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 linear_address);

    Index
    linear_address

    TLB_Replace_Data

    Description
    This hap is triggered when a TLB entry is replaced by another. The parameters relate to the old entry, and the insertion of the new entry will trigger a fill hap. Page size encoding: 0==4k, 1==2M, 2==4M, 3==1G.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 linear, 
             int64 physical, int64 page_size);

    Index
    page_size

    TLB_Replace_Instruction

    Description
    This hap is triggered when a TLB entry is replaced by another. The parameters relate to the old entry, and the insertion of the new entry will trigger a fill hap. Page size encoding: 0==4k, 1==2M, 2==4M, 3==1G.
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, int64 linear, 
             int64 physical, int64 page_size);

    Index
    page_size

    UI_Run_State_Changed

    Description
    Triggered when the run state changes; not triggered in batch mode. The argument is one of:
    "Stopped"
    simulation stopped and may not run
    "Stopped_Fwd"
    stopped and may run forward
    "Forwarding"
    simulation is running forward

    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj, char *state);

    Vga_Refresh_Triggered

    Description
    Triggered before picture on screen is updated
    Callback Type
    void (*)(lang_void *callback_data, 
             conf_object_t *trigger_obj);