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 |
String | const char * | str or unicode |
Integer | int64 or uint64 | int or long |
Boolean | bool | bool |
Floating | double | 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 |
Destructor | SIM_attr_free |
Type predicate | SIM_attr_is_TYPE |
Access | SIM_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.
typedef struct { uint8 *data; size_t len; } buffer_t;
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.
typedef struct { const uint8 *data; size_t len; } bytes_t;
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 a string of bytes.
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;
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.
lang_void
, SIM_make_cbdata,
SIM_make_simple_cbdata, SIM_free_cbdata,
SIM_cbdata_data, SIM_cbdata_type
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;
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:
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.
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;
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
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.
typedef enum { Sim_DI_Instruction = 0, Sim_DI_Data = 1 } data_or_instr_t;
typedef enum { Sim_Endian_Target, Sim_Endian_Host_From_BE, Sim_Endian_Host_From_LE } endianness_t;
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.
typedef enum { SIM_PSEUDO_EXC(SIM_PSEUDO_EXC_ENUM) } exception_type_t;
Sim_PE_No_Exception
, indicating that no error
has occurred. Pseudo exceptions are used by devices, memory spaces, and
Simics internally.
generic_transaction_t
represents a memory transaction. It should only be accessed via the accessor
functions documented in Device API Functions, Core, Memory
Transactions.
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;
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:
typedef int hap_type_t;
hap_type_t
can be made.
typedef struct { const char *name; bool boolean; union { const char *string; bool enabled; } u; } init_arg_t;
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
.
The int
n types are defined to be signed
integers of exactly
n
bits. The
uint
n 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.
integer_t
and uinteger_t
are equivalent to
int64
and uint64
, respectively, and are kept
for compatibility only; they should not be used in new code.
typedef void lang_void;
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.
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.
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;
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.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).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
.
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; const void *breakpoint_query_interface; 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;
typedef struct map_target map_target_t;
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.
In Python, the fields obj
, port
and target
are
exposed as read-only attributes, corresponding to the arguments given to
SIM_new_map_target when the map target was created.
translator_interface_t
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;
generic_transaction_t
, and SIM_set_mem_op_type()
is used to set it.
generic_transaction_t
,
/* 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;
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):
typedef enum { Sim_CPU_Mode_User = 0, Sim_CPU_Mode_Supervisor = 1, Sim_CPU_Mode_Hypervisor } processor_mode_t;
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
.
typedef enum { Sim_RW_Read = 0, Sim_RW_Write = 1 } read_or_write_t;
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;
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.
typedef int64 simtime_t;
typedef simtime_t cycles_t;
typedef simtime_t pc_step_t;
typedef int64 nano_secs_t;
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
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 { 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;
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;
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;
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;
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;
typedef enum { Arm_Transient_True, Arm_Transient_False, Arm_Transient_Unknown } arm_mem_transient_t;
typedef enum { Arm_MemType_Normal, Arm_MemType_Device } arm_mem_type_t;
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;
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;
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.
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;
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;
,
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;
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.
i2c_link_interface_t
,
i2c_master_interface_t
, i2c_slave_interface_t
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;
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.interrupt_subscriber_interface_t
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;
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.
typedef struct nios_memory_transaction { /* generic transaction */ generic_transaction_t s; } nios_memory_transaction_t;
generic_transaction_t
).
typedef struct pci_memory_transaction pci_memory_transaction_t;
pci_memory_transaction_t
is used for memory accesses
initiated by PCI devices.
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.generic_transaction_t
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;
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;
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.
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;
typedef enum serial_peripheral_interface_flags { SPI_Flags_CPHA = 0x1, SPI_Flags_CPOL = 0x2 } serial_peripheral_interface_flags_t;
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.
serial_peripheral_interface_slave_interface_t
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;
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.
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;
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;
typedef enum { X86_SFence = 1, X86_LFence = 2, X86_MFence = 3 } x86_sync_instruction_type_t;
Core_Sync_Instruction
hap.
typedef struct xtensa_memory_transaction { /* generic transaction */ generic_transaction_t s; } xtensa_memory_transaction_t;
generic_transaction_t
).