Model to Model Interfaces
Name
a20 — access the A20 line
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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"
Python
import simics
class simics.a20_interface_t(set_a20_line=None, get_a20_line=None)
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.
Execution Context
Cell Context for all methods.
Name
aarch64_sysreg — interface for accessing system registers of AArch64 systems
Synopsis
C and DML
#include <simics/arch/arm.h> // in C
import "simics/arch/arm.dml"; // in DML
SIM_INTERFACE(aarch64_sysreg) {
uint64 (*read_register)(conf_object_t *obj,
int op0, int op1, int crn, int crm,
int op2, bool inquiry);
void (*write_register)(conf_object_t *obj,
int op0, int op1, int crn, int crm,
int op2, uint64 value);
};
#define AARCH64_SYSREG_INTERFACE "aarch64_sysreg"
Python
import simics
class simics.aarch64_sysreg_interface_t(read_register=None, write_register=None)
Description
This is an interface that provides access to AArch64 system registers on an external device using the encoding tuple (op0, op1, CRn, CRm, op2)
The read_register function reads a system register identified by its encoding. If inquiry is true, the read must not have side effects.
The write_register function writes value to the system register identified by its encoding.
Execution Context
Cell Context for all methods.
Name
apic_destination_mode_t, apic_delivery_mode_t, apic_trigger_mode_t, apic_bus_status_t, apic_bus — interface for apic buses
Synopsis
C and DML
#include <simics/devs/apic.h> // in C
import "simics/devs/apic.dml"; // in DML
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;
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"
Python
import simics
simics.Apic_Destination_Mode_Logical
simics.Apic_Destination_Mode_Physical
simics.Apic_Delivery_Mode_Start_Up
simics.Apic_Delivery_Mode_NMI
simics.Apic_Delivery_Mode_Fixed
simics.Apic_Delivery_Mode_Lowest_Priority
simics.Apic_Delivery_Mode_INIT
simics.Apic_Delivery_Mode_Ext_INT
simics.Apic_Delivery_Mode_SMI
simics.Apic_Delivery_Mode_Remote_Read
simics.Apic_Trigger_Mode_Edge
simics.Apic_Trigger_Mode_Level
simics.Apic_Bus_Invalid
simics.Apic_Bus_Retry
simics.Apic_Bus_Accepted
simics.Apic_Bus_No_Target
class simics.apic_bus_interface_t(interrupt=None)
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.
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.
Name
apic_bus_to_apic — This interface is provided by APIC to APIC bus
Synopsis
C and DML
SIM_INTERFACE(apic_bus_to_apic) {
uint32 (*get_arbitration_id)(conf_object_t *obj);
void (*set_arbitration_id)(conf_object_t *obj, uint32 val);
uint32 (*get_arbitration_priority)(conf_object_t *obj);
uint32 (*get_processor_priority)(conf_object_t *obj);
uint32 (*get_apr)(conf_object_t *obj);
uint32 (*get_lvt_lint0)(conf_object_t *obj);
apic_type_t (*get_apic_type)(conf_object_t *obj);
uint32 (*get_apic_id)(conf_object_t *obj);
bool (*get_ack_in_progress)(conf_object_t *obj);
void (*set_pin_status)(conf_object_t *obj, x86_pin_t pin, int status);
bool (*has_physical_destination)(conf_object_t *obj,
uint32 destination,
bool exclude,
uint32 exclude_id);
bool (*has_logical_destination)(conf_object_t *obj, uint32 destination);
bool (*is_focus)(conf_object_t *obj, uint8 vector);
bool (*is_interrupt_slot_available)(conf_object_t *obj, uint8 vector);
void (*remote_read)(conf_object_t *obj, uint8 vector);
void (*do_lower_ext_int)(conf_object_t *obj);
void (*start_up)(conf_object_t *obj, uint32 start_address);
#ifndef PYWRAP
void (*interrupt)(conf_object_t *obj,
apic_delivery_mode_t delivery_mode,
bool level_assert,
apic_trigger_mode_t trigger_mode,
uint8 vector,
interrupt_ack_fn_t ack_func,
conf_object_t *ack_func_arg);
#endif
};
#define APIC_BUS_TO_APIC_INTERFACE "apic_bus_to_apic"
Description
get_arbitration_id and set_arbitration_id methods are used to get/set value of the 4-bit software-transparent arbitration id register of the LAPIC.
get_apic_type method is used to get type of the certain APIC. Also APIC has an attribute apic_type which indicate APIC’s type. The type of APIC is one of the constants defined in apic_type_t.
There are 3 types of the APIC:
-
“P6” - this type of the APIC is used in system based on P6 family and Pentium® processors, obsolete.
-
“P4” - this type of the APIC is used in system based Pentium® 4 and Intel® Xeon® processors. Also “P4” APICs is an extension of the APIC architecture found in the P6 family processors. Architecture of the APIC with type “P4” called the xAPIC architecture. See more information in IA SDM Vol3 ch. 10.3.
-
“X2” - this type of the APIC provides an extension of the xAPIC architecture (“P4” APIC type) - x2APIC. The x2APIC architecture provides backward compatibility to the xAPIC architecture and forward extendability for future Intel platform innovations. These extensions and modifications are supported by a new mode of execution (x2APIC mode) are detailed in IA SDM Vol. 3 Section 10.12.
remote_read method is used to do remote memory transaction. Remote transactions are supported only in the 82489DX and local APIC for Pentium® processors. This method is obsolete for modern processors.
get_apic_id method is used to get local APIC ID.
get_arbitration_priority method is used to get arbitration priority of the local APIC. Each local APIC is given an arbitration priority of from 0 to 15. The arbitration priority is available only for system based on P6 family processors. This method is obsolete for modern processors.
get_apr method is used to get value of the read only Arbitration Priority Register (APR) of the APIC. The APR is available only for system based on P6 family processors, so it is obsolete method for modern processors.
has_physical_destination and has_logical_destination methods are used to find out which destination mode has IPI: physical or logical.
is_focus method is used to find out is to be checked processor is focus processor. A processor is said to be the focus of an interrupt if it is currently servicing that interrupt or if it has a pending request for that interrupt. This arbitration scheme was used only in P6 family and Pentium® processors, so it is obsolete method for modern processors.
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.
is_interrupt_slot_available method is used to do check for the free interrupt slots in the local APIC. Only the local APICs having free interrupt slots participate in the lowest priority arbitration. The interrupt slot based arbitration scheme was used only in system based on the P6 family and Pentium® processors and it is not used in modern processors (obsolete method).
set_pin_status method is used to specify interrupt input pin polarity of the processor’s LINT0 and LINT1 pins: (0) active high or (1) active low.
get_ack_in_progress method indicates that acknowledging of the external interrupt is currently processing.
do_lower_ext_int method is used to clear posted and requested interrupts in the processor.
get_processor_priority method is used to get value of the Processor Priority Register (PPR) of the APIC.
get_lvt_lint0 method is used to get value of the LVT entry called LINT0 of the APIC.
interrupt method is used to send interrupt from APIC bus to certain APIC. Also interrupt method is not available from Python.
Execution Context
Cell Context for all methods.
Name
apic_bus_v2 — interface for handling 32-bit address mode interrupts
Synopsis
C and DML
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"
Description
The interface is used to handle extended 32-bit addressing mode supported by x2APIC. See apic_bus documentation.
Execution Context
Cell Context.
Name
local_apic_interrupt_t, apic_cpu — interface for the local APIC
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
typedef enum {
Apic_Lvt_2e = 0x2e0,
Apic_CMCI = 0x2f0,
Apic_Performance_Counter = 0x340,
Apic_Thermal_Sensor = 0x330
} local_apic_interrupt_t;
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"
Python
import simics
simics.Apic_Lvt_2e
simics.Apic_Performance_Counter
simics.Apic_Thermal_Sensor
simics.Apic_CMCI
class simics.apic_cpu_interface_t(tpr_r=None, tpr_w=None, local_int=None,
power_on=None, init=None, enabled_r=None)
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.
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.
Execution Context
Cell Context for all methods.
Name
apic_delivery_status_t — APIC delivery status
Synopsis
C and DML
#include <simics/devs/apic.h> // in C
import "simics/devs/apic.dml"; // in DML
typedef enum {
Apic_Delivery_Status_Idle = 0,
Apic_Delivery_Status_Send_Pending = 1
} apic_delivery_status_t;
Python
import simics
simics.Apic_Delivery_Status_Idle
simics.Apic_Delivery_Status_Send_Pending
Name
apic_rr_status_t — APIC RR status
Synopsis
C and DML
#include <simics/devs/apic.h> // in C
import "simics/devs/apic.dml"; // in DML
typedef enum {
Apic_RR_Invalid = 0,
Apic_RR_Pending = 1,
Apic_RR_Valid = 2
} apic_rr_status_t;
Python
import simics
simics.Apic_RR_Pending
simics.Apic_RR_Invalid
simics.Apic_RR_Valid
Name
apic_timer_mode_t — type for expressing APIC timer mode
Synopsis
C and DML
typedef enum {
Apic_Timer_Mode_One_Shot = 0,
Apic_Timer_Mode_Periodic = 1,
Apic_Timer_Mode_Tsc_Deadline = 2
} apic_timer_mode_t;
Name
apic_type_t — APIC types
Synopsis
C and DML
typedef enum {
Apic_P6,
Apic_P4,
Apic_X2
} apic_type_t;
Name
arinc429_bus — interface to Arinc-429 serial buses
Synopsis
C and DML
#include <simics/devs/arinc-429.h> // in C
import "simics/devs/arinc-429.dml"; // in DML
SIM_INTERFACE(arinc429_bus) {
void (*send_word)(conf_object_t *bus, uint32 word, int parity_ok);
};
#define ARINC429_BUS_INTERFACE "arinc429_bus"
Python
import simics
class simics.arinc429_bus_interface_t(send_word=None)
Description
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.
Name
arinc429_receiver — interface to Arinc-429 compatible receivers
Synopsis
C and DML
#include <simics/devs/arinc-429.h> // in C
import "simics/devs/arinc-429.dml"; // in DML
SIM_INTERFACE(arinc429_receiver) {
void (*receive_word)(conf_object_t *dev, uint32 word, int parity_ok);
};
#define ARINC429_RECEIVER_INTERFACE "arinc429_receiver"
Python
import simics
class simics.arinc429_receiver_interface_t(receive_word=None)
Description
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.
Name
arm_avic_t, arm_avic — ARM AVIC interface
Synopsis
C and DML
#include <simics/arch/arm.h> // in C
import "simics/arch/arm.dml"; // in DML
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"
Python
import simics
class simics.arm_avic_t(valid=0, address=0)
class simics.arm_avic_interface_t(get_interrupt_address=None)
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.
Execution Context
Cell Context for all methods.
Name
arm_coprocessor — ARM coprocessor interface
Synopsis
C and DML
#include <simics/arch/arm.h> // in C
import "simics/arch/arm.dml"; // in DML
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"
Python
import simics
class simics.arm_coprocessor_interface_t(process_data=None, load_coprocessor=None,
read_register=None, write_register=None, read_register_64_bit=None,
write_register_64_bit=None, store_coprocessor=None, reset=None)
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).
Execution Context
Cell Context for all methods.
Name
arm_cpu_group_event — ARM cpu group event interface
Synopsis
C and DML
#include <simics/arch/arm.h> // in C
import "simics/arch/arm.dml"; // in DML
SIM_INTERFACE(arm_cpu_group_event) {
void (*signal_event)(conf_object_t *obj);
};
#define ARM_CPU_GROUP_EVENT_INTERFACE "arm_cpu_group_event"
Python
import simics
class simics.arm_cpu_group_event_interface_t(signal_event=None)
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.
Execution Context
Threaded Context for all methods.
Name
arm_cpu_group_exclusive — ARM cpu group exclusive interface
Synopsis
C and DML
#include <simics/arch/arm.h> // in C
import "simics/arch/arm.dml"; // in DML
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"
Python
import simics
class simics.arm_cpu_group_exclusive_interface_t(mark_exclusive=None,
clear_and_probe_exclusive=None)
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.
Execution Context
Threaded Context for all methods.
Name
arm_cpu_group_tlb — ARM cpu group tlb interface
Synopsis
C and DML
#include <simics/arch/arm.h> // in C
import "simics/arch/arm.dml"; // in DML
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"
Python
import simics
class simics.arm_cpu_group_tlb_interface_t(invalidate_tlb=None)
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.
Execution Context
Threaded Context for all methods.
Name
arm_gic_cpu_state — interface for ARM processors to provide state to gic-models
Synopsis
C and DML
#include <simics/arch/arm.h> // in C
import "simics/arch/arm.dml"; // in DML
SIM_INTERFACE(arm_gic_cpu_state) {
arm_cpu_state_t (*get_cpu_state)(conf_object_t *obj);
};
#define ARM_GIC_CPU_STATE_INTERFACE "arm_gic_cpu_state"
Python
import simics
class simics.arm_gic_cpu_state_interface_t(get_cpu_state=None)
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.
See Also
arm_cpu_state_t
Execution Context
Cell Context for all methods.
Name
gic_reg_info_t, arm_gic — interface for ARM cores to access generic interrupt controller
Synopsis
C and DML
#include <simics/arch/arm.h> // in C
import "simics/arch/arm.dml"; // in DML
typedef struct gic_reg_info {
int op1;
int crn;
int crm;
int op2;
arm_cpu_state_t cpu_state;
} gic_reg_info_t;
SIM_INTERFACE(arm_gic) {
uint64 (*read_register)(conf_object_t *obj, gic_reg_info_t reg_info,
bool inquiry);
void (*write_register)(conf_object_t *obj, gic_reg_info_t reg_info,
uint64 value);
void (*cpu_state_changed)(conf_object_t *obj, arm_cpu_state_t cpu_state);
};
#define ARM_GIC_INTERFACE "arm_gic"
Python
import simics
class simics.gic_reg_info_t(op1=0, crn=0, crm=0, op2=0,
cpu_state=arm_cpu_state_t())
class simics.arm_gic_interface_t(read_register=None, write_register=None,
cpu_state_changed=None)
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.
See Also
arm_cpu_state_t
Execution Context
Cell Context for all methods.
Name
arm — interface that provides various functionality specific for Arm processors
Synopsis
C and DML
#include <simics/arch/arm.h> // in C
import "simics/arch/arm.dml"; // in DML
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"
Python
import simics
class simics.arm_interface_t(read_register_mode=None, write_register_mode=None)
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.
Execution Context
Cell Context for all methods.
See Also
int_register
Name
arm_trustzone_mode_t, arm_trustzone — ARM Trustzone interface
Synopsis
C and DML
#include <simics/arch/arm.h> // in C
import "simics/arch/arm.dml"; // in DML
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"
Python
import simics
simics.Arm_Trustzone_Secure
simics.Arm_Trustzone_Non_Secure
class simics.arm_trustzone_interface_t(get_security_mode=None,
mem_op_security_mode=None)
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.
Execution Context
Cell Context for all methods.
Name
bridge — implemented by objects that bridge between memory spaces
Synopsis
C and DML
#include <simics/devs/memory-space.h> // in C
import "simics/devs/memory-space.dml"; // in DML
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"
Python
import simics
class simics.bridge_interface_t(not_taken=None)
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.
Execution Context
Cell Context for all methods.
Name
can_device — Interface for receiving from CAN controller
Synopsis
C and DML
SIM_INTERFACE(can_device) {
void (*receive)(conf_object_t *obj, can_frame_t *frame);
};
#define CAN_DEVICE_INTERFACE "can_device"
Description
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.
Execution Context
Cell Context for all methods.
Name
can_frame_t — CAN frame
Synopsis
C and DML
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;
Description
- 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.
Name
can_link — Interface for sending to CAN endpoint
Synopsis
C and DML
SIM_INTERFACE(can_link) {
can_status_t (*send)(conf_object_t *obj, can_frame_t *frame);
};
#define CAN_LINK_INTERFACE "can_link"
Description
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.
Name
coreint_reply_t, coreint — interface between CoreInt capable processor and interrupt controller
Synopsis
C and DML
#include <simics/devs/coreint.h> // in C
// not available in DML
typedef struct {
bool enabled;
uint64 vector;
} coreint_reply_t;
SIM_INTERFACE(coreint) {
coreint_reply_t (*acknowledge)(conf_object_t *obj, conf_object_t *core);
};
#define COREINT_INTERFACE "coreint"
Description
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.
Execution Context
Cell Context for all methods.
Name
cxl_type_t, cxl_map — interface used to claim ranges in CXL address spaces
Synopsis
C and DML
#include <simics/devs/cxl.h> // in C
import "simics/devs/cxl.dml"; // in DML
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"
Python
import simics
simics.CXL_Type_Cache
simics.CXL_Type_Mem
simics.CXL_Type_Other
simics.CXL_Type_Not_Set
simics.CXL_Type_Io
class simics.cxl_map_interface_t(add_map=None, del_map=None)
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.
This interface is considered tech-preview and may change without notice.
Execution Context
Cell Context for all methods.
Name
cxl_mem_downstream_port_managing — interface for cxl downstream port memory management
Synopsis
C and DML
#include <simics/devs/cxl.h> // in C
import "simics/devs/cxl.dml"; // in DML
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"
Python
import simics
class simics.cxl_mem_downstream_port_managing_interface_t(register_port_mem_obj=None,
unregister_port_mem_obj=None)
Description
Functions register_port_mem_obj and unregister_port_mem_obj are used to register and unregister port memory objects.
Execution Context
Cell Context for all methods.
Name
cxl_non_device_decoder_handling — interface for cxl_hdm_port
Synopsis
C and DML
#include <simics/devs/cxl.h> // in C
import "simics/devs/cxl.dml"; // in DML
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"
Python
import simics
class simics.cxl_non_device_decoder_handling_interface_t(enable_decoder=None,
disable_decoder=None)
Description
Functions enable_decoder and disable_decoder are used to enable and disable HDM decoders on a cxl-hdm-port device.
Execution Context
Cell Context for all methods.
Name
datagram_link — implemented by objects that receive messages from a datagram-link
Synopsis
C and DML
#include <simics/devs/datagram-link.h> // in C
import "simics/devs/datagram-link.dml"; // in DML
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"
Python
import simics
class simics.datagram_link_interface_t(receive=None)
Description
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
Cell Context
Name
eri_reg_num_t — Registers number used by ERI or DCRA
Synopsis
C and DML
typedef enum {
DCRA_ERI_PMA_RESOLUTION_CONTROL = 0,
ERI_PMA_CORE_TTT_L32, // low 32-bit of arat_ttt small core
ERI_PMA_CORE_TTT_H32, // high 32-bit of arat_ttt small core
DCRA_ERI_PMA_CORE_STATUS,
DCRA_PMA_ACODE_TO_UCODE_CFG,
DCRA_PMA_ARAT_TTT, // arat_ttt of big core
DCRA_ERI_PMA_CSTT_THRESHOLD,
ERI_PMA_CR_UCODE_ASSIST_INFO,
} eri_reg_num_t;
Name
eri_transaction_t — Transaction info used in x86_eri_v1
Synopsis
C and DML
typedef struct {
uint64 val; // Read or Write value
bool valid; // Valid or not data in val field
} eri_transaction_t;
Name
eri_v2_transaction_t — Transaction info used in x86_eri_v2
Synopsis
C and DML
typedef struct {
uint32 value; // read or write value
uint16 addr;
uint8 scope;
uint8 type;
uint8 wrbe; // write bytes enable mask
bool valid; // valid or not data in val field
} eri_v2_transaction_t;
Name
ethernet_cable — ethernet interface used for notification of link status
Synopsis
C and DML
#include <simics/devs/ethernet.h> // in C
import "simics/devs/ethernet.dml"; // in DML
SIM_INTERFACE(ethernet_cable) {
void (*link_status)(conf_object_t *NOTNULL ep, bool link_up);
};
#define ETHERNET_CABLE_INTERFACE "ethernet_cable"
Python
import simics
class simics.ethernet_cable_interface_t(link_status=None)
Description
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 class propagates this information to the device connected at the other end.
Execution Context
Cell Context
Name
ethernet_common — common ethernet interface used by all ethernet links and devices
Synopsis
C and DML
#include <simics/devs/ethernet.h> // in C
import "simics/devs/ethernet.dml"; // in DML
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"
Python
import simics
class simics.ethernet_common_interface_t(frame=None)
Description
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.
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
Cell Context
Name
eth_probe_side_t, ethernet_probe_snoop_t, ethernet_probe — used to attach to ethernet connections and look at and/or modify frames
Synopsis
C and DML
#include <simics/devs/eth-probe.h> // in C
import "simics/devs/eth-probe.dml"; // in DML
typedef enum {
Eth_Probe_Port_A = 0,
Eth_Probe_Port_B = 1
} eth_probe_side_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);
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"
Python
import simics
simics.Eth_Probe_Port_A
simics.Eth_Probe_Port_B
class simics.ethernet_probe_interface_t(attach_snooper=None, attach_probe=None,
detach=None, send_frame=None)
Description
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.
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.
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.
Name
ethernet_link_snoop_t, ethernet_snoop — used to attach snooping functions to ethernet links
Synopsis
C and DML
#include <simics/devs/ethernet.h> // in C
import "simics/devs/ethernet.dml"; // in DML
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_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"
Python
import simics
class simics.ethernet_snoop_interface_t(attach=None)
Description
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
Global Context
Name
ethernet_vlan_snoop — used to attach snoop functions to VLAN network
Synopsis
C and DML
#include <simics/devs/ethernet.h> // in C
import "simics/devs/ethernet.dml"; // in DML
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"
Python
import simics
class simics.ethernet_vlan_snoop_interface_t(attach=None)
Description
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
Global Context
Name
exec_trace — interface for handling registration of trace listeners
Synopsis
C and DML
#include <simics/model-iface/exec-trace.h> // in C
import "simics/model-iface/exec-trace.dml"; // in DML
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"
Python
import simics
class simics.exec_trace_interface_t(register_tracer=None, unregister_tracer=None)
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 (of type instruction_trace_callback_t) 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.
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.
Execution Context
Global Context for both methods. Cell Context for the callback.
Name
extended_serial — extension to serial_device interface
Synopsis
C and DML
#include <simics/devs/serial-device.h> // in C
import "simics/devs/serial-device.dml"; // in DML
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"
Python
import simics
class simics.extended_serial_interface_t(write_at=None, graphics_mode=None)
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.
Execution Context
Cell Context for all methods.
Name
firewire_ack_code_t, firewire_bus — interface implemented by firewire buses
Synopsis
C and DML
#include <simics/devs/firewire.h> // in C
import "simics/devs/firewire.dml"; // in DML
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;
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"
Python
import simics
simics.Firewire_Ack_Address_Error
simics.Firewire_Ack_Busy_X
simics.Firewire_Ack_Tardy
simics.Firewire_Ack_No_Ack
simics.Firewire_Ack_Busy_A
simics.Firewire_Ack_No_Destination
simics.Firewire_Ack_Busy_B
simics.Firewire_Ack_Type_Error
simics.Firewire_Ack_Complete
simics.Firewire_Ack_Pending
simics.Firewire_Ack_Data_Error
simics.Firewire_Ack_Conflict_Error
class simics.firewire_bus_interface_t(connect_device=None, disconnect_device=None,
set_device_bus_id=None, set_id_mask=None, transfer=None,
register_channel=None, unregister_channel=None, reset=None)
Description
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:
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.
Name
uint32_array_t, firewire_device — implemented by firewire devices
Synopsis
C and DML
#include <simics/devs/firewire.h> // in C
import "simics/devs/firewire.dml"; // in DML
typedef struct {
size_t len;
uint32 *data;
} uint32_array_t;
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"
Python
import simics
class simics.firewire_device_interface_t(transfer=None, reset=None,
get_self_id_template=None, get_rhb=None, get_port_count=None,
get_port_mask=None)
Description
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:
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.
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.
Name
fmn_station_control — interface for Fast Messaging Network stations
Synopsis
C and DML
#include <simics/arch/mips.h> // in C
import "simics/arch/mips.dml"; // in DML
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"
Python
import simics
class simics.fmn_station_control_interface_t(send_message=None, load_message=None,
wait=None, sync=None)
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.
Execution Context
Cell Context for all methods.
Name
fmn_station_control_v2 — interface for Fast Messaging Network stations
Synopsis
C and DML
#include <simics/arch/mips.h> // in C
import "simics/arch/mips.dml"; // in DML
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"
Python
import simics
class simics.fmn_station_control_v2_interface_t(send_message=None,
load_message=None, wait=None, sync=None)
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.
Execution Context
Cell Context for all methods.
Name
frequency — interface used to publish frequency
Synopsis
C and DML
#include <simics/devs/frequency.h> // in C
import "simics/devs/frequency.dml"; // in DML
SIM_INTERFACE(frequency) {
double (*get)(conf_object_t *NOTNULL obj);
};
#define FREQUENCY_INTERFACE "frequency"
Python
import simics
class simics.frequency_interface_t(get=None)
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.
Execution Context
Cell Context for all methods.
Name
frequency_listener — interface used to model frequency changes
Synopsis
C and DML
#include <simics/devs/frequency.h> // in C
import "simics/devs/frequency.dml"; // in DML
SIM_INTERFACE(frequency_listener) {
void (*set)(conf_object_t *NOTNULL obj, uint64 numerator,
uint64 denominator);
};
#define FREQUENCY_LISTENER_INTERFACE "frequency_listener"
Python
import simics
class simics.frequency_listener_interface_t(set=None)
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.
Execution Context
Cell Context for all methods.
Name
generic_message_device — Interface for receiving from generic message devices
Synopsis
C and DML
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"
Description
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
| Function | Context |
receive_frame | Cell Context |
Name
generic_message_link — Interface for gml-link
Synopsis
C and DML
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"
Description
This interface is used for gml-link which is based on the link library. Refer to the Link Library Programming Guide 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
| Function | Context |
connect_device | Global Context |
disconnect_device | Global Context |
send_frame | Cell Context |
Name
hpi — interface for Host Port Interface
Synopsis
C and DML
#include <simics/devs/hpi-interface.h> // in C
// not available in DML
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"
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.
Execution Context
Cell Context for all methods.
Name
i2c_ack_t, i2c_master_v2 — interface implemented by I2C masters
Synopsis
C and DML
#include <simics/devs/i2c.h> // in C
import "simics/devs/i2c.dml"; // in DML
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"
Python
import simics
simics.I2C_noack
simics.I2C_ack
class simics.i2c_master_v2_interface_t(acknowledge=None, read_response=None)
Description
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.
Name
i2c_slave_v2 — interface used by I2C devices
Synopsis
C and DML
#include <simics/devs/i2c.h> // in C
import "simics/devs/i2c.dml"; // in DML
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"
Python
import simics
class simics.i2c_slave_v2_interface_t(start=None, read=None, write=None,
stop=None, addresses=None)
Description
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
The addresses method needs Global Context. All other methods can be used in Cell Context.
Name
i3c_daa_snoop — interface used with I3C monitoring
Synopsis
C and DML
#include <simics/devs/i3c.h> // in C
import "simics/devs/i3c.dml"; // in DML
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"
Python
import simics
class simics.i3c_daa_snoop_interface_t(assigned_address=None)
Description
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.
Name
i3c_hdr_slave, i3c_hdr_master — interfaces for I3C HDR communication
Synopsis
C and DML
#include <simics/devs/i3c.h> // in C
import "simics/devs/i3c.dml"; // in DML
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"
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"
Python
import simics
class simics.i3c_hdr_slave_interface_t(hdr_write=None, hdr_read=None,
hdr_restart=None, hdr_exit=None)
class simics.i3c_hdr_master_interface_t(hdr_read_response=None,
hdr_acknowledge=None)
Description
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 on 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 specific write transfer blocks, must in such cases 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:
- Minimize the number of
hdr_read calls needed to read a large amount of data.
- Avoid underflow on the slave side by allowing the slave respond with less data.
If more is set to false, the master has to end its 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 |
| 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 |
| 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 |
| 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.
This interface is in tech-preview and may change without notice.
Execution Context
Cell Context for all methods.
Name
i3c_ack_t, i3c_master, i3c_slave — interfaces for I3C bus communication
Synopsis
C and DML
#include <simics/devs/i3c.h> // in C
import "simics/devs/i3c.dml"; // in DML
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"
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"
Python
import simics
simics.I3C_noack
simics.I3C_ack
class simics.i3c_master_interface_t(acknowledge=None, read_response=None,
daa_response=None, ibi_request=None, ibi_address=None)
class simics.i3c_slave_interface_t(start=None, write=None, sdr_write=None,
read=None, daa_read=None, stop=None, ibi_start=None,
ibi_acknowledge=None)
Description
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.
Name
i8051_interrupt — interface for interrupts in i8051 cores
Synopsis
C and DML
#include <simics/arch/i8051.h> // in C
import "simics/arch/i8051.dml"; // in DML
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"
Python
import simics
class simics.i8051_interrupt_interface_t(active_interrupt=None, reti=None,
suppress_irq=None)
Description
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.
Name
i8051_timer — interface to control timer in i8051 cores
Synopsis
C and DML
#include <simics/arch/i8051.h> // in C
import "simics/arch/i8051.dml"; // in DML
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"
Python
import simics
class simics.i8051_timer_interface_t(change_mode=None, switch_timer=None)
Description
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.
Name
ieee_802_15_4_control — 802.15.4 control interface
Synopsis
C and DML
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"
Description
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.
Name
ieee_802_15_4_frame_crc_status_t — 802.15.4 frame CRC status
Synopsis
C and DML
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;
Description
- 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.
Name
ieee_802_15_4_link — An interface for 802.15.4 transmissions
Synopsis
C and DML
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"
Description
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.
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.
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.
Name
ieee_802_15_4_probe — Probe interface for 802.15.4 devices
Synopsis
C and DML
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"
Description
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.
See Also
ieee_802_15_4_probe_snoop_t, ieee_802_15_4_probe_side_t,
Execution Context
Cell Context for all methods.
Name
ieee_802_15_4_probe_side_t — 802.15.4 probe
Synopsis
C and DML
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;
Description
- 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.
Name
ieee_802_15_4_probe_snoop_t — Function prototype for 802.15.4 probe snope functions.
Synopsis
C and DML
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);
See Also
ieee_802_15_4_probe_side_t, ieee_802_15_4_frame_crc_status_t
Name
ieee_802_15_4_receiver — 802.15.4 receiver interface
Synopsis
C and DML
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"
Description
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.
Name
ieee_802_15_4_transmit_status_t — 802.15.4 transmit status
Synopsis
C and DML
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;
Description
- 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.
Name
ieee_802_3_mac — interface used for media access control layer
Synopsis
C and DML
#include <simics/devs/ieee_802_3.h> // in C
import "simics/devs/ieee_802_3.dml"; // in DML
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);
};
#define IEEE_802_3_MAC_INTERFACE "ieee_802_3_mac"
Python
import simics
class simics.ieee_802_3_mac_interface_t(receive_frame=None,
tx_bandwidth_available=None, link_status_changed=None)
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.
Name
ieee_802_3_link_status_t, ieee_802_3_mac_v3 — interface used for media access control layer
Synopsis
C and DML
#include <simics/devs/ieee_802_3.h> // in C
import "simics/devs/ieee_802_3.dml"; // in DML
typedef enum {
IEEE_link_unconnected,
IEEE_link_down,
IEEE_link_up
} ieee_802_3_link_status_t;
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);
};
#define IEEE_802_3_MAC_V3_INTERFACE "ieee_802_3_mac_v3"
Python
import simics
simics.IEEE_link_unconnected
simics.IEEE_link_up
simics.IEEE_link_down
class simics.ieee_802_3_mac_v3_interface_t(receive_frame=None,
tx_bandwidth_available=None, link_status_changed=None)
Description
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.
Name
ieee_802_3_phy — interface used with 802.3 physical layers
Synopsis
C and DML
#include <simics/devs/ieee_802_3.h> // in C
import "simics/devs/ieee_802_3.dml"; // in DML
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);
};
#define IEEE_802_3_PHY_INTERFACE "ieee_802_3_phy"
Python
import simics
class simics.ieee_802_3_phy_interface_t(send_frame=None, check_tx_bandwidth=None,
set_promiscous_mode=None)
Description
Interface that should be implemented by 802.3 physical layers.
Deprecated!
use ieee_802_3_phy_v2 instead.
Name
ieee_802_3_phy_v2 — interface used with 802.3 physical layers
Synopsis
C and DML
#include <simics/devs/ieee_802_3.h> // in C
import "simics/devs/ieee_802_3.dml"; // in DML
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);
};
#define IEEE_802_3_PHY_V2_INTERFACE "ieee_802_3_phy_v2"
Python
import simics
class simics.ieee_802_3_phy_v2_interface_t(send_frame=None,
check_tx_bandwidth=None, add_mac=None, del_mac=None,
add_mac_mask=None, del_mac_mask=None, set_promiscous_mode=None)
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 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.
Name
ieee_802_3_phy_v3 — interface used with 802.3 physical layers
Synopsis
C and DML
#include <simics/devs/ieee_802_3.h> // in C
import "simics/devs/ieee_802_3.dml"; // in DML
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);
};
#define IEEE_802_3_PHY_V3_INTERFACE "ieee_802_3_phy_v3"
Python
import simics
class simics.ieee_802_3_phy_v3_interface_t(send_frame=None,
check_tx_bandwidth=None)
Description
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.
Name
instruction_trace_callback_t — Function type for callbacks in exec_trace_interface_t
Synopsis
C and DML
#include <simics/model-iface/exec-trace.h> // in C
import "simics/model-iface/exec-trace.dml"; // in DML
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);
Description
It takes the following arguments:
tracer_data
- The exact pointer passed as
tracer_data when registering the listener function with register_tracer() in the exec_trace interface.
cpu
- The cpu executing the instruction.
la
- The linear address of the instruction for x86 processors, and nothing for all others.
va
- The virtual address of the instruction as contained in the program counter, or instruction pointer register.
pa
- The physical address of the instruction after doing a MMU lookup.
opcode
- The bytes composing the instruction.
Name
int_register — access registers in a processor
Synopsis
C and DML
#include <simics/model-iface/int-register.h> // in C
import "simics/model-iface/int-register.dml"; // in DML
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"
Python
import simics
simics.Sim_RegInfo_Catchable
class simics.int_register_interface_t(get_number=None, get_name=None, read=None,
write=None, all_registers=None, register_info=None)
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.
Execution Context
Cell Context for all methods, except for write where the register is a program counter; Global Context in that case.
Name
interrupt_ack — interface used with acked interrupts
Synopsis
C and DML
#include <simics/devs/interrupt-ack.h> // in C
import "simics/devs/interrupt-ack.dml"; // in DML
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"
Python
import simics
class simics.interrupt_ack_interface_t(raise_interrupt=None, lower_interrupt=None)
Description
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.
Execution Context
Cell Context for all methods.
Name
interrupt_cpu — interface used with interrupts
Synopsis
C and DML
#include <simics/devs/interrupt-ack.h> // in C
import "simics/devs/interrupt-ack.dml"; // in DML
SIM_INTERFACE(interrupt_cpu) {
interrupt_ack_fn_t ack;
};
#define INTERRUPT_CPU_INTERFACE "interrupt_cpu"
Python
import simics
class simics.interrupt_cpu_interface_t(ack=None)
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.
Execution Context
Cell Context for all methods.
Name
interrupt_subscriber — interface used with interrupts
Synopsis
C and DML
#include <simics/devs/interrupt-subscriber.h> // in C
import "simics/devs/interrupt-subscriber.dml"; // in DML
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);
};
#define INTERRUPT_SUBSCRIBER_INTERFACE "interrupt_subscriber"
Python
import simics
class simics.interrupt_subscriber_interface_t(notify=None, reset=None)
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.
Execution Context
Threaded Context for all methods.
Name
addr_space_t, io_memory — legacy interface for devices that can be mapped into address spaces
Synopsis
C and DML
#include <simics/device-api.h> // in C
// always available in DML
typedef enum {
Sim_Addr_Space_Conf,
Sim_Addr_Space_IO,
Sim_Addr_Space_Memory
} addr_space_t;
#include <simics/devs/io-memory.h> // in C
import "simics/devs/io-memory.dml"; // in DML
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"
Python
import simics
simics.Sim_Addr_Space_IO
simics.Sim_Addr_Space_Memory
simics.Sim_Addr_Space_Conf
class simics.io_memory_interface_t(_deprecated_map=None, operation=None)
Description
This interface is legacy. New code should use the transaction interface.
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
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.
Execution Context
Cell Context for all methods.
Name
map_demap — interface used to configure memory spaces
Synopsis
C and DML
#include <simics/devs/map-demap.h> // in C
import "simics/devs/map-demap.dml"; // in DML
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"
Python
import simics
class simics.map_demap_interface_t(add_map=None, remove_map=None,
add_default=None, remove_default=None, map_simple=None,
map_bridge=None, unmap=None, unmap_address=None)
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.
Execution Context
Cell Context for all methods.
Name
mdio45_bus — interface for PHY with MDIO management interface
Synopsis
C and DML
#include <simics/devs/mii.h> // in C
import "simics/devs/mii.dml"; // in DML
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"
Python
import simics
class simics.mdio45_bus_interface_t(read_register=None, write_register=None)
Description
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.
Name
mdio45_phy — interface for PHY with MDIO management interface
Synopsis
C and DML
#include <simics/devs/mii.h> // in C
import "simics/devs/mii.dml"; // in DML
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"
Python
import simics
class simics.mdio45_phy_interface_t(read_register=None, write_register=None)
Description
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.
Name
memory_space — implemented by classes that provide linear address spaces
Synopsis
C and DML
#include <simics/devs/memory-space.h> // in C
import "simics/devs/memory-space.dml"; // in DML
// some parts deprecated with SIMICS_API = 7
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"
Python
import simics
class simics.memory_space_interface_t(space_lookup=None, access=None, read=None,
write=None, timing_model_operate=None, fill=None)
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.
Exceptions
The read and write methods signal errors by raising frontend exceptions.
Execution Context
Cell Context for all methods.
Name
microwire — interface used to communicate with a 3-wire devices
Synopsis
C and DML
#include <simics/devs/microwire.h> // in C
import "simics/devs/microwire.dml"; // in DML
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);
};
#define MICROWIRE_INTERFACE "microwire"
Python
import simics
class simics.microwire_interface_t(set_cs=None, set_sk=None, set_di=None,
get_do=None, read_word=None, write_word=None)
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.
Execution Context
Cell Context for all methods.
Name
mii — interface for PHY with MII management interface
Synopsis
C and DML
#include <simics/devs/mii.h> // in C
import "simics/devs/mii.dml"; // in DML
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"
Python
import simics
class simics.mii_interface_t(serial_access=None, read_register=None,
write_register=None)
Description
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.
Name
mii_management — interface for PHY with MII management interface
Synopsis
C and DML
#include <simics/devs/mii.h> // in C
import "simics/devs/mii.dml"; // in DML
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"
Python
import simics
class simics.mii_management_interface_t(serial_access=None, read_register=None,
write_register=None)
Description
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.
Name
mips_cache_instruction — interface for side effects of cache instructions
Synopsis
C and DML
#include <simics/arch/mips.h> // in C
import "simics/arch/mips.dml"; // in DML
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"
Python
import simics
class simics.mips_cache_instruction_interface_t(cache_instruction=None)
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.
Execution Context
Cell Context.
Name
mips_coprocessor — interface used by MIPS cores to access coprocessors
Synopsis
C and DML
#include <simics/arch/mips.h> // in C
import "simics/arch/mips.dml"; // in DML
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"
Python
import simics
class simics.mips_coprocessor_interface_t(read_register=None, write_register=None)
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.
Execution Context
Cell Context for all methods.
Name
mips_eic — interface used between MIPS cores and external interrupt controllers
Synopsis
C and DML
#include <simics/arch/mips.h> // in C
import "simics/arch/mips.dml"; // in DML
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"
Python
import simics
class simics.mips_eic_interface_t(cpu_pending_irqs=None, requested_ipl=None,
requested_offset=None, requested_vect_num=None, reg_set=None,
handled=None)
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.
Execution Context
Cell Context for all methods.
Name
mips_exception_query — interface used with instrumentation of MIPS cores
Synopsis
C and DML
#include <simics/arch/mips-instrumentation.h> // in C
import "simics/arch/mips-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.mips_exception_query_interface_t(return_pc=None)
Description
Used to query information of an exception from a cpu_exception_cb_t callback.
return_pc is used to get the return address for the exception.
Execution Context
Cell Context for all methods.
Name
mips — MIPS dummy interface
Synopsis
C and DML
#include <simics/arch/mips.h> // in C
import "simics/arch/mips.dml"; // in DML
SIM_INTERFACE(mips) {
int dummy;
};
#define MIPS_INTERFACE "mips"
Python
import simics
class simics.mips_interface_t()
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.
Execution Context
Not applicable.
Name
mips_ite — interface for MIPS Inter-Thread Communication Unit
Synopsis
C and DML
#include <simics/arch/mips.h> // in C
import "simics/arch/mips.dml"; // in DML
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"
Python
import simics
class simics.mips_ite_interface_t(set_dtag_lo=None, get_dtag_lo=None,
get_errctl=None, block_tc=None, gated_exception=None,
current_tc_num=None, unblock_tc=None, is_big_endian=None)
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.
Execution Context
Cell Context for all methods.
Name
multi_level_signal — model a signal with multiple levels, such as an analog signal
Synopsis
C and DML
#include <simics/devs/signal.h> // in C
import "simics/devs/signal.dml"; // in DML
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"
Python
import simics
class simics.multi_level_signal_interface_t(signal_level_change=None,
signal_current_level=None)
Description
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.
Execution Context
Cell Context for all methods.
Name
nand_flash — interface implemented by NAND Flash devices
Synopsis
C and DML
#include <simics/devs/nand-flash.h> // in C
import "simics/devs/nand-flash.dml"; // in DML
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);
};
#define NAND_FLASH_INTERFACE "nand_flash"
Python
import simics
class simics.nand_flash_interface_t(read_access=None, write_access=None,
set_command_latch_enable=None, set_address_latch_enable=None,
set_write_protect=None, set_spare_area_enable=None)
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.
Execution Context
Cell Context for all methods.
Name
network_breakpoint — used to attach snoop functions to VLAN network
Synopsis
C and DML
#include <simics/devs/ethernet.h> // in C
import "simics/devs/ethernet.dml"; // in DML
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"
Python
import simics
class simics.network_breakpoint_interface_t(add=None, remove=None)
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.
Execution Context
Global Context for all methods
See Also
break_net_cb_t
Name
nios_cache — NIOS cache interface
Synopsis
C and DML
#include <simics/arch/nios.h> // in C
import "simics/arch/nios.dml"; // in DML
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"
Python
import simics
class simics.nios_cache_interface_t(flushd=None, flushda=None, flushi=None,
flushp=None, initd=None, initda=None, initi=None, sync=None)
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.
Execution Context
Cell Context for all methods.
Name
nios_custom — interface used with the NIOS custom instruction
Synopsis
C and DML
#include <simics/arch/nios.h> // in C
import "simics/arch/nios.dml"; // in DML
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"
Python
import simics
class simics.nios_custom_interface_t(custom=None)
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.
Execution Context
Cell Context
Name
nios_eic — interface for NIOS external interrupt controllers
Synopsis
C and DML
#include <simics/arch/nios.h> // in C
import "simics/arch/nios.dml"; // in DML
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"
Python
import simics
class simics.nios_eic_interface_t(handler=None, level=None, reg_set=None,
nmi=None, handled=None)
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.
Execution Context
Cell Context for all methods.
Name
nios — NIOS dummy interface
Synopsis
C and DML
#include <simics/arch/nios.h> // in C
import "simics/arch/nios.dml"; // in DML
SIM_INTERFACE(nios) {
int dummy;
};
#define NIOS_INTERFACE "nios"
Python
import simics
class simics.nios_interface_t()
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.
Execution Context
Not applicable.
Name
nvm_subsystem_controller_management — Interface for NVME Subsystem Controller management
Synopsis
C and DML
SIM_INTERFACE(nvm_subsystem_controller_management)
{
int (*register_controller)(conf_object_t *obj, uint16 cntid,
conf_object_t *controller);
attr_value_t (*get_all_controllers)(conf_object_t *obj);
};
#define NVM_SUBSYSTEM_CONTROLLER_MANAGEMENT_INTERFACE \
"nvm_subsystem_controller_management"
Description
This interface is intended for implementing NVM Subsystem Controller management.
register_controller
- registers a new controller with the NVM subsystem using the specified controller ID. Returns 0 on success, or a negative error code on failure. Parameters:
cntid: The controller identifier to register
controller: The controller object to register
get_all_controllers
- retrieves a list of all controllers currently registered with the NVM subsystem. Returns an attribute value containing the list of controller identifiers. The caller must free the returned attribute.
Execution Context
Cell Context for all methods.
Name
nvme_namespace_management — Interface for NVMe namespace management
Synopsis
C and DML
SIM_INTERFACE(nvme_namespace_management)
{
int (*create_namespace)(conf_object_t *obj, uint64 size, char *file);
int (*delete_namespace)(conf_object_t *obj, uint32 nsid);
void (*delete_all_namespaces)(conf_object_t *obj);
int (*attach_namespace)(conf_object_t *obj, uint32 nsid,
attr_value_t *cntids);
int (*detach_namespace)(conf_object_t *obj, uint32 nsid,
attr_value_t *cntids);
uint32 (*get_max_namespaces)(conf_object_t *obj);
attr_value_t (*get_namespaces)(conf_object_t *obj);
bytes_t (*get_namespace_uuid)(conf_object_t *obj, uint32 nsid);
uint64 (*get_namespace_size)(conf_object_t *obj, uint32 nsid);
uint64 (*get_total_disk_capacity)(conf_object_t *obj);
uint64 (*get_free_disk_capacity)(conf_object_t *obj);
int (*sanitize)(conf_object_t *obj, uint8 sanitize_action);
int (*format_nvm)(conf_object_t *obj, uint32 nsid);
};
#define NVME_NAMESPACE_MANAGEMENT_INTERFACE "nvme_namespace_management"
Description
This interface is intended for implementing NVMe namespace management.
create_namespace
-
creates a new NVMe namespace with the specified size and backing file. Returns 0 on success, or a negative error code on failure. Parameters:
size: The size of the namespace in bytes. If 0, and file is not NULL, the size of the backing file is used.
file: Path to the backing file for the namespace. If NULL, a sparse backing store is used.
delete_namespace
-
deletes an existing namespace identified by the given namespace ID. Returns 0 on success, or a negative error code on failure. Parameters:
nsid: The namespace identifier to delete
delete_all_namespaces
-
deletes all existing namespaces.
attach_namespace
-
attaches a namespace to one or more controllers. Returns 0 on success, or a negative error code on failure. Parameters:
nsid: The namespace identifier to attach
cntids: List of controller IDs to attach the namespace to
detach_namespace
-
detaches a namespace from one or more controllers. Returns 0 on success, or a negative error code on failure. Parameters:
nsid: The namespace identifier to detach
cntids: List of controller IDs to detach the namespace from
get_max_namespaces
-
returns the maximum number of namespaces supported by the NVM subsystem.
get_namespaces
-
returns a list of all currently active namespace identifiers in the subsystem. The returned attribute is a list that is structured as follows:
[image object, namespace id, uuid string, attached controllers list]
The caller must free the returned attribute.
get_namespace_uuid
-
retrieves the UUID of the specified namespace. Returns the UUID as a string, or NULL if the namespace doesn’t exist. Parameters:
nsid: The namespace identifier
get_namespace_size
-
retrieves the size in bytes of the specifiednamespace. Returns the size, or 0 if the namespace doesn’t exist. Parameters:
nsid: The namespace identifier
get_total_disk_capacity
-
returns the total disk capacity in bytes available to the NVM subsystem.
get_free_disk_capacity
-
returns the free (unallocated) disk capacity in bytes available for new namespaces.
sanitize
-
performs a sanitize operation on the NVM subsystem using the specified action. Returns 0 on success, or a negative error code on failure.
format_nvm
-
performs a format NVM operation using the specified nsid. If the nsid is 0xFFFFFFFF, the format applies to all namespaces. Returns 0 on success, or -1 in case of failure. Parameters:
sanitize_action: The sanitize action to perform
Execution Context
Cell Context for all methods.
Name
packet — interface used to transfer data between devices
Synopsis
C and DML
#include <simics/model-iface/packet.h> // in C
import "simics/model-iface/packet.dml"; // in DML
SIM_INTERFACE(packet) {
void (*transfer)(conf_object_t *obj, bytes_t data);
};
#define PACKET_INTERFACE "packet"
Python
import simics
class simics.packet_interface_t(transfer=None)
Description
The packet interface is implemented by objects that transfer chunks of data without exposing the underlying structure of the data.
The transfer function is called to transfer data from one device to another.
Name
pci_bridge — interface used with downstream PCI(e)
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
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"
Python
import simics
class simics.pci_bridge_interface_t(system_error=None, raise_interrupt=None,
lower_interrupt=None)
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.
Execution Context
Cell Context for all methods.
Name
pci_bus — interface implemented by all PCI buses
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
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"
Python
import simics
class simics.pci_bus_interface_t(memory_access=None, raise_interrupt=None,
lower_interrupt=None, interrupt_acknowledge=None, add_map=None,
remove_map=None, set_bus_number=None, set_sub_bus_number=None,
add_default=None, remove_default=None, bus_reset=None,
special_cycle=None, system_error=None, get_bus_address=None,
set_device_status=None, configuration_space=None, io_space=None,
memory_space=None)
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”.
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.
Execution Context
Cell Context for all methods.
Name
pci_device — interface implemented by PCI devices
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
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"
Python
import simics
class simics.pci_device_interface_t(bus_reset=None,
_deprecated_interrupt_acknowledge=None,
_deprecated_special_cycle=None, system_error=None,
interrupt_raised=None, interrupt_lowered=None)
Description
This interface is implemented by all PCI devices (including bridges).
The interrupt_acknowledge and special_cycle functions are deprecated. The functions can be left unimplemented (NULL).
Execution Context
Cell Context for all methods.
Name
pci_downstream — interface used with downstream PCI(e)
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
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"
Python
import simics
class simics.pci_downstream_interface_t(operation=None)
Description
The pci_downstream interface is implemented by PCI(e) buses to handle downstream transactions.
Execution Context
Cell Context for all methods.
Name
pci_express_hotplug — deprecated interface part of the old PCIe library
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
// only supported with SIMICS_API = 6
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"
Python
import simics
class simics.pci_express_hotplug_interface_t(presence_change=None,
inject_power_fault=None, press_attention_button=None,
set_mrl_state=None, get_mrl_state=None)
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.
Execution Context
Cell Context for all methods.
Name
pcie_message_type_t, pci_express — deprecated interface part of the old PCIe library
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
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;
// only supported with SIMICS_API = 6
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"
Python
import simics
simics.PCIE_PRS_Request
simics.PCIE_ATS_Invalidate_Completion
simics.PCIE_Msg_Deassert_INTC
simics.PCIE_PM_Turn_Off
simics.PCIE_Msg_Deassert_INTA
simics.PCIE_HP_Attention_Indicator_Blink
simics.PCIE_PM_Active_State_Nak
simics.PCIE_PM_PME
simics.PCIE_PM_PME_TO_Ack
simics.PCIE_HP_Attention_Indicator_Off
simics.PCIE_ERR_FATAL
simics.PCIE_Msg_Assert_INTC
simics.PCIE_ATS_Invalidate
simics.PCIE_Optimized_Buffer_Flush_Fill
simics.PCIE_HP_Power_Indicator_Blink
simics.PCIE_Msg_Assert_INTB
simics.PCIE_DLL_Link_Up
simics.PCIE_PRS_Response
simics.PCIE_HP_Attention_Button_Pressed
simics.PCIE_Latency_Tolerance_Reporting
simics.PCIE_Vendor_Defined_Type_1
simics.PCIE_DLL_Link_Down
simics.PCIE_HP_Power_Indicator_On
simics.PCIE_Msg_Assert_INTD
simics.PCIE_Precision_Time_Measurement
simics.PCIE_HP_Power_Indicator_Off
simics.PCIE_HP_Attention_Indicator_On
simics.PCIE_Msg_Deassert_INTD
simics.PCIE_ERR_COR
simics.PCIE_Unlock
simics.PCIE_ERR_NONFATAL
simics.PCIE_Msg_Assert_INTA
simics.PCIE_Vendor_Defined_Type_0
simics.PCIE_Msg_Deassert_INTB
simics.PCIE_Set_Slot_Power_Limit
class simics.pci_express_interface_t(send_message=None)
Description
Deprecated as part of the old PCIe library. Replaced by the new PCIe library.
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 (Type2: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 pcie_message_type_t.
The contents of payload depends on type.
Execution Context
Cell Context for all methods.
Name
pci_interrupt — interface used with PCI(e) interrupts
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
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"
Python
import simics
class simics.pci_interrupt_interface_t(raise_interrupt=None, lower_interrupt=None)
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.
Execution Context
Cell Context for all methods.
Name
pci_multi_function_device — interface used by PCI devices with multiple functions
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
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"
Python
import simics
class simics.pci_multi_function_device_interface_t(supported_functions=None)
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.
Execution Context
Global Context for all methods.
Name
pci_upstream — interface used with upstream PCI(e)
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
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"
Python
import simics
class simics.pci_upstream_interface_t(operation=None)
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.
Execution Context
Cell Context for all methods.
Name
pci_upstream_operation — interface used with upstream PCI(e)
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
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"
Python
import simics
class simics.pci_upstream_operation_interface_t(read=None, write=None)
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.
Execution Context
Cell Context for all methods.
Name
pcie_adapter_compat — interface used with PCIe
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
// only supported with SIMICS_API = 6
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"
Python
import simics
class simics.pcie_adapter_compat_interface_t(set_secondary_bus_number=None)
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.
Execution Context
Cell Context for all methods.
Name
pcie_device — interface implemented by PCI devices
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
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"
Python
import simics
class simics.pcie_device_interface_t(connected=None, disconnected=None,
hot_reset=None)
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.
This interface is considered tech-preview and may change without notice.
Execution Context
Global Context for all methods.
Name
pcie_function_info — interface used with PCIe
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
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);
map_info_t (*get_bar_map_info)(conf_object_t *obj, uint8 bar_offset);
};
#define PCIE_FUNCTION_INFO_INTERFACE "pcie_function_info"
Python
import simics
class simics.pcie_function_info_interface_t(get_device_id=None,
get_upstream_target=None, is_virtual_function=None,
get_bar_map_obj=None, get_bar_map_info=None)
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).
Execution Context
Cell Context for all methods.
Name
pcie_hotplug_pd_t, pcie_hotplug_mrl_t, pcie_hotplug_events — interface implemented by Hot-Plug capable Downstream Ports
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
typedef enum {
PCIE_HP_PD_Adapter_Not_Present = 0,
PCIE_HP_PD_Adapter_Present = 1
} pcie_hotplug_pd_t;
typedef enum {
PCIE_HP_MRL_Closed = 0,
PCIE_HP_MRL_Open = 1
} pcie_hotplug_mrl_t;
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"
Python
import simics
simics.PCIE_HP_PD_Adapter_Present
simics.PCIE_HP_PD_Adapter_Not_Present
simics.PCIE_HP_MRL_Open
simics.PCIE_HP_MRL_Closed
class simics.pcie_hotplug_events_interface_t(presence_change=None,
power_fault=None, attention_button_pressed=None, mrl_sensor=None,
data_link_layer=None)
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:
- If the applicable Hot-Plug capability has been enabled, set the new value of the corresponding Hot-Plug event in the applicable register.
- If the value changed from its previous value, set the changed register value for the applicable Hot-Plug event.
- 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.
Execution Context
Cell Context for all methods.
Name
pcie_link_control — Interface allowing receiving upstream and downstream
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
SIM_INTERFACE(pcie_link_control) {
void (*downstream_component_blocking)(conf_object_t *obj, bool is_blocking);
void (*upstream_component_blocking)(conf_object_t *obj, bool is_blocking);
void (*request_link_retraining)(conf_object_t *obj);
};
#define PCIE_LINK_CONTROL_INTERFACE "pcie_link_control"
Python
import simics
class simics.pcie_link_control_interface_t(downstream_component_blocking=None,
upstream_component_blocking=None, request_link_retraining=None)
Description
This interface should be implemented by pcie-downstream-ports to receive directions from upstream and downstream components on the link to tear down the link or retrain the link.
Execution Context
Cell Context for all methods.
Name
pcie_link_readiness — Interface for receiving link blocking state changes.
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
SIM_INTERFACE(pcie_link_readiness) {
void (*link_down)(conf_object_t *obj);
void (*link_not_blocking)(conf_object_t *obj);
};
#define PCIE_LINK_READINESS_INTERFACE "pcie_link_readiness"
Python
import simics
class simics.pcie_link_readiness_interface_t(link_down=None,
link_not_blocking=None)
Description
This interface is implemented by PCIe devices so that they can be notified if a link has been torn down by the link blocking mechanism. The implementer of this interface will be notified when the link peer component is blocking or unblocking the link.
Execution Context
Cell Context for all methods.
Name
pcie_link_training — interface used with PCIe training
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
SIM_INTERFACE(pcie_link_training) {
// Deprecated
bool (*trigger)(conf_object_t *obj, uint16 device_id);
bool (*invoke)(conf_object_t *obj);
};
#define PCIE_LINK_TRAINING_INTERFACE "pcie_link_training"
Python
import simics
class simics.pcie_link_training_interface_t(trigger=None, invoke=None)
Description
Trigger link training on obj. The trigger function is deprecated and should not be used. The implementation of trigger ignores the device_id.
Execution Context
Cell Context for all methods.
Name
pcie_map — interface used with PCIe address space
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
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"
Python
import simics
class simics.pcie_map_interface_t(add_map=None, del_map=None, add_function=None,
del_function=None, enable_function=None, disable_function=None,
get_device_id=None)
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.
This interface is considered tech-preview and may change without notice.
Execution Context
Cell Context for all methods.
Name
pcie_port_control — interface used to configure PCIe downstream ports
Synopsis
C and DML
#include <simics/devs/pci.h> // in C
import "simics/devs/pci.dml"; // in DML
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"
Python
import simics
class simics.pcie_port_control_interface_t(set_secondary_bus_number=None,
hot_reset=None)
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
This interface is considered tech-preview and may change without notice.
Execution Context
Cell Context for all methods.
Name
pmr — PPC performance monitor interface
Synopsis
C and DML
#include <simics/arch/ppc.h> // in C
import "simics/arch/ppc.dml"; // in DML
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"
Python
import simics
class simics.pmr_interface_t(get=None, set=None)
Description
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.
Name
port_space — I/O port interface
Synopsis
C and DML
#include <simics/devs/memory-space.h> // in C
import "simics/devs/memory-space.dml"; // in DML
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"
Python
import simics
class simics.port_space_interface_t(port_operation=None, read=None, write=None)
Execution Context
Cell Context for all methods.
Name
ppc_mc_exc_t, ppc — PPC specific interface
Synopsis
C and DML
#include <simics/arch/ppc.h> // in C
import "simics/arch/ppc.dml"; // in DML
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;
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"
Python
import simics
simics.Sim_PPC_L2_Data_Parity
simics.Sim_PPC_Data_Cache_Parity
simics.Sim_PPC970_SLB_Parity
simics.Sim_PPC_Bus_Data_Parity
simics.Sim_PPC970_Data_Cache_Parity
simics.Sim_PPC_Bus_Address_Parity
simics.Sim_PPC_L3_Address_Parity
simics.Sim_PPC970_MC_External
simics.Sim_PPC970_L2_Load_ECC_Parity
simics.Sim_PPC970_L2_Page_Table_ECC_Parity
simics.Sim_PPC970_TLB_Parity
simics.Sim_PPC970_Uncacheable_Load_Parity
simics.Sim_PPC970_D_ERAT_Parity
simics.Sim_PPC_MC_TEA
simics.Sim_PPC_Generic_MC
simics.Sim_PPC_MC_MCP
simics.Sim_PPC970_Data_Cache_Tag_Parity
simics.Sim_PPC_L3_Data_Parity
simics.Sim_PPC_Instruction_Cache_Parity
class simics.ppc_interface_t(clear_atomic_reservation_bit=None,
raise_machine_check_exception=None, get_timebase_enabled=None,
set_timebase_enabled=None, get_sleep_state=None,
set_sleep_state=None)
Description
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 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.
Name
pulse — model a pulse, meaning an event that triggers
Synopsis
C and DML
#include <simics/devs/signal.h> // in C
import "simics/devs/signal.dml"; // in DML
SIM_INTERFACE(pulse) {
void (*pulse)(conf_object_t *NOTNULL obj);
};
#define PULSE_INTERFACE "pulse"
Python
import simics
class simics.pulse_interface_t(pulse=None)
Execution Context
Cell Context for all methods.
Name
ram, rom — provide random access memory
Synopsis
C and DML
#include <simics/device-api.h> // in C
// always available in DML
typedef struct page page_t;
#include <simics/devs/ram.h> // in C
import "simics/devs/ram.dml"; // in DML
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"
Python
import simics
class simics.page_t
simics.Sim_Ram_Op_Fetch
simics.Sim_Ram_Op_Non_Coherent
class simics.ram_interface_t(fill=None, read=None, write=None, touch=None,
size=None)
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).
#define ROM_INTERFACE "rom"
typedef ram_interface_t rom_interface_t;
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.
Execution Context
Cell Context for all methods.
Name
riscv_coprocessor — RISC-V coprocessor interface
Synopsis
C and DML
#include <simics/arch/risc-v.h> // in C
import "simics/arch/risc-v.dml"; // in DML
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"
Python
import simics
class simics.riscv_coprocessor_interface_t(read_register=None,
write_register=None)
Description
This interface makes it possible for RISC-V processors to read and write externally defined Control and Status Registers (CSRs) like mtime.
Execution Context
Threaded Context for all methods.
Name
riscv_csr_access_type_t, riscv_csr_access_cb_t, riscv_reset_cb_t, riscv_custom_csr — interface for implementation of custom RISC-V CSR
Synopsis
C and DML
#include <simics/arch/risc-v-customize.h> // in C
import "simics/arch/risc-v-customize.dml"; // in DML
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);
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"
Python
import simics
simics.Riscv_Int_Register_Access
simics.Riscv_CSR_Instruction_Access
simics.Riscv_Attribute_Access
class simics.riscv_custom_csr_interface_t(register_csr=None, register_reset=None)
Description
The riscv_custom_csr interface lets other Simics objects implement custom Control and Status Registers (CSRs) 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.
The type riscv_csr_access_type_t value shows the kind of access to handle.
access is a callback of type riscv_csr_access_cb_t that will be called for each access to the custom CSR.
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.
Execution Context
Global Context for all methods.
Name
riscv_instruction_action — interface implemented by RISC-V cpus and used to model custom instructions
Synopsis
C and DML
#include <simics/arch/risc-v-customize.h> // in C
import "simics/arch/risc-v-customize.dml"; // in DML
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"
Python
import simics
class simics.riscv_instruction_action_interface_t(read_x_register=None,
write_x_register=None, name_x_register=None, read_csr=None,
write_csr=None, read_memory=None, write_memory=None,
load_memory_buf=None, store_memory_buf=None,
get_current_cpu_mode=None, raise_exception=None)
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. Note: 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 xCAUSE CSR set to code and xTVAL CSR set to tval.
Execution Context
Threaded Context for all methods. Must only be called from within an instruction emulation callback registered using the cpu_instruction_decoder interface.
Name
sata — interface implemented by SATA objects
Synopsis
C and DML
#include <simics/devs/sata-interface.h> // in C
import "simics/devs/sata-interface.dml"; // in DML
SIM_INTERFACE(sata) {
void (*receive_fis)(conf_object_t *obj, const bytes_t fis);
};
#define SATA_INTERFACE "sata"
Python
import simics
class simics.sata_interface_t(receive_fis=None)
Description
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.
Name
scale_factor_listener — interface used for modeling changes in frequency scale factors
Synopsis
C and DML
#include <simics/devs/frequency.h> // in C
import "simics/devs/frequency.dml"; // in DML
SIM_INTERFACE(scale_factor_listener) {
void (*set)(conf_object_t *NOTNULL obj, uint64 numerator,
uint64 denominator);
};
#define SCALE_FACTOR_LISTENER_INTERFACE "scale_factor_listener"
Python
import simics
class simics.scale_factor_listener_interface_t(set=None)
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 set are typically a scale factor rather close to 1, while the parameters of the frequency_listener method set represent a base frequency in Hz, which is typically significantly larger than 1000000.
See the documentation on the frequency_listener interface for more information.
Execution Context
Cell Context for all methods.
Name
TTY_ABORT, serial_device — interface used to connect serial devices together
Synopsis
C and DML
#include <simics/devs/serial-device.h> // in C
// not available in DML
TTY_ABORT;
import "simics/devs/serial-device.dml"; // in DML
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"
Python
import simics
class simics.serial_device_interface_t(write=None, receive_ready=None)
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.
Execution Context
Cell Context for all methods.
Name
serial_peripheral_interface_flags_t — type used with serial_peripheral_interface_slave interface
Synopsis
C and DML
#include <simics/devs/serial-peripheral-interface.h> // in C
import "simics/devs/serial-peripheral-interface.dml"; // in DML
typedef enum serial_peripheral_interface_flags {
SPI_Flags_CPHA = 0x1,
SPI_Flags_CPOL = 0x2
} serial_peripheral_interface_flags_t;
Python
import simics
simics.SPI_Flags_CPOL
simics.SPI_Flags_CPHA
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
Name
serial_peripheral_interface_master — interface implemented by SPI master devices
Synopsis
C and DML
#include <simics/devs/serial-peripheral-interface.h> // in C
import "simics/devs/serial-peripheral-interface.dml"; // in DML
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"
Python
import simics
class simics.serial_peripheral_interface_master_interface_t(spi_response=None)
Description
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 via serial_peripheral_interface_slave. 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.
Execution Context
Cell Context for all methods.
See Also
serial_peripheral_interface_slave
Name
serial_peripheral_interface_slave — interface implemented by all SPI slave devices
Synopsis
C and DML
#include <simics/devs/serial-peripheral-interface.h> // in C
import "simics/devs/serial-peripheral-interface.dml"; // in DML
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"
Python
import simics
class simics.serial_peripheral_interface_slave_interface_t(spi_request=None,
connect_master=None, disconnect_master=None)
Description
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.
Execution Context
Cell Context for all methods.
See Also
serial_peripheral_interface_master, serial_peripheral_interface_flags_t
Name
shared_memory_map_demap — Interface for mapping/unmapping shared memory
Synopsis
C and DML
SIM_INTERFACE(shared_memory_map_demap) {
void (*map)(conf_object_t* obj, uint64 addr, uint64 size);
void (*unmap)(conf_object_t* obj, uint64 addr);
};
#define SHARED_MEMORY_MAP_DEMAP_INTERFACE "shared_memory_map_demap"
Description
Interface to inform a device to map or demap a shared memory region into its address space.
map Called to map a region of shared memory into the peripheral’s address space.
unmap Called to unmap a region of shared memory from the peripheral’s address space.
Execution Context
Cell Context for all methods.
Name
signal — model a logical signal
Synopsis
C and DML
#include <simics/devs/signal.h> // in C
import "simics/devs/signal.dml"; // in DML
SIM_INTERFACE(signal) {
void (*signal_raise)(conf_object_t *NOTNULL obj);
void (*signal_lower)(conf_object_t *NOTNULL obj);
};
#define SIGNAL_INTERFACE "signal"
Python
import simics
class simics.signal_interface_t(signal_raise=None, signal_lower=None)
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 (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.
Execution Context
Cell Context for all methods.
Name
simple_dispatcher — interface for subscribing to frequency related changes
Synopsis
C and DML
#include <simics/devs/frequency.h> // in C
import "simics/devs/frequency.dml"; // in DML
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"
Python
import simics
class simics.simple_dispatcher_interface_t(subscribe=None, unsubscribe=None)
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.
Execution Context
Global Context for all methods.
Name
simple_interrupt — obsolete interface used with interrupts
Synopsis
C and DML
#include <simics/devs/interrupt.h> // in C
import "simics/devs/interrupt.dml"; // in DML
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"
Python
import simics
class simics.simple_interrupt_interface_t(interrupt=None, interrupt_clear=None)
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>).
Obsoleted by the signal interface.
Execution Context
Cell Context for all methods.
Name
smm_instrumentation_subscribe — x86 specific interface for smm mode instrumentation
Synopsis
C and DML
#include <simics/arch/x86-instrumentation.h> // in C
import "simics/arch/x86-instrumentation.dml"; // in DML
SIM_INTERFACE(smm_instrumentation_subscribe) {
cpu_cb_handle_t *(*register_smm_enter_before_cb)(
conf_object_t *cpu,
conf_object_t *connection,
smm_switch_cb_t cb,
lang_void *user_data);
cpu_cb_handle_t *(*register_smm_enter_after_cb)(
conf_object_t *cpu,
conf_object_t *connection,
smm_switch_cb_t cb,
lang_void *user_data);
cpu_cb_handle_t *(*register_smm_leave_before_cb)(
conf_object_t *cpu,
conf_object_t *connection,
smm_switch_cb_t cb,
lang_void *user_data);
cpu_cb_handle_t *(*register_smm_leave_after_cb)(
conf_object_t *cpu,
conf_object_t *connection,
smm_switch_cb_t cb,
lang_void *user_data);
};
#define SMM_INSTRUMENTATION_SUBSCRIBE_INTERFACE \
"smm_instrumentation_subscribe"
Python
import simics
class simics.smm_instrumentation_subscribe_interface_t(register_smm_enter_before_cb=None,
register_smm_enter_after_cb=None, register_smm_leave_before_cb=None,
register_smm_leave_after_cb=None)
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.
Execution Context
Global Context for all methods.
Name
sparc_v8_ecc_fault_injection — interface for error injection with SPARC V8
Synopsis
C and DML
#include <simics/arch/sparc-v8.h> // in C
// not available in DML
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"
Description
Support the injection of uncorrectable ECC faults. It can be used to inject
- V8_Exc_Data_Access_Exception,
- V8_Exc_Instruction_Access_Exception, and
- 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.
Name
sparc_v8 — interface for SPARC V8 specific functions
Synopsis
C and DML
#include <simics/arch/sparc-v8.h> // in C
// not available in DML
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"
Description
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.
Name
spr — interface for ppc special function registers
Synopsis
C and DML
#include <simics/arch/ppc.h> // in C
import "simics/arch/ppc.dml"; // in DML
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"
Python
import simics
class simics.spr_interface_t(register_user_handlers=None,
unregister_user_handlers=None, set_target_value=None,
stash_value=None, fetch_value=None, default_getter=None,
default_setter=None, get_name=None, get_number=None)
Description
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 type gen_spr_user_getter_func_t.
The type parameter in the get and set functions is of the type gen_spr_access_type_t.
Both the get and the set functions must return a value of the type 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
- Global Context
register_user_handlers
unregister_user_handlers
- Cell Context
set_target_value
stash_value
fetch_value
default_getter
default_setter
get_name
get_number
Name
telemetry_class_id_t, telemetry_id_t, telemetry — interface for accessing or providing arbitrary data
Synopsis
C and DML
#include <simics/devs/telemetry-interface.h> // in C
import "simics/devs/telemetry-interface.dml"; // in DML
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"
Python
import simics
class simics.telemetry_interface_t(get_telemetry_class_id=None,
get_telemetry_class_name=None, get_telemetry_class_description=None,
get_telemetry_id=None, get_telemetry_name=None,
get_telemetry_description=None, get_value=None)
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.
get_telemetry_id 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.
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.
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.
get_value function returns the value for the telemetry_id within telemetry_class_id.
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.
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.
Execution Context
Global Context for all methods.
Name
transaction_translator — interface used to inspect and/or modify transactions
Synopsis
C and DML
#include <simics/devs/translator.h> // in C
import "simics/devs/translator.dml"; // in DML
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"
Python
import simics
class simics.transaction_translator_interface_t(translate=None)
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.
Execution Context
Cell Context for all methods.
See Also
translation_t, translation_flush interface, SIM_map_target_flush
Name
translate — implemented by objects that bridge between memory spaces
Synopsis
C and DML
#include <simics/devs/memory-space.h> // in C
import "simics/devs/memory-space.dml"; // in DML
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"
Python
import simics
class simics.translate_interface_t(translate=None)
Description
The translate interface is implemented by objects that bridge between memory spaces.
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).
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.
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.
Execution Context
Cell Context for all methods.
Name
translation_flush — optional interface used with address translation
Synopsis
C and DML
#include <simics/devs/translator.h> // in C
import "simics/devs/translator.dml"; // in DML
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"
Python
import simics
class simics.translation_flush_interface_t(flush_range=None)
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
Execution Context
Cell Context
Name
translator — interface implemented for address translation
Synopsis
C and DML
#include <simics/devs/translator.h> // in C
import "simics/devs/translator.dml"; // in DML
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"
Python
import simics
class simics.translator_interface_t(translate=None)
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).
Execution Context
Cell Context
See Also
translation_t, SIM_map_target_flush
Name
uint64_state — interface used in transferring state between devices
Synopsis
C and DML
#include <simics/model-iface/state.h> // in C
import "simics/model-iface/state.dml"; // in DML
SIM_INTERFACE(uint64_state) {
void (*set)(conf_object_t *NOTNULL obj, uint64 level);
};
#define UINT64_STATE_INTERFACE "uint64_state"
Python
import simics
class simics.uint64_state_interface_t(set=None)
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)
The uint64_state interface should be used instead of the deprecated multi_level_signal interface when writing new models.
Execution Context
Cell Context for all methods.
Name
usb_device — interface implemented by USB devices
Synopsis
C and DML
#include <simics/devs/usb.h> // in C
import "simics/devs/usb.dml"; // in DML
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"
Python
import simics
class simics.usb_device_interface_t(submit_transfer=None, abort_transfer=None,
reset=None)
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, 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.
Execution Context
Cell Context for all methods.
Name
usb — interface used in communication with USB hosts
Synopsis
C and DML
#include <simics/devs/usb.h> // in C
import "simics/devs/usb.dml"; // in DML
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"
Python
import simics
class simics.usb_interface_t(connect_device=None, disconnect_device=None,
complete_transfer=None)
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 interface documentation to know more about how a transfer is sent to the USB device.
Execution Context
- Global Context
connect_device
disconnect_device Cell Context
complete_transfer
Name
vectored_interrupt — interface used with vectored interrupts
Synopsis
C and DML
#include <simics/devs/vectored-interrupt.h> // in C
import "simics/devs/vectored-interrupt.dml"; // in DML
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"
Python
import simics
class simics.vectored_interrupt_interface_t(set_level=None)
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.
Execution Context
Cell Context for all methods.
Name
vectored_interrupt_source — interface implemented by interrupt sources
Synopsis
C and DML
#include <simics/devs/vectored-interrupt.h> // in C
import "simics/devs/vectored-interrupt.dml"; // in DML
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"
Python
import simics
class simics.vectored_interrupt_source_interface_t(acknowledge=None)
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.
Execution Context
Cell Context for all methods.
Name
virtiofs_fuse — FUSE request handler interface
Synopsis
C and DML
SIM_INTERFACE(virtiofs_fuse)
{
buffer_t (*handle_request)(conf_object_t * obj, bytes_t req);
};
#define VIRTIOFS_FUSE_INTERFACE "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.
Execution Context
Cell Context for all methods.
Name
vmp — control VMP from a user perspective
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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"
Python
import simics
class simics.vmp_interface_t(class_has_support=None, host_support=None,
compatible_config=None, enable=None, disable=None, enabled=None,
set_threshold=None, get_feature=None, set_feature=None,
get_info=None)
Description
This is an internal interface between VMP and the Simics Base package, and it may change at any time without notice.
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.
Execution Context
Cell Context for all methods.
Name
vmx_instrumentation_subscribe — x86 specific interface for vmx mode instrumentation
Synopsis
C and DML
#include <simics/arch/x86-instrumentation.h> // in C
import "simics/arch/x86-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.vmx_instrumentation_subscribe_interface_t(register_vmx_mode_leave_cb=None,
register_vmx_mode_enter_cb=None)
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 different VMX modes are defined by 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.
Execution Context
Global Context for all methods.
Name
x86_access_type — information about the x86_access_type_t enum
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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"
Python
import simics
class simics.x86_access_type_interface_t(get_enum_name=None, get_short_name=None,
get_description=None, implicit=None)
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.
Execution Context
Cell Context for all methods.
Name
x86_address_query — interface for x86 specific address queries
Synopsis
C and DML
#include <simics/arch/x86-instrumentation.h> // in C
import "simics/arch/x86-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.x86_address_query_interface_t(segment=None,
get_page_crossing_info=None)
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_address_cb_t callback.
The segment is used to get the segment register used in the address calculation. The handle is the address handle passed to cpu_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.
Name
x86_cache_flush — flush x86 specific caches
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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"
Python
import simics
class simics.x86_cache_flush_interface_t(flush=None)
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.
Execution Context
Cell Context for all methods.
Name
cpuid_ret_t, x86_cpuid — customize responses to CPUID requests
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
typedef struct {
int taken;
uint64 out_a;
uint64 out_b;
uint64 out_c;
uint64 out_d;
} cpuid_ret_t;
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"
Python
import simics
class simics.cpuid_ret_t(taken=0, out_a=0, out_b=0, out_c=0, out_d=0)
class simics.x86_cpuid_interface_t(cpuid=None)
Description
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.
Name
cpuid_value_t, x86_cpuid_query — query values returned by the CPUID instruction
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
typedef struct {
uint64 a, b, c, d;
} cpuid_value_t;
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"
Python
import simics
class simics.cpuid_value_t(a=0, b=0, c=0, d=0)
class simics.x86_cpuid_query_interface_t(cpuid_query=None)
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.
Execution Context
Cell Context for all methods.
Name
x86_cstate_event_t — Enumeration of all supported reasons for a C-state change
Synopsis
C and DML
typedef enum {
X86_Cstate_Event_Unspecified,
X86_Cstate_Event_Hlt,
X86_Cstate_Event_Mwait,
X86_Cstate_Event_External,
X86_Cstate_Event_Wakeup,
X86_Cstate_Event_MonitorWakeup,
X86_Cstate_Event_IntrWakeup,
X86_Cstate_Event_MwaitTimerWakeup,
X86_Cstate_Event_Max
} x86_cstate_event_t;
Name
x86_cstate_t, x86_cstate — interface used with x86 power states
Synopsis
C and DML
#include <simics/devs/x86-cstate-iface.h> // in C
import "simics/devs/x86-cstate-iface.dml"; // in DML
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"
Python
import simics
class simics.x86_cstate_t(state=0, sub_state=0)
class simics.x86_cstate_interface_t(get_cstate=None, set_cstate=None)
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.
Execution Context
Cell Context for all methods.
Name
x86_cstate_notification — interface used with x86 power states
Synopsis
C and DML
#include <simics/devs/x86-cstate-iface.h> // in C
import "simics/devs/x86-cstate-iface.dml"; // in DML
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"
Python
import simics
class simics.x86_cstate_notification_interface_t(notification=None)
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.
Execution Context
Cell Context.
Name
x86_cstate_notification_v2 — Interface to notifyabout C-state transitions
Synopsis
C and DML
SIM_INTERFACE(x86_cstate_notification_v2) {
void (*notification)(conf_object_t *listener, conf_object_t *cpu,
const x86_cstate_notify_info_t *info);
};
#define X86_CSTATE_NOTIFICATION_V2_INTERFACE "x86_cstate_notification_v2"
Description
The interface is used to notify the listener about the processor C-state transitions.
The info contains information about the source of change and current C-state of the processor cpu.
A state value of 0 corresponds to C0, a value of 1 corresponds to C1, etc. HLT is reported as state 1, substate 0. MWAIT is reported based upon the eax hint, decoded as state = (eax[7:4] + 1) mod 16, substate = eax[3:0].
Name
x86_cstate_notify_info_t — Contains C-state event info
Synopsis
C and DML
typedef struct {
x86_cstate_event_t event;
uint32 state;
uint32 sub_state;
} x86_cstate_notify_info_t;
Name
x86_doma_cstate_info_v2_t — Info about cstates
Synopsis
C and DML
typedef struct {
uint32 state;
uint32 sub_state;
uint64 deadline;
uint64 tsc;
} x86_doma_cstate_info_v2_t;
Name
x86_doma_cstate_v3 — Interface that provides callbacks on cstate changes
Synopsis
C and DML
SIM_INTERFACE(x86_doma_cstate_v3)
{
void (*notify_sleep)(conf_object_t *listener, conf_object_t *cpu,
const x86_doma_cstate_info_v2_t *info);
void (*notify_resume)(conf_object_t *listener,
const x86_doma_cstate_info_v2_t *info);
void (*notify_waiting_interrupt)(conf_object_t *listener,
bool is_waiting);
void (*notify_reset)(conf_object_t *listener);
};
#define X86_DOMA_CSTATE_V3_INTERFACE "x86_doma_cstate_v3"
Description
For notify_sleep, and notify_resume, the cstate information is in the info x86_doma_cstate_info_v2_t argument.
Name
x86_ept — provides insight into the Extended Page Table (EPT)
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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"
Python
import simics
class simics.x86_ept_interface_t(guest_physical_to_physical=None,
is_ept_active=None)
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.
Execution Context
Cell Context for all methods.
Name
x86_eri_v1 — For read/write of ERI registers
Synopsis
C and DML
SIM_INTERFACE(x86_eri_v1) {
void (*read)(conf_object_t *listener,
uint64 reg_num, eri_transaction_t *data);
void (*write)(conf_object_t *listener,
uint64 reg_num, eri_transaction_t *data);
};
#define X86_ERI_V1_INTERFACE "x86_eri_v1"
Description
The interface is used to read/writer external registers.
data (with type eri_transaction_t) is owned by caller. Callee always fills field valid to cate transaction result. Field val contains the result of read method input for write method.
Name
x86_eri_v2 — For read/write of ERI registers
Synopsis
C and DML
SIM_INTERFACE(x86_eri_v2) {
void (*read)(conf_object_t *listener, eri_v2_transaction_t *data);
void (*write)(conf_object_t *listener, eri_v2_transaction_t *data);
};
#define X86_ERI_V2_INTERFACE "x86_eri_v2"
Description
The interface is used to read/writer external registers.
data (with type eri_v2_transaction_t) is owned by caller. Callee always fills field valid to cate transaction result. Field val contains the result of read method input for write method.
Name
x86_exception — raise x86 exceptions
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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"
Python
import simics
class simics.x86_exception_interface_t(DE_fault=None, BR_fault=None,
UD_fault=None, NM_fault=None, DF_abort=None, TS_fault=None,
NP_fault=None, SS_fault=None, GP_fault=None, PF_fault=None,
MF_fault=None, AC_fault=None, XM_fault=None)
Description
This interface is internal and may change without notice.
The methods in this interface are 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.
Execution Context
The methods in this interface may only be called from user decoder service routines.
Name
x86_exception_query — interface for x86 specific exception queries
Synopsis
C and DML
#include <simics/arch/x86-instrumentation.h> // in C
import "simics/arch/x86-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.x86_exception_query_interface_t(vector=None, source=None,
error_code=None)
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.
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.
Name
x86_execution_mode_t, x86_execution_mode — provides insight into the processor execution mode
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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"
Python
import simics
class simics.x86_execution_mode_t
class simics.x86_execution_mode_interface_t(get_execution_mode=None)
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.
Execution Context
Cell Context for all methods.
Name
x86_external_reset — interface that notifies clients of reset
Synopsis
C and DML
SIM_INTERFACE(x86_external_reset) {
void (*triple_fault_event)(conf_object_t *obj);
};
#define X86_EXTERNAL_RESET_INTERFACE "x86_external_reset"
Description
The interface is used to notify platform devices about reset events that happened inside a CPU.
The triple_fault_event method is used to inform obj that a reset happened due to a triple fault.
Execution Context
Cell Context for all methods.
Name
x86_instruction_query — interface for x86 specific instrumentation queries
Synopsis
C and DML
#include <simics/arch/x86-instrumentation.h> // in C
import "simics/arch/x86-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.x86_instruction_query_interface_t(linear_address=None)
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.
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.
Name
x86_instrumentation_subscribe — interface for x86 specific instrumentation subscribe
Synopsis
C and DML
#include <simics/arch/x86-instrumentation.h> // in C
import "simics/arch/x86-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.x86_instrumentation_subscribe_interface_t(register_mode_switch_cb=None,
register_illegal_instruction_cb=None)
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.
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 callback has the type [x86_mode_switch_cb_t].
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 type of the callback is cpu_instruction_decoder_cb_t
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. The callback should be of type cpu_instruction_disassemble_cb_t.
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.
Name
x86_instrumentation_subscribe_v2 — interface for x86 specific instrumentation subscribe
Synopsis
C and DML
#include <simics/arch/x86-instrumentation.h> // in C
import "simics/arch/x86-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.x86_instrumentation_subscribe_v2_interface_t(register_mode_enter_cb=None,
register_mode_leave_cb=None, register_illegal_instruction_cb=None)
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.
Execution Context
Global Context for all methods.
Name
x86_pin_t, tagged_linear_address_t, x86 — x86 specific functionality
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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;
typedef struct {
bool valid;
linear_address_t addr;
} tagged_linear_address_t;
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"
Python
import simics
simics.Pin_Mcerr
simics.Pin_Cmci
simics.Pin_Smi
simics.Pin_Init
simics.Pin_Nmi
simics.Pin_Ignne
class simics.tagged_linear_address_t(valid=False, addr=0)
class simics.x86_interface_t(set_pin_status=None, start_up=None, interrupt=None,
uninterrupt=None, has_pending_interrupt=None,
has_waiting_interrupt=None, logical_to_linear=None,
linear_to_physical=None, enter_acpi_c2_state=None)
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.
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.
Execution Context
Cell Context for all methods.
Name
x86_alignment_t, x86_read_physical_ret_t, x86_memory_access — access x86 memory from user decoder service routines
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
typedef enum {
X86_Alignment_Not_Required,
X86_Alignment_Required
} x86_alignment_t;
typedef struct {
uint64 value;
exception_type_t exception;
} x86_read_physical_ret_t;
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"
Python
import simics
simics.X86_Alignment_Required
simics.X86_Alignment_Not_Required
class simics.x86_memory_access_interface_t(read_logical=None, write_logical=None)
Description
This interface is internal and may change without notice.
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.
Execution Context
The methods in this interface may only be called from user decoder service routines.
Name
x86_memory_operation — access memory from a user instruction
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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"
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.
Execution Context
Cell Context for all methods, but must be called from an invoke function set by the register_emulation_cb method in the cpu_instruction_decoder interface.
Name
x86_memory_query — interface for x86 specific memory instrumentation queries
Synopsis
C and DML
#include <simics/arch/x86-instrumentation.h> // in C
import "simics/arch/x86-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.x86_memory_query_interface_t(linear_address=None, segment=None,
access_type=None, memory_type=None)
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.
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.
Name
x86_monitor — interface for supporting MONITOR/MWAIT instructions
Synopsis
C and DML
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"
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 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_address1 up to start_address + length - 1, returns true on success. Thedisarmunsubscribeslistener`, so the latter won’t be notified about writes to a monitored memory range, returns true on success.
Execution Context
Cell Context for all methods.
Name
x86_monitor_notification — interface for getting a callback for writes to write-ack memory
Synopsis
C and DML
SIM_INTERFACE(x86_monitor_notification) {
bool (*notify)(conf_object_t *obj);
};
#define X86_MONITOR_NOTIFICATION_INTERFACE "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 to find out how to subscribe for write notifications to a write-back memory range.
Execution Context
Cell Context.
Name
x86_msr_access_type_t, x86_msr_ret_t, x86_msr_getter_ret_t, x86_msr — x86 msr interface
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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;
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 struct {
x86_msr_ret_t status;
uint64 value;
} x86_msr_getter_ret_t;
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"
Python
import simics
simics.Sim_X86_Msr_Attribute_Access
simics.Sim_X86_Msr_Architectural_Access
simics.Sim_X86_Msr_Int_Register_Access
simics.Sim_X86_Msr_Instruction_Access
simics.Sim_X86_Msr_VMX_Access
simics.Sim_X86_Msr_GP_Fault
simics.Sim_X86_Msr_Ok
simics.Sim_X86_Msr_Not_Handled
class simics.x86_msr_getter_ret_t(status=0, value=0)
class simics.x86_msr_interface_t(register_handlers=None, unregister_handlers=None,
get=None, set=None, get_name=None, get_number=None,
get_all_valid_numbers=None)
Description
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 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.
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.
Name
x86_pkg_cstate — interface used with x86 power states
Synopsis
C and DML
#include <simics/devs/x86-cstate-iface.h> // in C
import "simics/devs/x86-cstate-iface.dml"; // in DML
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"
Python
import simics
class simics.x86_pkg_cstate_interface_t(get_pkg_cstate=None, set_pkg_cstate=None,
pkg_cstate_update=None)
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) mid 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.
Execution Context
Cell Context for all methods.
Name
x86_rar_interrupt — interface for providing CPU with RAR interrupt info
Synopsis
C and DML
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"
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.
Execution Context
Cell Context for all methods.
Name
x86_xmode_info_t, ymm_reg_t, xmm_reg_t, x86_exec_mode_t, x86_detailed_exec_mode_t, x86_fpu_reg_t, x86_fpu_env_t, x86_seg_t, x86_reg_access — access x86 register state
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
typedef struct {
bool efer_lma;
bool cs_l;
bool cs_d;
bool ss_b;
} x86_xmode_info_t;
typedef struct {
uint64 llo64;
uint64 lhi64;
uint64 hlo64;
uint64 hhi64;
} ymm_reg_t;
typedef struct {
uint64 lo64;
uint64 hi64;
} xmm_reg_t;
typedef enum {
X86_Exec_Mode_Real,
X86_Exec_Mode_V86,
X86_Exec_Mode_Prot,
X86_Exec_Mode_Compat,
X86_Exec_Mode_64
} x86_exec_mode_t;
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;
typedef struct {
uint64 low;
uint16 high;
} x86_fpu_reg_t;
typedef struct {
uint16 cw;
uint16 sw;
uint16 tag;
uint16 opc;
uint64 last_instr_ptr;
uint64 last_operand_ptr;
uint16 last_instr_sel;
uint16 last_operand_sel;
uint32 pad;
} x86_fpu_env_t;
typedef enum {
X86_Seg_ES,
X86_Seg_CS,
X86_Seg_SS,
X86_Seg_DS,
X86_Seg_FS,
X86_Seg_GS,
X86_Seg_LDTR,
X86_Seg_TR,
X86_Seg_None,
} x86_seg_t;
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"
Python
import simics
class simics.x86_xmode_info_t(efer_lma=False, cs_l=False, cs_d=False, ss_b=False)
class simics.ymm_reg_t(llo64=0, lhi64=0, hlo64=0, hhi64=0)
class simics.xmm_reg_t(lo64=0, hi64=0)
simics.X86_Exec_Mode_Real
simics.X86_Exec_Mode_Compat
simics.X86_Exec_Mode_Prot
simics.X86_Exec_Mode_V86
simics.X86_Exec_Mode_64
simics.X86_Detailed_Exec_Mode_Real_16
simics.X86_Detailed_Exec_Mode_Real_32
simics.X86_Detailed_Exec_Mode_V86
simics.X86_Detailed_Exec_Mode_Protected_64
simics.X86_Detailed_Exec_Mode_Compatibility_32
simics.X86_Detailed_Exec_Mode_Protected_32
simics.X86_Detailed_Exec_Mode_Protected_16
simics.X86_Detailed_Exec_Mode_Compatibility_16
class simics.x86_fpu_reg_t(low=0, high=0)
class simics.x86_fpu_env_t(cw=0, sw=0, tag=0, opc=0, last_instr_ptr=0,
last_operand_ptr=0, last_instr_sel=0, last_operand_sel=0, pad=0)
simics.X86_Seg_CS
simics.X86_Seg_LDTR
simics.X86_Seg_GS
simics.X86_Seg_FS
simics.X86_Seg_None
simics.X86_Seg_ES
simics.X86_Seg_DS
simics.X86_Seg_SS
simics.X86_Seg_TR
class simics.x86_reg_access_interface_t(get_gpr=None, set_gpr=None, get_rip=None,
set_rip=None, get_rflags=None, set_rflags=None,
set_status_flags=None, get_seg=None, set_seg=None,
get_system_seg=None, set_system_seg=None, get_cr=None, set_cr=None,
get_efer=None, set_efer=None, get_xcr=None, set_xcr=None,
get_freg=None, set_freg=None, get_fpu_env=None, set_fpu_env=None,
get_xmm=None, set_xmm=None, get_ymm=None, set_ymm=None,
get_mxcsr=None, set_mxcsr=None, get_dr=None, set_dr=None,
get_in_smm=None, set_in_smm=None, get_smm_base=None,
set_smm_base=None, get_monitor_info=None, set_monitor_info=None,
get_mwait_info=None, set_mwait_info=None, get_activity_state=None,
set_activity_state=None, get_interruptibility_state=None,
set_interruptibility_state=None, get_pending_debug_exc=None,
set_pending_debug_exc=None, get_xmode_info=None, get_exec_mode=None,
get_mxcsr_mask=None, get_ext_state_dirty_bits=None,
or_ext_state_dirty_bits=None, and_ext_state_dirty_bits=None,
get_pdpte=None, set_pdpte=None, get_vmx_mode=None)
Description
This interface is internal and may change without notice.
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.
Execution Context
Cell Context for all methods.
Name
x86_sai — interface for retrieving current sai
Synopsis
C and DML
SIM_INTERFACE(x86_sai) {
uint64 (*get_current_sai)(conf_object_t *obj);
};
#define X86_SAI_INTERFACE "x86_sai"
Name
x86_smm — custom SMRAM state save map
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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"
Python
import simics
class simics.x86_smm_interface_t(save_state=None, restore_state=None)
Description
This interface is internal and may change without notice.
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.
Execution Context
Cell Context for all methods.
Name
x86_smm_event_type_t, x86_smm_phase_type_t, x86_smm_notification — interface for registering callbacks on SMI
Synopsis
C and DML
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"
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.
Execution Context
Cell Context.
Name
x86_smm_state — access x86 smm state
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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"
Python
import simics
class simics.x86_smm_state_interface_t(get_state=None, set_state=None,
smram_read=None, smram_write=None)
Description
This interface is internal and may change without notice.
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.
Execution Context
Cell Context for all methods.
Name
tagged_physical_address_t, x86_tlb — used to communicate between x86 cpu and its TLB
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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"
Python
import simics
class simics.tagged_physical_address_t
class simics.x86_tlb_interface_t(flush_all=None, flush_page=None, lookup=None,
add=None, itlb_lookup=None, set_pae_mode=None)
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.
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.
Name
x86_tlb_attrs_t, x86_tlb_entry_t, x86_tlb_v2 — used to communicate between x86 cpu and its TLB
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
typedef struct {
access_t supervisor_access;
access_t user_access;
bool global_page;
x86_memory_type_t pat_type;
x86_memory_type_t mtrr_type;
unsigned page_size_k;
} x86_tlb_attrs_t;
typedef struct {
linear_address_t linear_page_start;
physical_address_t physical_page_start;
x86_tlb_attrs_t attrs;
} x86_tlb_entry_t;
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"
Python
import simics
class simics.x86_tlb_attrs_t
class simics.x86_tlb_entry_t
class simics.x86_tlb_v2_interface_t(flush_all=None, flush_page=None, lookup=None,
add=None, itlb_lookup=None)
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.
Execution Context
Cell Context for all methods.
Name
x86_tlb_attrs_v3_t, x86_tlb_entry_v3_t, x86_tlb_inv_t, x86_tlb_v3 — used to communicate between x86 cpu and its TLB
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
typedef struct {
uint64 pte_attrs;
x86_memory_type_t pat_type;
x86_memory_type_t mtrr_type;
unsigned page_size_k;
} x86_tlb_attrs_v3_t;
typedef struct {
linear_address_t linear_page_start;
physical_address_t physical_page_start;
x86_tlb_attrs_v3_t attrs;
} x86_tlb_entry_v3_t;
typedef enum {
X86_Tlb_Invalidate_Page = 0,
X86_Tlb_Invalidate_Address_Space = 4,
X86_Tlb_Invalidate_Address_Space_NonGlobal = 1,
X86_Tlb_Invalidate_All = 2,
X86_Tlb_Invalidate_All_NonGlobal = 3
} x86_tlb_inv_t;
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"
Python
import simics
class simics.x86_tlb_attrs_v3_t(pte_attrs=0, pat_type=X86_None,
mtrr_type=X86_None, page_size_k=0)
class simics.x86_tlb_entry_v3_t
simics.X86_Tlb_Invalidate_All_NonGlobal
simics.X86_Tlb_Invalidate_All
simics.X86_Tlb_Invalidate_Address_Space_NonGlobal
simics.X86_Tlb_Invalidate_Address_Space
simics.X86_Tlb_Invalidate_Page
class simics.x86_tlb_v3_interface_t(add=None, lookup=None, itlb_lookup=None,
invalidate_page=None, invalidate=None)
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.
Execution Context
Cell Context for all methods.
Name
x86_txt_chipset — interface to Intel® Trusted Execution Technology (Intel® TXT)
Synopsis
C and DML
SIM_INTERFACE(x86_txt_chipset) {
void (*signal_txt_msg)(conf_object_t *obj, txt_msg_t txt_msg,
uint8 package_id);
//supporting method to report platform capabilities to processor
bool (*get_platform_feature)(conf_object_t *obj, int feature);
//get list of cpus (threads) available in the current system
attr_value_t (*get_platform_cpus)(conf_object_t *obj);
};
#define X86_TXT_CHIPSET_INTERFACE "x86_txt_chipset"
Description
This interface is meant to be implemented by Intel® Trusted Execution Technology (Intel® TXT) chipset. Refer to the “Intel® Trusted Execution Technology Software Development Guide Measured Launched Environment Developer’s Guide” document for explanation of interactions between CPU and Intel® TXT chipset.
This interface is internal and may change without notice.
The signal_txt_msg method is to send TXT-specific message to chipset. The get_platform_feature method is to query the chipset for supported Intel® TXT features. The get_platform_cpus method returns a list of all logical processors connected to the chipset.
Execution Context
Cell Context for all methods.
Name
x86_unplug — interface for plug and and plug of CPU cores/threads
Synopsis
C and DML
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"
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).
Execution Context
Cell Context for all methods.
Name
x86_unplug_v2 — interface for plug and and plug of CPU cores/threads
Synopsis
C and DML
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"
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).
Execution Context
Cell Context for all methods.
Name
x86_vmp_control — block VMP from being used
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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"
Python
import simics
class simics.x86_vmp_control_interface_t(get_block_count=None,
set_block_count=None)
Description
This interface is internal and may change without notice.
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.
Execution Context
Cell Context for all methods.
Name
xed_access — call into the call Intel\reg; XED library
Synopsis
C and DML
#include <simics/arch/x86.h> // in C
import "simics/arch/x86.dml"; // in DML
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"
Python
import simics
class simics.xed_access_interface_t(get_last=None, decode=None, to_string=None)
Description
This interface is internal and may change without notice.
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.
Execution Context
Cell Context for all methods.
Name
xtensa_export_state — TIE interface for the export state type
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
SIM_INTERFACE(xtensa_export_state) {
void (*register_export_state)(conf_object_t *obj,
lang_void *user_object,
lang_void *export_state_func);
};
#define XTENSA_EXPORT_STATE_INTERFACE "xtensa_export_state"
Python
import simics
class simics.xtensa_export_state_interface_t(register_export_state=None)
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.
Name
xtensa_import_wire — TIE interface for the import wire type
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
SIM_INTERFACE(xtensa_import_wire) {
void (*register_import_wire)(conf_object_t *obj,
lang_void *user_object,
lang_void *import_wire_func);
};
#define XTENSA_IMPORT_WIRE_INTERFACE "xtensa_import_wire"
Python
import simics
class simics.xtensa_import_wire_interface_t(register_import_wire=None)
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.
Name
xtensa_input_queue — TIE interface for the input queue type
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
SIM_INTERFACE(xtensa_input_queue) {
void (*register_input_queue)(conf_object_t *obj,
lang_void *user_object,
lang_void *empty_callback,
lang_void *data_callback);
};
#define XTENSA_INPUT_QUEUE_INTERFACE "xtensa_input_queue"
Python
import simics
class simics.xtensa_input_queue_interface_t(register_input_queue=None)
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.
Name
xtensa_internal_memories — interface implemented by all Xtensa cores
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
SIM_INTERFACE(xtensa_internal_memories) {
attr_value_t (*iram_mappings)(conf_object_t *obj);
attr_value_t (*irom_mappings)(conf_object_t *obj);
attr_value_t (*dram_mappings)(conf_object_t *obj);
attr_value_t (*drom_mappings)(conf_object_t *obj);
};
#define XTENSA_INTERNAL_MEMORIES_INTERFACE "xtensa_internal_memories"
Python
import simics
class simics.xtensa_internal_memories_interface_t(iram_mappings=None,
irom_mappings=None, dram_mappings=None, drom_mappings=None)
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.
Name
xtensa_lookup — Xtensa TIE interface for the lookup type
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
SIM_INTERFACE(xtensa_lookup) {
void (*register_lookup)(conf_object_t *obj,
lang_void *user_object,
lang_void *lookup_func);
};
#define XTENSA_LOOKUP_INTERFACE "xtensa_lookup"
Python
import simics
class simics.xtensa_lookup_interface_t(register_lookup=None)
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.
Name
xtensa_mpu_lookup_t, xtensa_mpu_lookup — interface used with xtensa MPU
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
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"
Python
import simics
class simics.xtensa_mpu_lookup_t(background=False, region=0, start=0, end=0,
sr=False, sw=False, sx=False, ur=False, uw=False, ux=False)
class simics.xtensa_mpu_lookup_interface_t(mpu_region=None)
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.
Execution Context
Cell Context for all methods.
Name
xtensa_output_queue — TIE interface for the output queue type
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
SIM_INTERFACE(xtensa_output_queue) {
void (*register_output_queue)(conf_object_t *obj,
lang_void *user_object,
lang_void *full_callback,
lang_void *data_callback);
};
#define XTENSA_OUTPUT_QUEUE_INTERFACE "xtensa_output_queue"
Python
import simics
class simics.xtensa_output_queue_interface_t(register_output_queue=None)
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.
Name
xtensa_reset_configure — interface implemented by Xtensa cores
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
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"
Python
import simics
class simics.xtensa_reset_configure_interface_t(set_reset_prid=None,
set_alternative_reset_vector=None)
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.
Execution Context
Threaded Context for all methods.
Name
xtensa_tie_export_state — interface for tie communication with xtensa
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
SIM_INTERFACE(xtensa_tie_export_state) {
void (*data)(conf_object_t *obj, uint32 bit_width, const uint32 *out_data);
};
#define XTENSA_TIE_EXPORT_STATE_INTERFACE "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.
Name
xtensa_tie_import_wire — interface for tie communication with xtensa
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
SIM_INTERFACE(xtensa_tie_import_wire) {
void (*data)(conf_object_t *obj, uint32 bit_width, uint32 *in_data);
};
#define XTENSA_TIE_IMPORT_WIRE_INTERFACE "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.
Name
xtensa_tie_input_queue — interface for tie communication with xtensa
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
SIM_INTERFACE(xtensa_tie_input_queue) {
bool (*empty)(conf_object_t *obj);
void (*data)(conf_object_t *obj, uint32 bit_width, bool is_peek, uint32 *in_data);
};
#define XTENSA_TIE_INPUT_QUEUE_INTERFACE "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.
Name
xtensa_tie_lookup — interface for tie communication with xtensa
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
SIM_INTERFACE(xtensa_tie_lookup) {
void (*data)(conf_object_t *obj,
uint32 out_width, const uint32 *out_data,
uint32 in_width, uint32 *in_data);
};
#define XTENSA_TIE_LOOKUP_INTERFACE "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.
Name
xtensa_tie_output_queue — interface for tie communication with xtensa
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
SIM_INTERFACE(xtensa_tie_output_queue) {
bool (*full)(conf_object_t *obj);
void (*data)(conf_object_t *obj, uint32 bit_width, bool reserve_only, const uint32 *out_data);
};
#define XTENSA_TIE_OUTPUT_QUEUE_INTERFACE "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.
Name
xtensa_wwdt_config — internal interface for WWDT communication
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
SIM_INTERFACE(xtensa_wwdt_config) {
bool (*has_wwdt)(conf_object_t *obj);
uint32 (*reset_val)(conf_object_t *obj);
uint32 (*hb_reset_val)(conf_object_t *obj);
uint32 (*ikey)(conf_object_t *obj);
uint32 (*bkey)(conf_object_t *obj);
uint32 (*rkey)(conf_object_t *obj);
uint32 (*kkey)(conf_object_t *obj);
uint32 (*ekey)(conf_object_t *obj);
uint32 (*c1key)(conf_object_t *obj);
uint32 (*c2key)(conf_object_t *obj);
uint32 (*t1key)(conf_object_t *obj);
uint32 (*t2key)(conf_object_t *obj);
};
#define XTENSA_WWDT_CONFIG_INTERFACE "xtensa_wwdt_config"
Python
import simics
class simics.xtensa_wwdt_config_interface_t(has_wwdt=None, reset_val=None,
hb_reset_val=None, ikey=None, bkey=None, rkey=None, kkey=None,
ekey=None, c1key=None, c2key=None, t1key=None, t2key=None)
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.
Name
xtensa_wwdt_faultinfo_t, xtensa_wwdt_faultinfo — interface used with Xtensa WWDT timer
Synopsis
C and DML
#include <simics/arch/xtensa.h> // in C
import "simics/arch/xtensa.dml"; // in DML
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;
SIM_INTERFACE(xtensa_wwdt_faultinfo) {
uint8 (*status)(conf_object_t *obj);
};
#define XTENSA_WWDT_FAULTINFO_INTERFACE "xtensa_wwdt_faultinfo"
Python
import simics
simics.Wwdt_Info_Tfv_Err
simics.Wwdt_Info_Derr_Inj_Dis
simics.Wwdt_Info_Oor_Kick
simics.Wwdt_Info_Err_Inj
simics.Wwdt_Info_Cnt_Exp
simics.Wwdt_Fault_Asserted
simics.Wwdt_Info_Ill_Kick
simics.Wwdt_Info_Oor_Exp
class simics.xtensa_wwdt_faultinfo_interface_t(status=None)
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_faultinfo_t.
Execution Context
Cell Context for all methods.
Model to Simulator Interfaces
Name
abs_pointer_activate — interface used with tablet devices
Synopsis
C and DML
#include <simics/model-iface/abs-pointer.h> // in C
import "simics/model-iface/abs-pointer.dml"; // in DML
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"
Python
import simics
class simics.abs_pointer_activate_interface_t(enable=None, disable=None)
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.
Execution Context
Cell Context for all methods.
Name
abs_pointer_buttons_t, abs_pointer_state_t, abs_pointer — interface and types used with tablet devices
Synopsis
C and DML
#include <simics/model-iface/abs-pointer.h> // in C
import "simics/model-iface/abs-pointer.dml"; // in DML
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"
Python
import simics
simics.Abs_Pointer_Button_Right
simics.Abs_Pointer_Button_Middle
simics.Abs_Pointer_Button_Left
class simics.abs_pointer_state_t(buttons=0, x=0, y=0, z=0)
class simics.abs_pointer_interface_t(set_state=None)
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.
Execution Context
Cell Context for all methods.
Name
arm_external_debug — arm_external_debug interface used for external debug feature
Synopsis
C and DML
#include <simics/arch/arm.h> // in C
import "simics/arch/arm.dml"; // in DML
SIM_INTERFACE(arm_external_debug) {
void (*handle_semihosting)(conf_object_t *obj);
uint64 (*read_reg)(conf_object_t *obj, int offset);
void (*write_reg)(conf_object_t *obj, int offset, uint64 v);
};
#define ARM_EXTERNAL_DEBUG_INTERFACE "arm_external_debug"
Python
import simics
class simics.arm_external_debug_interface_t(handle_semihosting=None,
read_reg=None, write_reg=None)
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.
Name
bank_after_read — Used from callback registered with bank_instrumentation_subscribe interface
Synopsis
C and DML
#include <simics/model-iface/bank-instrumentation.h> // in C
import "simics/model-iface/bank-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.bank_after_read_interface_t(offset=None, size=None, missed=None,
value=None, set_missed=None, set_value=None, initiator=None)
Description
The bank_after_read interface is used to monitor and modify the state of read accesses from the after_read_callback_t callback.
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.
See Also
after_read_callback_t bank_instrumentation_subscribe
Name
bank_after_write — Used from callback registered with bank_instrumentation_subscribe interface
Synopsis
C and DML
#include <simics/model-iface/bank-instrumentation.h> // in C
import "simics/model-iface/bank-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.bank_after_write_interface_t(offset=None, size=None, missed=None,
set_missed=None, initiator=None)
Description
The bank_after_write interface is used to monitor and modify the state of write accesses from the after_write_callback_t callback.
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.
See Also
after_write_callback_t bank_instrumentation_subscribe
Name
bank_before_read — Used from callback registered with bank_instrumentation_subscribe interface
Synopsis
C and DML
#include <simics/model-iface/bank-instrumentation.h> // in C
import "simics/model-iface/bank-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.bank_before_read_interface_t(offset=None, size=None, set_offset=None,
inquire=None, initiator=None)
Description
The bank_before_read interface is used to monitor and modify the state of read accesses from the before_read_callback_t callback.
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.
See Also
before_read_callback_t bank_instrumentation_subscribe
Name
bank_before_write — Used from callback registered with bank_instrumentation_subscribe interface
Synopsis
C and DML
#include <simics/model-iface/bank-instrumentation.h> // in C
import "simics/model-iface/bank-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.bank_before_write_interface_t(offset=None, size=None, value=None,
suppress=None, set_offset=None, set_value=None, initiator=None)
Description
The bank_before_write interface is used to monitor and modify the state of write accesses from the before_write_callback_t callback.
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.
See Also
before_write_callback_t bank_instrumentation_subscribe
Name
bank_instrumentation_subscribe — interface for bank instrumentation
Synopsis
C and DML
#include <simics/model-iface/bank-instrumentation.h> // in C
import "simics/model-iface/bank-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.bank_instrumentation_subscribe_interface_t(register_before_read=None,
register_after_read=None, register_before_write=None,
register_after_write=None, remove_callback=None,
remove_connection_callbacks=None, enable_connection_callbacks=None,
disable_connection_callbacks=None)
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_subscribe 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.
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.
A registered callback is allowed to call remove_callback but not remove_connection_callbacks.
Callback functions registered through the bank_instrumentation_subscribe interface are called before or after read and write accesses, and they are of the types before_read_callback_t, after_read_callback_t, before_write_callback_t and, after_write_callback_t.
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
Global Context for remove_connection_callbacks, Cell Context for other methods.
Name
breakpoint_change — interface that provides callbacks when breakpoints are added or removed
Synopsis
C and DML
#include <simics/device-api.h> // in C
// always available in DML
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"
Python
import simics
class simics.breakpoint_change_interface_t(breakpoint_added=None,
breakpoint_removed=None)
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.
Execution Context
Cell Context for all methods.
Name
breakpoint — interface for adding and removing breakpoints
Synopsis
C and DML
#include <simics/device-api.h> // in C
// always available in DML
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"
Python
import simics
class simics.breakpoint_interface_t(insert_breakpoint=None,
remove_breakpoint=None, get_breakpoint=None)
Description
The breakpoint interface is implemented by any object that supports breaking on an address range.
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.
Name
breakpoint_query_v2 — interface for getting all breakpoints
Synopsis
C and DML
#include <simics/device-api.h> // in C
// always available in DML
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"
Python
import simics
class simics.breakpoint_query_v2_interface_t(get_breakpoints=None)
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 function 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.
Execution Context
Cell Context for all methods.
Name
breakpoint_trigger — interface that allows triggering of breakpoints
Synopsis
C and DML
#include <simics/device-api.h> // in C
// always available in DML
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"
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.
Execution Context
Cell Context for all methods.
Name
callback_info — interface for instrumentation callbacks
Synopsis
C and DML
#include <simics/model-iface/instrumentation-provider.h> // in C
import "simics/model-iface/instrumentation-provider.dml"; // in DML
SIM_INTERFACE(callback_info) {
attr_value_t (*get_callbacks)(conf_object_t *obj);
};
#define CALLBACK_INFO_INTERFACE "callback_info"
Python
import simics
class simics.callback_info_interface_t(get_callbacks=None)
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.
Execution Context
Cell Context for all methods, but must be called from a callback receiving a handle of type instruction_handle_t.
Name
cell_inspection — interface used by processor models to update current cpu
Synopsis
C and DML
#include <simics/model-iface/execute.h> // in C
import "simics/model-iface/execute.dml"; // in DML
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"
Python
import simics
class simics.cell_inspection_interface_t(set_current_processor_obj=None,
set_current_step_obj=None)
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.
Execution Context
Cell Context
Name
co_execute — experimental interface
Synopsis
C and DML
#include <simics/model-iface/co-execute.h> // in C
import "simics/model-iface/co-execute.dml"; // in DML
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"
Python
import simics
class simics.co_execute_interface_t(start_thread=None, yield=None)
Description
Experimental, may change without notice.
Execution Context
Cell Context
Name
component_connector — interface that must be implemented by a connector
Synopsis
C and DML
#include <simics/model-iface/components.h> // in C
import "simics/model-iface/components.dml"; // in DML
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"
Python
import simics
class simics.component_connector_interface_t(get_check_data=None,
get_connect_data=None, check=None, connect=None, disconnect=None)
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.
Execution Context
Global Context for all methods.
Name
component — interface implemented by component classes
Synopsis
C and DML
#include <simics/model-iface/components.h> // in C
import "simics/model-iface/components.dml"; // in DML
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"
Python
import simics
class simics.component_interface_t(pre_instantiate=None, post_instantiate=None,
create_cell=None, get_slots=None, get_slot_objects=None,
get_slot_value=None, set_slot_value=None, has_slot=None,
add_slot=None, del_slot=None)
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.
Execution Context
| Function | Context |
add_slot | Global Context |
create_cell | Global Context |
del_slot | Global Context |
get_objects | Cell Context |
get_slot_value | Global Context |
get_slots | Cell Context |
post_instantiate | Global Context |
pre_instantiate | Global Context |
set_slot_value | Global Context |
Name
concurrency_group — concurrency group interface
Synopsis
C and DML
#include <simics/model-iface/concurrency.h> // in C
import "simics/model-iface/concurrency.dml"; // in DML
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"
Python
import simics
class simics.concurrency_group_interface_t(serialized_memory_group=None,
execution_group=None)
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 Model in the API Reference Manual for more details.
Execution Context
Global Context for all methods.
Name
concurrency_mode — concurrency mode interface
Synopsis
C and DML
#include <simics/model-iface/concurrency.h> // in C
import "simics/model-iface/concurrency.dml"; // in DML
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"
Python
import simics
class simics.concurrency_mode_interface_t(supported_modes=None, current_mode=None,
switch_mode=None)
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 Threading Model chapter in the API Reference Manual for details about thread domains, the Standard Device Model and the Threaded Device Model.
Execution Context
Global Context for all methods.
See Also
concurrency_mode_t
Name
connector_direction_t, connector — interface that must be implemented by a connector
Synopsis
C and DML
#include <simics/model-iface/components.h> // in C
import "simics/model-iface/components.dml"; // in DML
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"
Python
import simics
simics.Sim_Connector_Direction_Up
simics.Sim_Connector_Direction_Down
simics.Sim_Connector_Direction_Any
class simics.connector_interface_t(type=None, hotpluggable=None, required=None,
multi=None, direction=None, add_destination=None,
remove_destination=None, destination=None, update=None, check=None,
connect=None, disconnect=None, deletion_requested=None)
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.
Execution Context
Global Context for all methods.
Name
cpu_cached_instruction — interface for regestering instrumentation for cached instructions
Synopsis
C and DML
#include <simics/model-iface/cpu-instrumentation.h> // in C
import "simics/model-iface/cpu-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.cpu_cached_instruction_interface_t(register_instruction_before_cb=None,
register_instruction_after_cb=None, register_read_before_cb=None,
register_read_after_cb=None, register_write_before_cb=None,
register_write_after_cb=None)
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 method register_instruction_before_cb installs a cpu_instruction_cb_t callback function that is called before the cached instruction is executed. The ci_handle is used to bind the callback to the cached instruction.
The cb callback type is the same as used for instructions in the cpu_instrumentation_subscribe interface.
The user_data is the callback’s user data, and a callback for freeing the data is also available. The free_cb should be of type cpu_callback_free_user_data_cb_t. 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 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 cpu_memory_cb_t callback function 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.
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.
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.
Name
cpu_cached_instruction_once — interface for regestering cached instrumentation callbacks
Synopsis
C and DML
#include <simics/model-iface/cpu-instrumentation.h> // in C
import "simics/model-iface/cpu-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.cpu_cached_instruction_once_interface_t(register_instruction_before_once_cb=None,
register_instruction_after_once_cb=None)
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.
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.
Name
exception_handle_t, cpu_exception_query — query interface for exception information
Synopsis
C and DML
#include <simics/model-iface/cpu-instrumentation.h> // in C
import "simics/model-iface/cpu-instrumentation.dml"; // in DML
typedef struct cpu_exception_info exception_handle_t;
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"
Python
import simics
class simics.exception_handle_t
class simics.cpu_exception_query_interface_t(exception_number=None, fault_pc=None)
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.
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.
Name
decoder_handle_t, cpu_instruction_decoder — interface used with replacing instruction operation
Synopsis
C and DML
#include <simics/model-iface/cpu-instrumentation.h> // in C
import "simics/model-iface/cpu-instrumentation.dml"; // in DML
typedef struct cpu_replace_info decoder_handle_t;
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"
Python
import simics
class simics.decoder_handle_t
class simics.cpu_instruction_decoder_interface_t(register_emulation_cb=None)
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:
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 emulation callback function is of type cpu_emulation_cb_t.
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.
Name
instruction_handle_t, cpu_instruction_query — query interface for instruction information
Synopsis
C and DML
#include <simics/model-iface/cpu-instrumentation.h> // in C
import "simics/model-iface/cpu-instrumentation.dml"; // in DML
typedef struct cpu_instrumentation_info instruction_handle_t;
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);
bool (*is_jit_mode)(conf_object_t *cpu, instruction_handle_t *handle);
};
#define CPU_INSTRUCTION_QUERY_INTERFACE "cpu_instruction_query"
Python
import simics
class simics.instruction_handle_t
class simics.cpu_instruction_query_interface_t(logical_address=None,
physical_address=None, get_instruction_bytes=None,
is_existing_instruction=None, is_jit_mode=None)
Description
The cpu_instruction_query interface can be used in functions of the following types:
where an instruction_handle_t handle 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.
The logical_address and physical_address is used to get the different addresses of the instruction being executed.
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 or 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.
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.
The is_jit_mode method can be used to determine if the instruction is being executed by the JIT engine.
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.
Name
cpu_cb_handle_t, cpu_instrumentation_subscribe — interface used with CPU instrumentation
Synopsis
C and DML
#include <simics/model-iface/cpu-instrumentation.h> // in C
import "simics/model-iface/cpu-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.cpu_instrumentation_subscribe_interface_t(remove_callback=None,
enable_callback=None, disable_callback=None,
remove_connection_callbacks=None, enable_connection_callbacks=None,
disable_connection_callbacks=None,
register_instruction_before_cb=None,
register_instruction_after_cb=None, register_read_before_cb=None,
register_read_after_cb=None, register_write_before_cb=None,
register_write_after_cb=None, register_address_before_cb=None,
register_cached_instruction_cb=None,
register_instruction_decoder_cb=None,
register_exception_before_cb=None, register_exception_after_cb=None,
register_exception_return_before_cb=None,
register_exception_return_after_cb=None,
register_mode_change_cb=None,
register_control_register_read_before_cb=None,
register_control_register_write_before_cb=None)
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, not all CPU models implement all parts of the instrumentation API. Register methods not implemented in this interface will be NULL.
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 cpu_instruction_cb_t.
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.
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 function is of type cpu_memory_cb_t.
The scope argument of type cpu_access_scope_t 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.
When an exception occurs the instruction is aborted and any installed memory callbacks after this point are not called.
Addresses
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 type of cpu_address_cb_t.
The new logical address should be returned by the callback.
Cached Instructions
register_cached_instruction_cb is used for installing a cpu_cached_instruction_cb_t callback that is called every time Simics inserts an 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.
From the cpu_cached_instruction_cb_t callback one can use the supplied ci_handle and the cpu_cached_instruction interface 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 methods 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 cpu_instruction_decoder_cb_t 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.
An implementation of cpu_instruction_disassemble_cb_t should be passed in the disass_cb argument 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.
Exception Related Methods
register_exception_before_cb is used to register a cpu_exception_cb_t callback function 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.
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 cpu_exception_return_cb_t callback function that will be called just before an exception handler is done and resumes execution of the normal program code.
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 cpu_mode_change_cb_t callback function that will be called every time the processor changes mode. The supported modes are: user, supervisor, and hypervisor.
Control Registers
register_control_register_read_before_cb is used to register a cpu_control_register_read_cb_t callback function 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.
register_control_register_write_before_cb is used to register a cpu_control_register_write_cb_t callback function 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.
Execution Context
Global Context for all methods.
Name
memory_handle_t, page_crossing_info_t, cpu_memory_query — query interface for memory access information
Synopsis
C and DML
#include <simics/model-iface/cpu-instrumentation.h> // in C
import "simics/model-iface/cpu-instrumentation.dml"; // in DML
typedef struct cpu_memory_info memory_handle_t;
typedef enum {
Sim_Page_Crossing_None,
Sim_Page_Crossing_First,
Sim_Page_Crossing_Second,
} page_crossing_info_t;
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"
Python
import simics
class simics.memory_handle_t
simics.Sim_Page_Crossing_First
simics.Sim_Page_Crossing_None
simics.Sim_Page_Crossing_Second
class simics.cpu_memory_query_interface_t(logical_address=None,
physical_address=None, get_bytes=None, set_bytes=None, atomic=None,
arch=None, get_page_crossing_info=None, get_surrounding_bytes=None)
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.
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. 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 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.
Name
cycle_control — interface for controlling a cycle counter with events
Synopsis
C and DML
#include <simics/model-iface/cycle-event.h> // in C
import "simics/model-iface/cycle-event.dml"; // in DML
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"
Python
import simics
class simics.cycle_control_interface_t(stop=None, start=None,
set_cycle_count=None)
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.
Execution Context
Cell Context
Name
cycle_event_instrumentation — internal interfaces
Description
This interface is exported for Simics internal use.
Execution Context
Global Context.
Name
cycle_event — -
Synopsis
C and DML
#include <simics/model-iface/cycle-event.h> // in C
import "simics/model-iface/cycle-event.dml"; // in DML
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"
Python
import simics
class simics.cycle_event_interface_t(cycles=None, post=None, cancel=None,
lookup=None, events=None)
Description
TODO: document the cycle_event interface.
Execution Context
Cell Context
Name
cycle — interface used to handle events based on time
Synopsis
C and DML
#include <simics/device-api.h> // in C
// always available in DML
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"
Python
import simics
class simics.cycle_interface_t(get_cycle_count=None, get_time=None,
cycles_delta=None, get_frequency=None, post_cycle=None,
post_time=None, cancel=None, find_next_cycle=None,
find_next_time=None, events=None, get_time_in_ps=None,
cycles_delta_from_ps=None, post_time_in_ps=None,
find_next_time_in_ps=None)
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 cyclecycle_interface_t 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 cyclecycle_interface_t 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.
Execution Context
Cell Context
Name
decoder — interface and type used with user decoder
Synopsis
C and DML
#include <simics/model-iface/decoder.h> // in C
import "simics/model-iface/decoder.dml"; // in DML
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);
};
#define DECODER_INTERFACE "decoder"
Description
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.
Execution Context
Cell Context for all methods.
See Also
service_routine_t,instruction_info_t, decoder_t,
Name
describe_registers — used by the Simics debugger to get register information
Synopsis
C and DML
#include <simics/model-iface/describe-registers.h> // in C
import "simics/model-iface/describe-registers.dml"; // in DML
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"
Python
import simics
simics.Description_Type_Int_Reg
simics.Description_Type_Group
simics.Description_Type_Float_Reg
simics.Description_Type_Float_Field
simics.Description_Type_Fields_Reg
simics.Description_Type_Int_Field
simics.Reg_Role_None
simics.Reg_Role_Program_Counter
simics.Reg_Bitorder_Little_Endian
simics.Reg_Bitorder_Big_Endian
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.
Execution Context
Cell Context for all methods.
Name
device_identification — interface used to provide product information on a device
Synopsis
C and DML
#include <simics/model-iface/device-identification.h> // in C
import "simics/model-iface/device-identification.dml"; // in DML
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"
Python
import simics
class simics.device_identification_interface_t(get_id=None, get_key=None)
Description
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 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.
Execution Context
Cell Context
Name
direct_memory_flush — used to flush granted rights and for managing access rights
Synopsis
C and DML
#include <simics/model-iface/direct-memory.h> // in C
import "simics/model-iface/direct-memory.dml"; // in DML
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"
Python
import simics
class simics.direct_memory_flush_interface_t(revoke=None, set_access_bits=None)
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.
Execution Context
Cell Context for all methods.
Name
direct_memory — implemented to provide direct access to memory
Synopsis
C and DML
#include <simics/device-api.h> // in C
// always available in DML
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;
#include <simics/model-iface/direct-memory.h> // in C
import "simics/model-iface/direct-memory.dml"; // in DML
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"
Python
import simics
class simics.direct_memory_t
class simics.direct_memory_interface_t(get_handle=None, request=None, revoke=None,
release=None, ack=None)
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.
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.
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.
Execution Context
Cell Context for all methods.
Name
direct_memory_lookup, direct_memory_lookup_v2 — lookup direct memory providers in a memory-space
Synopsis
C and DML
#include <simics/device-api.h> // in C
// always available in DML
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;
#include <simics/model-iface/direct-memory.h> // in C
import "simics/model-iface/direct-memory.dml"; // in DML
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"
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"
Python
import simics
class simics.direct_memory_lookup_t
class simics.direct_memory_lookup_interface_t(lookup=None)
class simics.direct_memory_lookup_v2_interface_t(lookup=None)
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.
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.
The direct_memory_lookup and direct_memory interfaces replace the memory_page interface of Simics 4.8.
Execution Context
Cell Context for all methods.
Name
direct_memory_tags — implemented by objects that model RAM with auxiliary RAM bits
Synopsis
C and DML
#include <simics/device-api.h> // in C
// always available in DML
typedef struct {
#ifndef PYWRAP
uint8 *data;
#endif
unsigned len;
} direct_memory_tags_t;
#include <simics/model-iface/direct-memory.h> // in C
import "simics/model-iface/direct-memory.dml"; // in DML
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"
Python
import simics
class simics.direct_memory_tags_t
class simics.direct_memory_tags_interface_t(get_tags_data=None)
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.
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.
Execution Context
Cell Context for all methods.
Name
direct_memory_update — implemented by objects that use the direct_memory interface
Synopsis
C and DML
#include <simics/model-iface/direct-memory.h> // in C
import "simics/model-iface/direct-memory.dml"; // in DML
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"
Python
import simics
class simics.direct_memory_update_interface_t(release=None,
update_permission=None, conflicting_access=None)
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.
Execution Context
Cell Context for all methods.
Name
disk_component — interface that should be implemented by disk components
Synopsis
C and DML
#include <simics/model-iface/components.h> // in C
import "simics/model-iface/components.dml"; // in DML
SIM_INTERFACE(disk_component) {
uint64 (*size)(conf_object_t *obj);
};
#define DISK_COMPONENT_INTERFACE "disk_component"
Python
import simics
class simics.disk_component_interface_t(size=None)
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.
Execution Context
Global Context for all methods.
Name
event_delta — interface implemented by objects that advance time
Synopsis
C and DML
#include <simics/model-iface/event-delta.h> // in C
import "simics/model-iface/event-delta.dml"; // in DML
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"
Python
import simics
class simics.event_delta_interface_t(set_delta=None, get_delta=None)
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
Execution Context
Cell Context
Name
event_handler — interface used to
Synopsis
C and DML
#include <simics/model-iface/event-delta.h> // in C
import "simics/model-iface/event-delta.dml"; // in DML
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"
Python
import simics
class simics.event_handler_interface_t(handle_event=None, stop=None)
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.
Execution Context
Cell Context
Name
event_provider — Internal interface for ISIM modules
Synopsis
C and DML
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"
Description
This is a tech-preview interface that 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.
Execution Context
Called from performance models.
Name
exception — interface used with exception haps
Synopsis
C and DML
#include <simics/model-iface/exception.h> // in C
import "simics/model-iface/exception.dml"; // in DML
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"
Python
import simics
class simics.exception_interface_t(get_number=None, get_name=None,
get_source=None, all_exceptions=None)
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.
Execution Context
Cell Context
Name
execute_control — interface implemented by CPUs and devices that support threading
Synopsis
C and DML
#include <simics/model-iface/execute.h> // in C
import "simics/model-iface/execute.dml"; // in DML
SIM_INTERFACE(execute_control) {
void (*message_pending)(conf_object_t *obj);
void (*yield_request)(conf_object_t *obj);
};
#define EXECUTE_CONTROL_INTERFACE "execute_control"
Python
import simics
class simics.execute_control_interface_t(message_pending=None, yield_request=None)
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.
Execution Context
Threaded Context
Name
execute — interface implemented by objects that can drive simulation
Synopsis
C and DML
#include <simics/model-iface/execute.h> // in C
import "simics/model-iface/execute.dml"; // in DML
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"
Python
import simics
class simics.execute_interface_t(run=None, stop=None, switch_in=None,
switch_out=None)
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.
Execution Context
Cell Context
Name
external_connection_ctl — interface used in external communication
Synopsis
C and DML
#include <simics/model-iface/external-connection.h> // in C
import "simics/model-iface/external-connection.dml"; // in DML
SIM_INTERFACE(external_connection_ctl) {
void (*accept)(conf_object_t *NOTNULL obj,
uint64 id, ext_con_cookie_t *cookie,
bool blocking);
ssize_t (*read)(conf_object_t *NOTNULL obj,
ext_con_cookie_t *NOTNULL cookie,
buffer_t buffer);
ssize_t (*write)(conf_object_t *NOTNULL obj,
ext_con_cookie_t *NOTNULL cookie,
bytes_t bytes);
void (*write_async)(conf_object_t *NOTNULL obj,
ext_con_cookie_t *NOTNULL cookie,
bytes_t bytes);
bool (*has_error)(conf_object_t *NOTNULL obj,
ext_con_cookie_t *NOTNULL cookie);
void (*notify)(conf_object_t *NOTNULL obj,
ext_con_cookie_t *NOTNULL cookie,
notify_mode_t notify_mode, exec_mode_t exec_mode,
bool active);
void (*close)(conf_object_t *NOTNULL obj,
ext_con_cookie_t *NOTNULL cookie);
};
#define EXTERNAL_CONNECTION_CTL_INTERFACE "external_connection_ctl"
Python
import simics
class simics.external_connection_ctl_interface_t(accept=None, read=None,
write=None, write_async=None, has_error=None, notify=None,
close=None)
Description
This interface is implemented by external connection server classes in the external-connection module.
The accept method must be called on every incoming connection, generally in the on_accept method of the external_connection_events, to indicate to the server whether a connection is accepted. The value of id must be the value given to the on_accept method. The value of the cookie argument will be used in all other methods of external_connection_ctl and external_connection_events to identify the connection. Its value is defined by the caller and opaque to the server. Use the value NULL to specify that the connection is not accepted. If the blocking argument is set to true, then the read and write methods will have blocking semantics for this connection.
The read method reads bytes from the connection identified by cookie into the caller-allocated buffer, whose size defines an upper bound on the number of bytes read. The method returns the number of bytes read (which may be less than the size of buffer), or -1 on error. If blocking semantics was turned on for the connection, in the accept method call, then the read method call will block until there is some data to return. Otherwise it will return -2 immediately in that case.
The write method writes bytes to the connection identified by cookie from the buffer bytes. If blocking semantics was turned on for the connection, in the accept method call, then the write method call will block until some data has been written. Otherwise it will return -2 immediately in that case.
The write_async method queues up the data in bytes and sends it as soon as possible on the connection identified by cookie. The method makes a copy of the data and returns immediately.
The has_error method returns true if and only if there has been an error on the connection identified by cookie.
The notify method activates or deactivates read or write notifications on the connection identified by cookie. The active argument specifies if the call is an activation or a deactivation and the notify_mode argument specifies if read (Sim_NM_Read) or write (Sim_NM_Write) notifications should be affected. Activating read notifications means that the on_input method in the external_connection_events interface may be called on this connection at any time after the call to notify. Activating write notifications means that the can_write method in the external_connection_events interface may be called on this connection at any time after the call to notify. If exec_mode is set to Sim_EM_Global, the call to on_input or can_write will be done in GLobal Context and if exec_mode is set to Sim_EM_Thread, the call will be in done in Threaded Context.
The close method closes the connection identified by cookie. After this call, it is is illegal to call any other method using this value of cookie.
Execution Context
Global Context for accept and notify, Threaded Context for other methods.
Name
external_connection_events — interface used in communication with external communication servers
Synopsis
C and DML
#include <simics/model-iface/external-connection.h> // in C
import "simics/model-iface/external-connection.dml"; // in DML
SIM_INTERFACE(external_connection_events) {
void (*on_accept)(conf_object_t *NOTNULL obj,
conf_object_t *NOTNULL server, uint64 id);
void (*on_input)(conf_object_t *NOTNULL obj,
ext_con_cookie_t *NOTNULL cookie);
void (*can_write)(conf_object_t *NOTNULL obj,
ext_con_cookie_t *NOTNULL cookie);
};
#define EXTERNAL_CONNECTION_EVENTS_INTERFACE "external_connection_events"
Python
import simics
class simics.external_connection_events_interface_t(on_accept=None, on_input=None,
can_write=None)
Description
This interface must be implemented by objects communicating with external connection servers.
The on_accept method is called on every incoming connection, when it is being set up. The server argument is the server object that is handling the connection. The id value identifies this connection in the server object. This value must be passed in the call to accept in the external_connection_ctl interface.
The on_input method is called on the connection identified by cookie when there is some data available to read on it.
The can_write method is called on the connection identified by cookie when some data can be written to it.
Execution Context
Global Context for on_accept, Threaded or Global Context for the others, depending on how notify was called.
Name
freerun — interface used to extend cpu model with freerunning capability
Synopsis
C and DML
#include <simics/model-iface/freerun.h> // in C
import "simics/model-iface/freerun.dml"; // in DML
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"
Python
import simics
class simics.freerun_interface_t(enabled=None, advance_clock=None,
start_clock=None, stop_clock=None, current_itime=None)
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.
The freerun interface is experimental and may change without notice.
Execution Context
Cell Context for all methods.
Name
gfx_con_pixel_fmt_t, gfx_con — interface used in communication with graphic consoles
Synopsis
C and DML
#include <simics/model-iface/gfx-console.h> // in C
import "simics/model-iface/gfx-console.dml"; // in DML
typedef enum {
GFX_8BIT_INDEXED = 8, /* 0xII */
GFX_RGB_565 = 16, /* 0bRRRRRGGGGGGBBBBB */
GFX_RGB_888 = 24, /* 0xRRGGBB */
GFX_xRGB_8888 = 32, /* 0xXXRRGGBB (X=unused) */
} gfx_con_pixel_fmt_t;
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"
Python
import simics
simics.GFX_RGB_565
simics.GFX_RGB_888
simics.GFX_8BIT_INDEXED
simics.GFX_xRGB_8888
class simics.gfx_con_interface_t(set_color=None, set_size=None, put_pixel=None,
put_pixel_rgb=None, redraw=None, update_keyboard_leds=None,
put_pixel_col=None, put_block=None)
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_pixel method 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>.
The gfx_con_pixel_fmt_t enumeration is used when calling the put_block method, to specify the pixel format of the provided buffer.
Specifying GFX_8BIT_INDEXED means that the buffer uses VGA style 8-bit per pixel indexed colors, and that the console palette, specified by the set_color method, should be used.
Specifying GFX_RGB_565 means that the buffer uses 16 bits per pixel, with format 0bRRRRRGGGGGGBBBBB (in little endian).
Specifying GFX_RGB_888 means that the buffer uses 24 bits per pixel, with format 0xRRGGBB (in little endian).
Specifying GFX_xRGB_8888 means that the buffer uses 32 bits per pixel, with format 0xXXRRGGBB (in little endian), where X is unused.
Execution Context
Cell Context
Name
hap_listen — interface used to be notified abd haps
Synopsis
C and DML
#include <simics/model-iface/hap-listen.h> // in C
// not available in DML
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"
Description
With the hap_listen interface, objects can pick up haps and process then as they wish, including re-raising the haps.
Execution Context
Cell Context
Name
image — interface used for handling big data images
Synopsis
C and DML
#include <simics/model-iface/image.h> // in C
import "simics/model-iface/image.dml"; // in DML
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"
Python
import simics
class simics.image_interface_t(set_persistent=None, save_to_file=None,
save_diff=None, clear_range=None, fill=None, size=None, set=None,
get=None, flush_writable=None)
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.
Execution Context
Cell Context
Name
image_snoop — interface used to snoop om changes to pages within an image
Synopsis
C and DML
#include <simics/model-iface/image.h> // in C
import "simics/model-iface/image.dml"; // in DML
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"
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.
Execution Context
Cell Context
Name
instruction_fetch_mode_t, instruction_fetch — interface to control how instruction fetches should be modelled
Synopsis
C and DML
#include <simics/model-iface/instruction-fetch.h> // in C
import "simics/model-iface/instruction-fetch.dml"; // in DML
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"
Python
import simics
simics.Instruction_Fetch_Trace
simics.Instruction_Fetch_Cache_Access_Trace
simics.Instruction_Fetch_None
class simics.instruction_fetch_interface_t(get_mode=None, set_mode=None,
get_line_size=None, set_line_size=None)
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.
Execution Context
- Global Context
set_mode
set_line_size Cell Context
get_mode
get_line_size
Name
instrumentation_order — interface for instrumentation order
Synopsis
C and DML
#include <simics/model-iface/instrumentation-provider.h> // in C
import "simics/model-iface/instrumentation-provider.dml"; // in DML
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"
Python
import simics
class simics.instrumentation_order_interface_t(get_connections=None,
move_before=None)
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:
- all anonymous connections, i.e. NULL connections, in registration order
- connection order, which if not re-ordered will be the connection registration order
- 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.
Execution Context
Global Context for all methods, but must be called from a callback receiving a handle of type instruction_handle_t.
Name
keyboard_console — interface implemented by consoles
Synopsis
C and DML
#include <simics/model-iface/kbd-interface.h> // in C
import "simics/model-iface/kbd-interface.dml"; // in DML
SIM_INTERFACE(keyboard_console) {
void (*keyboard_ready)(conf_object_t *obj);
};
#define KEYBOARD_CONSOLE_INTERFACE "keyboard_console"
Python
import simics
class simics.keyboard_console_interface_t(keyboard_ready=None)
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.
Execution Context
Cell Context for all methods.
Name
keyboard — interface implemented by keyboard controllers
Synopsis
C and DML
#include <simics/model-iface/kbd-interface.h> // in C
import "simics/model-iface/kbd-interface.dml"; // in DML
SIM_INTERFACE(keyboard) {
int (*keyboard_event)(conf_object_t *obj, int key_up, uint8 key);
};
#define KEYBOARD_INTERFACE "keyboard"
Python
import simics
class simics.keyboard_interface_t(keyboard_event=None)
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.
Execution Context
Cell Context for all methods.
Name
linear_image — experimental image access interface
Synopsis
C and DML
#include <simics/model-iface/image.h> // in C
import "simics/model-iface/image.dml"; // in DML
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"
Python
import simics
class simics.linear_image_interface_t(prepare_range=None)
Description
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.
Execution Context
- Global Context
set_base
get_base Cell Context
prepare_range
Name
magic_pipe_reader — Interface for reading data from magic pipe
Synopsis
C and DML
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"
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.
This interface is an experimental feature. It is excluded from the standard support program, and is subject to change or removal without notice.
Execution Context
Cell Context for all methods.
Name
magic_pipe_setup — Interface for magic pipe setup
Synopsis
C and DML
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"
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.
This interface is an experimental feature. It is excluded from the standard support program, and is subject to change or removal without notice.
Execution Context
Cell Context for all methods.
Name
magic_pipe_writer — Interface magic pipe transmission
Synopsis
C and DML
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"
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.
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.
This interface is an experimental feature. It is excluded from the standard support program, and is subject to change or removal without notice.
Execution Context
Cell Context for all methods.
Name
memory_profiler — interface for processors supporting memory profiling
Synopsis
C and DML
#include <simics/model-iface/memory-profiler.h> // in C
import "simics/model-iface/memory-profiler.dml"; // in DML
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"
Python
import simics
class simics.memory_profiler_interface_t(get=None, set=None,
get_granularity_log2=None)
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.
Execution Context
Cell Context for all methods.
Name
mmc — interface implemented by MMC/SD/SDHC/SDIO card models
Synopsis
C and DML
#include <simics/model-iface/mmc.h> // in C
import "simics/model-iface/mmc.dml"; // in DML
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);
};
#define MMC_INTERFACE "mmc"
Python
import simics
class simics.mmc_interface_t(write_data=None)
Description
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.
Name
mouse — interface used to send mouse events to a mouse device
Synopsis
C and DML
#include <simics/model-iface/kbd-interface.h> // in C
import "simics/model-iface/kbd-interface.dml"; // in DML
SIM_INTERFACE(mouse) {
void (*mouse_event)(conf_object_t *obj,
int xmicro,
int ymicro,
int z,
int buttons);
};
#define MOUSE_INTERFACE "mouse"
Python
import simics
class simics.mouse_interface_t(mouse_event=None)
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>.
Execution Context
Cell Context for all methods.
Name
opcode_length_info_t, opcode_info — interface implemented by processors
Synopsis
C and DML
#include <simics/model-iface/processor-info.h> // in C
import "simics/model-iface/processor-info.dml"; // in DML
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"
Python
import simics
class simics.opcode_length_info_t(min_alignment=0, max_length=0, avg_length=0)
class simics.opcode_info_interface_t(get_opcode_length_info=None)
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.
Execution Context
Cell Context for all methods.
Name
pipe_func_t — Function prototype used in magic_pipe_setup
Synopsis
C and DML
typedef void (*pipe_func_t)(conf_object_t *cpu, uintptr_t buf, uint64 magic);
Arguments
- cpu
- the active cpu core of the event.
- buf
- the buffer data handle.
- magic
- the magic number of the buffer.
The buffer handle is used in most calls to this interface to identify the buffer.
Name
pre_decoder — interface for changing bytes going into instruction decode
Synopsis
C and DML
#include <simics/model-iface/cpu-instrumentation.h> // in C
import "simics/model-iface/cpu-instrumentation.dml"; // in DML
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);
};
#define PRE_DECODER_INTERFACE "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.
Execution Context
Global context.
Name
processor_cli — command feature interface for processor models
Synopsis
C and DML
#include <simics/model-iface/processor-info.h> // in C
import "simics/model-iface/processor-info.dml"; // in DML
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"
Python
import simics
class simics.processor_cli_interface_t(get_disassembly=None, get_pregs=None,
get_diff_regs=None, get_pending_exception_string=None,
get_address_prefix=None, translate_to_physical=None)
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_v2 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 step-instruction 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_v2 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_v2 interface will be used to translate virtual addresses.
Execution Context
Cell Context for all methods.
Name
processor_endian — interface used for retrieving processor endianness
Synopsis
C and DML
#include <simics/model-iface/processor-info.h> // in C
import "simics/model-iface/processor-info.dml"; // in DML
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"
Python
import simics
class simics.processor_endian_interface_t(get_instruction_endian=None,
get_data_endian=None)
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 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.
Execution Context
Cell Context
Name
processor_gui — processor interface used with Simics native GUI
Synopsis
C and DML
#include <simics/model-iface/processor-info.h> // in C
import "simics/model-iface/processor-info.dml"; // in DML
SIM_INTERFACE(processor_gui) {
void (*dummy)(conf_object_t *obj);
};
#define PROCESSOR_GUI_INTERFACE "processor_gui"
Python
import simics
class simics.processor_gui_interface_t(dummy=None)
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.
Name
processor_info — older version of the processor_info_v2 interface
Synopsis
C and DML
#include <simics/model-iface/processor-info.h> // in C
import "simics/model-iface/processor-info.dml"; // in DML
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"
Python
import simics
class simics.processor_info_interface_t(disassemble=None,
set_program_counter=None, get_program_counter=None,
logical_to_physical=None, enable_processor=None,
disable_processor=None, get_enabled=None, get_endian=None,
get_physical_memory=None, get_logical_address_width=None,
get_physical_address_width=None, architecture=None)
Description
An older version of the processor_info_v2 interface. See processor_info_v2 for more information.
Execution Context
Cell Context for all methods.
Name
processor_info_v2 — interface with generic functions implemented by processor models
Synopsis
C and DML
#include <simics/model-iface/processor-info.h> // in C
import "simics/model-iface/processor-info.dml"; // in DML
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"
Python
import simics
class simics.processor_info_v2_interface_t(disassemble=None,
set_program_counter=None, get_program_counter=None,
logical_to_physical=None, get_processor_mode=None,
enable_processor=None, disable_processor=None, get_enabled=None,
get_endian=None, get_physical_memory=None,
get_logical_address_width=None, get_physical_address_width=None,
architecture=None)
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 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.
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
Cell Context for all methods except set_program_counter which needs Global Context.
It is explicitly permitted to call set_program_counter from inside an execution breakpoint handler.
Name
processor_memory_inspection — implemented by processor models for memory inspection
Synopsis
C and DML
#include <simics/model-iface/processor-info.h> // in C
import "simics/model-iface/processor-info.dml"; // in DML
SIM_INTERFACE(processor_memory_inspection) {
conf_object_t *(*logical_inspection_port)(conf_object_t *obj);
conf_object_t *(*physical_inspection_port)(conf_object_t *obj);
};
#define PROCESSOR_MEMORY_INSPECTION_INTERFACE "processor_memory_inspection"
Python
import simics
class simics.processor_memory_inspection_interface_t(logical_inspection_port=None,
physical_inspection_port=None)
Description
The processor_memory_inspection interface is implemented by processor models for memory inspection.
Function logical_inspection_port returns a port that can be used to issue transactions from the point of view of the processor. The user is expected to use a logical/virtual address when accessing this port. The processors architectural atoms are appended to the transaction. An internal MMU lookup is performed to translate the logical/virtual address to a physical address. The transaction is then forwarded to the physical_memory attached to the processor. This will give the same access rights to the memory hierarchy as if the processor itself had issued the transaction. This function can return NULL if the processor does not support logical/virtual memory addressing.
Function physical_inspection_port returns a port that can be used to issue transactions from the point of view of the processor. The user is expected to use a physical address when accessing this port. The processors architectural atoms are appended to the transaction when using this port, before the transaction is forwarded to the physical_memory attached to the processor. This will give the same access rights to the memory hierarchy as if the processor itself had issued the transaction.
Execution Context
Cell Context for all methods.
Name
ram_cb_handle_t, ram_access_subscribe — interface for ram access instrumentation
Synopsis
C and DML
#include <simics/model-iface/ram-instrumentation.h> // in C
import "simics/model-iface/ram-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.ram_cb_handle_t
class simics.ram_access_subscribe_interface_t(remove_callback=None,
enable_callback=None, disable_callback=None,
register_access_before_cb=None, register_access_after_cb=None,
register_access_filter_cb=None)
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.
Execution Context
Global Context for all methods.
Name
register_breakpoint — optional CPU interface
Synopsis
C and DML
#include <simics/simulator-iface/register-breakpoint.h> // in C
import "simics/simulator-iface/register-breakpoint.dml"; // in DML
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"
Python
import simics
class simics.register_breakpoint_interface_t(add_breakpoint=None,
remove_breakpoint=None, get_breakpoints=None)
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.
Execution Context
Global Context
Name
simple_timing_v2 — Interface that provides execution information
Synopsis
C and DML
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"
Description
This interface is a tech preview and 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.
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 to the modules Makefile:
EXTRA_MODULE_VPATH := simple-timing-interface
Execution Context
Called from performance models.
Name
simulator_cache — interface optionally implemented by processor models
Synopsis
C and DML
#include <simics/model-iface/simulator-cache.h> // in C
import "simics/model-iface/simulator-cache.dml"; // in DML
SIM_INTERFACE(simulator_cache) {
void (*flush)(conf_object_t *obj);
};
#define SIMULATOR_CACHE_INTERFACE "simulator_cache"
Python
import simics
class simics.simulator_cache_interface_t(flush=None)
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.
Execution Context
Cell Context
Name
stall — optionally implemented by objects together with cycle and step interfaces
Synopsis
C and DML
#include <simics/model-iface/step.h> // in C
import "simics/model-iface/step.dml"; // in DML
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"
Python
import simics
class simics.stall_interface_t(get_stall_cycles=None, set_stall_cycles=None,
get_total_stall_cycles=None)
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.
Execution Context
Cell Context for all methods.
Name
step_cycle_ratio_t, step_cycle_ratio — implemented by objects with changeable ratio between steps and cycles
Synopsis
C and DML
#include <simics/model-iface/step.h> // in C
import "simics/model-iface/step.dml"; // in DML
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"
Python
import simics
class simics.step_cycle_ratio_t
class simics.step_cycle_ratio_interface_t(get_ratio=None, set_ratio=None)
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.
Execution Context
Cell Context for all methods.
Name
step_event_instrumentation — internal interfaces
Description
This interface is exported for Simics internal use.
Execution Context
Global Context.
Name
step_info — optional interface implemented by processors
Synopsis
C and DML
#include <simics/model-iface/step.h> // in C
import "simics/model-iface/step.dml"; // in DML
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"
Python
import simics
class simics.step_info_interface_t(get_halt_steps=None, set_halt_steps=None,
get_ffwd_steps=None, set_ffwd_steps=None, get_ma_steps=None,
set_ma_steps=None)
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.
Execution Context
Cell Context for all methods.
Name
step — interface used to handle step events
Synopsis
C and DML
#include <simics/model-iface/step.h> // in C
import "simics/model-iface/step.dml"; // in DML
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"
Python
import simics
class simics.step_interface_t(get_step_count=None, post_step=None,
cancel_step=None, find_next_step=None, events=None, advance=None)
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.
Execution Context
Cell Context for all methods.
Name
synchronous_mode — experimental interface
Synopsis
C and DML
#include <simics/model-iface/co-execute.h> // in C
import "simics/model-iface/co-execute.dml"; // in DML
SIM_INTERFACE(synchronous_mode) {
int (*enter)(conf_object_t *NOTNULL obj);
int (*leave)(conf_object_t *NOTNULL obj);
};
#define SYNCHRONOUS_MODE_INTERFACE "synchronous_mode"
Python
import simics
class simics.synchronous_mode_interface_t(enter=None, leave=None)
Description
Experimental, may change without notice.
Execution Context
Cell Context
Name
temporal_state — interface related to reverse execution
Synopsis
C and DML
#include <simics/model-iface/temporal-state.h> // in C
import "simics/model-iface/temporal-state.dml"; // in DML
// only supported with SIMICS_API = 6
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"
Python
import simics
class simics.temporal_state_interface_t(save=None, merge=None,
prepare_restore=None, finish_restore=None)
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.
Execution Context
Cell Context for all methods.
Name
timing_model, snoop_memory — interfaces for stalling and snooping on memory accesses
Synopsis
C and DML
#include <simics/model-iface/timing-model.h> // in C
import "simics/model-iface/timing-model.dml"; // in DML
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"
Python
import simics
class simics.timing_model_interface_t(operate=None)
class simics.snoop_memory_interface_t(operate=None)
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.
Execution Context
Cell Context for all methods.
Name
transaction — interface used to pass transactions
Synopsis
C and DML
#include <simics/model-iface/transaction.h> // in C
import "simics/model-iface/transaction.dml"; // in DML
SIM_INTERFACE(transaction) {
exception_type_t (*issue)(
conf_object_t *NOTNULL obj,
transaction_t *NOTNULL t,
uint64 addr);
};
#define TRANSACTION_INTERFACE "transaction"
Python
import simics
class simics.transaction_interface_t(issue=None)
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.
Execution Context
Cell Context for all methods.
Name
transaction_cb_handle_t, transaction_subscribe — internal transaction instrumentation interface
Synopsis
C and DML
#include <simics/model-iface/transaction-instrumentation.h> // in C
import "simics/model-iface/transaction-instrumentation.dml"; // in DML
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"
Python
import simics
class simics.transaction_cb_handle_t
class simics.transaction_subscribe_interface_t(remove_callback=None,
enable_callback=None, disable_callback=None, register_issue_cb=None)
Description
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.
Execution Context
Outside execution context for all methods.
Name
tsc_update — Interface that allows changing Time Stamp Counter
Synopsis
C and DML
SIM_INTERFACE(tsc_update) {
void (*load_tsc_from_xtal)(conf_object_t *obj, uint64 xtal_value);
};
#define TSC_UPDATE_INTERFACE "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.
Execution Context
Cell Context for all methods.
Name
vga_text_info — interface used with vga text
Synopsis
C and DML
#include <simics/model-iface/vga-text-interface.h> // in C
import "simics/model-iface/vga-text-interface.dml"; // in DML
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"
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.
Execution Context
Cell Context
Name
vga_text_update — interface used with vga text
Synopsis
C and DML
#include <simics/model-iface/vga-text-interface.h> // in C
import "simics/model-iface/vga-text-interface.dml"; // in DML
SIM_INTERFACE(vga_text_update) {
void (*write)(conf_object_t *NOTNULL obj, char value);
};
#define VGA_TEXT_UPDATE_INTERFACE "vga_text_update"
Python
import simics
class simics.vga_text_update_interface_t(write=None)
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.
Execution Context
Cell Context
Name
vga_update — interface used with graphic consoles
Synopsis
C and DML
#include <simics/model-iface/gfx-console.h> // in C
import "simics/model-iface/gfx-console.dml"; // in DML
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"
Python
import simics
class simics.vga_update_interface_t(refresh=None, refresh_all=None)
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.
Execution Context
Cell Context
Name
virtual_breakpoint_flags_t, virtual_breakpoint_access_t, virtual_data_breakpoint — interface for data access breakpoints on virtual addresses
Synopsis
C and DML
#include <simics/device-api.h> // in C
// always available in DML
typedef enum {
Virtual_Breakpoint_Flag_Linear = 1
} virtual_breakpoint_flags_t;
typedef enum {
Virtual_Breakpoint_Access_Read = 1,
Virtual_Breakpoint_Access_Write = 2,
Virtual_Breakpoint_Access_Execute = 4
} virtual_breakpoint_access_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);
attr_value_t (*list)(conf_object_t *NOTNULL obj);
};
#define VIRTUAL_DATA_BREAKPOINT_INTERFACE "virtual_data_breakpoint"
Python
import simics
simics.Virtual_Breakpoint_Flag_Linear
simics.Virtual_Breakpoint_Access_Read
simics.Virtual_Breakpoint_Access_Execute
simics.Virtual_Breakpoint_Access_Write
class simics.virtual_data_breakpoint_interface_t(add_read=None, add_write=None,
remove=None, list=None)
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.)
The list method returns the data breakpoints that are set on the object right now. The returned value is a list with one entry per breakpoint, and each entry is a list of [key, value] pairs where the key is a string:
id - the handle that add_read or add_write returned, as a number.
object - the object the breakpoint is set on.
access - a virtual_breakpoint_access_t value, Virtual_Breakpoint_Access_Read or Virtual_Breakpoint_Access_Write.
first, last - the interval, both endpoints included.
linear_address - true when the breakpoint uses linear rather than virtual addresses.
callback - the callback function pointer as a number. Every breakpoint set from Python shares the same wrapper function, so this only tells breakpoints apart when they were set from C.
The id is unique while the breakpoint lives, but it is reused once the breakpoint is removed, and it is not the same between runs. A breakpoint set entirely above the largest representable address is never stored, so it is not listed.
The list method is optional and may be NULL. It was added in build-id 7204, and a module built against an older header registers an interface struct that has no list member at all. So before reading list, check that the build_id attribute of the object is 7204 or later, and then that list is not NULL.
This interface is preliminary and may change without prior notice.
Execution Context
Cell Context for all methods.
Name
virtual_instruction_breakpoint — interface for instruction breakpoints on virtual addresses
Synopsis
C and DML
#include <simics/device-api.h> // in C
// always available in DML
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);
attr_value_t (*list)(conf_object_t *NOTNULL obj);
};
#define VIRTUAL_INSTRUCTION_BREAKPOINT_INTERFACE \
"virtual_instruction_breakpoint"
Python
import simics
class simics.virtual_instruction_breakpoint_interface_t(add=None, remove=None,
list=None)
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.
The list method returns the instruction breakpoints that are set on the object right now, in the same format as the list method of virtual_data_breakpoint. Here id is the handle that add returned, access is always Virtual_Breakpoint_Access_Execute, and there is one more key:
filter - the filter function pointer as a number, 0 when there is no filter.
The same rules apply as for virtual_data_breakpoint: list is optional and may be NULL, and it only exists in modules with build-id 7204 or later, so check the build_id attribute of the object before reading list.
This interface is preliminary and may change without prior notice.
Execution Context
Cell Context for all methods.
Simulator to Simulator Interfaces
Name
address_profiler — interface used to get statistics out of profilers
Synopsis
C and DML
#include <simics/simulator-iface/address-profiler.h> // in C
import "simics/simulator-iface/address-profiler.dml"; // in DML
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"
Python
import simics
class simics.address_profiler_interface_t(iter=None, sum=None, max=None,
granularity_log2=None, address_bits=None, physical_addresses=None,
description=None, num_views=None)
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.
Execution Context
Cell Context for all methods.
Name
branch_arc_t, branch_arc_iter_t, branch_recorder_direction_t, branch_arc — interface for getting branch arcs out profilers
Synopsis
C and DML
#include <simics/simulator-api.h> // in C
import "simics/simulator-api.dml"; // in DML
typedef struct {
uint64 addr_from;
uint64 addr_to;
int64 count;
branch_arc_type_t type;
} branch_arc_t;
typedef struct branch_arc_iter {
branch_arc_t *(*next)(struct branch_arc_iter *i);
void (*destroy)(struct branch_arc_iter *i);
} branch_arc_iter_t;
typedef enum {
BR_Direction_From,
BR_Direction_To
} branch_recorder_direction_t;
#include <simics/simulator-iface/address-profiler.h> // in C
import "simics/simulator-iface/address-profiler.dml"; // in DML
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"
Python
import simics
class simics.branch_arc_t
class simics.branch_arc_iter_t
simics.BR_Direction_From
simics.BR_Direction_To
class simics.branch_arc_interface_t(iter=None)
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
Execution Context
Cell Context for all methods.
See Also
branch_arc_type_t, branch_recorder_direction_t
Name
break_string_cb_t, break_strings_v2 — interface used with console breakpoints
Synopsis
C and DML
#include <simics/simulator-iface/consoles.h> // in C
import "simics/simulator-iface/consoles.dml"; // in DML
typedef int (*break_string_cb_t)(conf_object_t *obj,
const char *str, int64 break_id,
lang_void *arg);
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);
attr_value_t (*get_state)(conf_object_t *NOTNULL obj, int64 bp_id);
char *(*set_state)(conf_object_t *NOTNULL obj, int64 bp_id, attr_value_t data);
};
#define BREAK_STRINGS_V2_INTERFACE "break_strings_v2"
Python
import simics
class simics.break_strings_v2_interface_t(add=None, add_single=None,
add_regexp=None, remove=None, get_state=None, set_state=None)
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.
The remove method deactivates a previously activated breakpoint.
The get_state and set_state functions can be used to serialize and deserialize string matchers: For instance, consider a breakpoint on the string ABC, where the characters A and B have already been matched. If you call get_state to retrieve the current state, then you can later call set_state with this state on any active breakpoint that waits for ABC, which will put that breakpoint in a state where its callback is triggered by the character C.
The get_state function returns an attribute value of data kind. It is only allowed to call set_state with a value returned by get_state, for a breakpoint waiting for the same string or regexp. The set_state function returns NULL on success, and an error message if the state cannot be restored. The caller is responsible for deallocating the error message using MM_FREE.
The methods get_state and set_state were both added in version 6.0.250 of the Simics Base package; any code that uses it will break if used with older base packages.
The break_string_cb_t callback function type is used by the string breakpoint system, called when the associated string breakpoint has matched. The obj parameter is the console where the breakpoint matched, str is the break string that matched, break_id is the associated breakpoint id, returned by the add or add_single method in the interface, and arg is the callback data passed to that method. The return value is ignored.
Execution Context
Global Context
Name
breakpoint_manager — internal interface used by the breakpoint manager
Synopsis
C and DML
#include <simics/simulator-iface/breakpoint-manager.h> // in C
import "simics/simulator-iface/breakpoint-manager.dml"; // in DML
SIM_INTERFACE(breakpoint_manager) {
/* Return a list of the breakpoint ids of all breakpoints. */
attr_value_t (*list_breakpoints)(conf_object_t *NOTNULL mgr);
void (*delete_breakpoint)(conf_object_t *NOTNULL mgr, uint64 id);
/* Return a dictionary with the properties for a specific breakpoint */
attr_value_t (*get_properties)(conf_object_t *NOTNULL mgr, uint64 id);
bool (*set_enabled)(conf_object_t *NOTNULL mgr,
uint64 id, bool enabled);
bool (*set_temporary)(conf_object_t *NOTNULL mgr, uint64 id,
bool temporary);
bool (*set_ignore_count)(conf_object_t *NOTNULL mgr, uint64 id,
uint64 ignore_count);
};
#define BREAKPOINT_MANAGER_INTERFACE "breakpoint_manager"
Python
import simics
class simics.breakpoint_manager_interface_t(list_breakpoints=None,
delete_breakpoint=None, get_properties=None, set_enabled=None,
set_temporary=None, set_ignore_count=None)
Description
An internal interface used by the breakpoint manager. Can be changed at any time.
Execution Context
Internal.
Name
breakpoint_type — interface that allows implementing a custom breakpoint type
Synopsis
C and DML
#include <simics/simulator-iface/breakpoint-manager.h> // in C
import "simics/simulator-iface/breakpoint-manager.dml"; // in DML
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"
Python
import simics
class simics.breakpoint_type_interface_t(register_type=None, trigger=None,
get_break_id=None, get_manager_id=None)
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 commands break, run-until, wait-for and trace 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} and bp-trace-{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.
Execution Context
Global Context
Name
breakpoint_type_provider — interface implemented by breakpoint providers
Synopsis
C and DML
#include <simics/simulator-iface/breakpoint-manager.h> // in C
import "simics/simulator-iface/breakpoint-manager.dml"; // in DML
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"
Python
import simics
class simics.breakpoint_type_provider_interface_t(register_bp=None, add_bp=None,
remove_bp=None, trace_msg=None, break_msg=None, wait_msg=None,
break_data=None, values=None, trace=None)
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.
Execution Context
Global Context
Name
checkpoint — interface used with checkpointing
Synopsis
C and DML
#include <simics/simulator-iface/checkpoint.h> // in C
import "simics/simulator-iface/checkpoint.dml"; // in DML
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"
Python
import simics
class simics.checkpoint_interface_t(save=None, finish=None,
has_persistent_data=None, save_v2=None)
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.
Execution Context
Global Context for all methods.
Name
con_input_code — interface for sending key events to target through a console
Synopsis
C and DML
#include <simics/simulator-iface/consoles.h> // in C
import "simics/simulator-iface/consoles.dml"; // in DML
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"
Python
import simics
class simics.con_input_code_interface_t(input=None)
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.
Execution Context
Global Context
Name
con_input — interface for sending data to target through a console
Synopsis
C and DML
#include <simics/simulator-iface/consoles.h> // in C
import "simics/simulator-iface/consoles.dml"; // in DML
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"
Python
import simics
class simics.con_input_interface_t(input_str=None, input_data=None)
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.
Execution Context
Global Context
Name
context_handler — interface for working with contexts
Synopsis
C and DML
#include <simics/processor-api.h> // in C
import "simics/processor-api.dml"; // in DML
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"
Python
import simics
class simics.context_handler_interface_t(get_current_context=None,
set_current_context=None)
Description
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.
Execution Context
Cell Context for all methods.
Name
debug_notification — get notifications for debugger events
Synopsis
C and DML
#include <simics/simulator-iface/debugger.h> // in C
import "simics/simulator-iface/debugger.dml"; // in DML
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"
Python
import simics
class simics.debug_notification_interface_t(notify_context_creation=None,
notify_context_destruction=None, notify_location=None,
notify_address=None, notify_line=None, notify_activated=None,
notify_deactivated=None, notify_callbacks_done=None, cancel=None)
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. 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.
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.
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.
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.
Execution Context
Global Context for all methods.
Name
debug_query — query the debugger for debug contexts
Synopsis
C and DML
#include <simics/simulator-iface/debugger.h> // in C
import "simics/simulator-iface/debugger.dml"; // in DML
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;
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"
Python
import simics
simics.Debugger_Unknown_Id
simics.Debugger_Section_Info_Missing
simics.Debugger_Section_Not_Found
simics.Debugger_Invalid_Path
simics.Debugger_Already_Running
simics.Debugger_Context_Does_Not_Have_State
simics.Debugger_Incorrect_Context_Query
simics.Debugger_Failed_To_Continue
simics.Debugger_Not_Supported_For_Context
simics.Debugger_Segment_Not_Found
simics.Debugger_Unsupported_For_File_Format
simics.Debugger_Not_Allowed_In_Execution_Context
simics.Debugger_Incorrect_Type
simics.Debugger_Missing_Object
simics.Debugger_Unexpected_Error
simics.Debugger_Incorrect_Size
simics.Debugger_Unrecognized_File_Format
simics.Debugger_Unknown_Context
simics.Debugger_Failed_To_Evaluate_Expression
simics.Debugger_Source_Not_Found
simics.Debugger_Failed_To_Read
simics.Debugger_Frame_Outside_Of_Known_Stack
simics.Debugger_Not_Relocatable
simics.Debugger_No_Context_For_Object
simics.Debugger_Failed_To_Open_File
simics.Debugger_Failed_To_Get_PC
simics.Debugger_Lookup_Failure
simics.Debugger_Failed_To_Get_Stack_Frame
simics.Debugger_File_Not_Found
simics.Debugger_Context_Is_Not_Active
simics.Debugger_No_Error
simics.Debugger_Step_Interrupted
simics.Debugger_Segment_Info_Missing
simics.Debugger_Failed_To_Write
class simics.debug_query_interface_t(matching_contexts=None,
get_context_group=None, get_context_parent=None,
get_context_children=None, query_for_context_group=None,
query_for_context_id=None, query_for_context_tree=None,
context_name=None, context_id_for_object=None,
object_for_context=None, context_has_state=None,
get_active_processor=None)
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 or processor objects.
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.
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.
Execution Context
Global Context for all methods.
Name
debug_setup — configure the debugger with symbol files and paths
Synopsis
C and DML
#include <simics/simulator-iface/debugger.h> // in C
import "simics/simulator-iface/debugger.dml"; // in DML
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"
Python
import simics
class simics.debug_setup_interface_t(add_symbol_file=None,
add_symbol_segment=None, add_symbol_section=None,
remove_symbol_file=None, clear_symbol_files=None, symbol_files=None,
symbol_files_for_ctx=None, list_all_mappings=None,
add_path_map_entry=None, remove_path_map_entry=None,
clear_path_map_entries=None, path_map_entries=None,
path_map_entries_for_ctx=None, apply_path_map=None)
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. 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.
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.
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.
Execution Context
Global Context for all methods.
Name
debug_step — perform stepping with the debugger
Synopsis
C and DML
#include <simics/simulator-iface/debugger.h> // in C
import "simics/simulator-iface/debugger.dml"; // in DML
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"
Python
import simics
class simics.debug_step_interface_t(instruction_into=None, into=None,
instruction_over=None, over=None, out=None,
reverse_instruction_into=None, reverse_into=None,
reverse_instruction_over=None, reverse_over=None, reverse_out=None)
Description
This interface is used to perform stepping with the debugger, on a specified debug context.
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.
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.
Execution Context
Global Context for all methods.
Name
debug_symbol_file — for symbol file operations
Synopsis
C and DML
#include <simics/simulator-iface/debugger.h> // in C
import "simics/simulator-iface/debugger.dml"; // in DML
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"
Python
import simics
class simics.debug_symbol_file_interface_t(open_symbol_file=None,
close_symbol_file=None, symbol_file_info=None, sections_info=None,
segments_info=None, open_symbol_section=None)
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.
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.
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.
Execution Context
Global Context for all methods.
Name
debug_symbol — get symbol and source information
Synopsis
C and DML
#include <simics/simulator-iface/debugger.h> // in C
import "simics/simulator-iface/debugger.dml"; // in DML
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"
Python
import simics
class simics.debug_symbol_interface_t(address_source=None, source_address=None,
address_symbol=None, stack_depth=None, stack_frames=None,
local_variables=None, local_arguments=None, expression_value=None,
expression_type=None, type_info=None, type_to_string=None,
symbol_address=None, address_string=None, lvalue_write=None,
address_write=None, address_read=None, struct_members=None,
struct_field=None, list_functions=None, list_global_variables=None,
list_source_files=None)
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.
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.
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]]].
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. The symbols included are the known symbols from added symbol files that match ctx_id, for example symbol files added using 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.
Execution Context
Global Context for all methods.
Name
disasm_instr_t, disassemble — interface used with disassembling
Synopsis
C and DML
#include <simics/simulator-iface/disassemble.h> // in C
import "simics/simulator-iface/disassemble.dml"; // in DML
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;
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"
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.
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).
next returns a structure with the next disassembled instruction. Repeated use of next will disassemble additional instructions.
Execution Context
Cell Context for all methods.
Name
follower_agent — interface used with follower agents
Synopsis
C and DML
#include <simics/simulator-iface/follower.h> // in C
// not available in DML
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"
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.
Execution Context
Cell Context for all methods.
Name
gfx_break_cb_t, gbp_header_t, gfx_break — interface used with graphical breakpoints
Synopsis
C and DML
#include <simics/simulator-iface/consoles.h> // in C
import "simics/simulator-iface/consoles.dml"; // in DML
typedef int (*gfx_break_cb_t)(conf_object_t *obj,
int64 break_id, lang_void *arg);
typedef struct {
uint32 magic;
uint32 format;
uint64 bytes;
uint32 minx;
uint32 miny;
uint32 maxx;
uint32 maxy;
} gbp_header_t;
SIM_INTERFACE(gfx_break) {
bool (*store)(conf_object_t *NOTNULL obj,
const char *file,
uint32 minx, uint32 miny, uint32 maxx, uint32 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);
bytes_t (*store_bytes)(conf_object_t *NOTNULL obj,
uint32 minx, uint32 miny,
uint32 maxx, uint32 maxy);
int (*match_bytes)(conf_object_t *NOTNULL obj, bytes_t data);
};
#define GFX_BREAK_INTERFACE "gfx_break"
Python
import simics
class simics.gfx_break_interface_t(store=None, add=None, remove=None, match=None,
info=None, export_png=None, add_bytes=None, store_bytes=None,
match_bytes=None)
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 store and remove functions log error messages on failure.
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.
The store_bytes method behaves as store but writes the breakpoint data to memory and returns it, instead of writing a file. On failure, errors are logged and the return value is an empty bytes_t.
The match_bytes method behaves as match but reads the breakpoint data from memory instead of a file.
The gbp_header_t type is returned by the info method. The fields magic and format are always GBP_MAGIC and GBP_FMT_V3_32, respectively. The field bytes is the size of the image data in the file, not including the header. The other fields specify the breakpoint image patch location on the screen.
The gfx_break_cb_t callback function type is used by the graphics breakpoint system and called when the associated graphical breakpoint has matched. The obj parameter is the graphics console where the breakpoint matched, break_id is the associated breakpoint id, returned by the add method in the interface, and arg is the callback data passed to that method.
Execution Context
| Function | Context |
| match | Cell Context |
| match_bytes | Cell Context |
| all other methods | Global Context |
Name
host_serial — interface used to control connection to host serial port
Synopsis
C and DML
#include <simics/simulator-iface/consoles.h> // in C
import "simics/simulator-iface/consoles.dml"; // in DML
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"
Python
import simics
class simics.host_serial_interface_t(setup=None, name=None, shutdown=None)
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.
Execution Context
Global Context
Name
instrumentation_connection — interface used with instrumentation tools
Synopsis
C and DML
#include <simics/simulator-iface/instrumentation-tool.h> // in C
import "simics/simulator-iface/instrumentation-tool.dml"; // in DML
SIM_INTERFACE(instrumentation_connection) {
void (*enable)(conf_object_t *obj);
void (*disable)(conf_object_t *obj);
};
#define INSTRUMENTATION_CONNECTION_INTERFACE "instrumentation_connection"
Python
import simics
class simics.instrumentation_connection_interface_t(enable=None, disable=None)
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.
Execution Context
Cell Context for all methods.
Name
instrumentation_filter_master — interface used with instrumentation filter
Synopsis
C and DML
#include <simics/simulator-iface/instrumentation-filter.h> // in C
import "simics/simulator-iface/instrumentation-filter.dml"; // in DML
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"
Python
import simics
class simics.instrumentation_filter_master_interface_t(set_source_id=None,
add_slave=None, remove_slave=None, short_filter_config=None)
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.
Execution Context
Global Context for all methods.
Name
instrumentation_filter_slave — interface used with instrumentation filter
Synopsis
C and DML
#include <simics/simulator-iface/instrumentation-filter.h> // in C
import "simics/simulator-iface/instrumentation-filter.dml"; // in DML
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"
Python
import simics
class simics.instrumentation_filter_slave_interface_t(disable=None, enable=None)
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 method enables the connection. That is, the filter is now in a state when it thinks the connection should be enabled.
Execution Context
Cell Context for all methods.
Name
instrumentation_filter_status — interface used with instrumentation filter
Synopsis
C and DML
#include <simics/simulator-iface/instrumentation-filter.h> // in C
import "simics/simulator-iface/instrumentation-filter.dml"; // in DML
SIM_INTERFACE(instrumentation_filter_status) {
attr_value_t (*get_disabled_sources)(conf_object_t *obj);
};
#define INSTRUMENTATION_FILTER_STATUS_INTERFACE "instrumentation_filter_status"
Python
import simics
class simics.instrumentation_filter_status_interface_t(get_disabled_sources=None)
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.
Execution Context
Global Context for all methods.
Name
instrumentation_tool — interface used with instrumentation tools
Synopsis
C and DML
#include <simics/simulator-iface/instrumentation-tool.h> // in C
import "simics/simulator-iface/instrumentation-tool.dml"; // in DML
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"
Python
import simics
class simics.instrumentation_tool_interface_t(connect=None, disconnect=None)
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.
Execution Context
Global Context for all methods.
Name
leader_message — interface used with follower agents
Synopsis
C and DML
#include <simics/simulator-iface/follower.h> // in C
// not available in DML
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"
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.
Execution Context
Cell Context for all methods.
Name
osa_component — get information about OS awareness objects
Synopsis
C and DML
#include <simics/simulator-iface/osa-component-interface.h> // in C
import "simics/simulator-iface/osa-component-interface.dml"; // in DML
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"
Python
import simics
class simics.osa_component_interface_t(get_admin=None, get_root_node=None,
notify_tracker=None, cancel_notify=None, has_tracker=None,
get_processors=None)
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.
Execution Context
Cell Context for all methods.
Name
osa_control — enable and disable the OS awareness framework
Synopsis
C and DML
#include <simics/simulator-iface/osa-control-interface.h> // in C
import "simics/simulator-iface/osa-control-interface.dml"; // in DML
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"
Python
import simics
class simics.osa_control_interface_t(request=None, release=None)
Description
Note: The osa_control_v2 interface should be used instead of this one.
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.
Execution Context
Global Context for all methods.
See Also
osa_control_v2
Name
osa_control_v2 — enable and disable the OS awareness framework
Synopsis
C and DML
#include <simics/simulator-iface/osa-control-v2-interface.h> // in C
import "simics/simulator-iface/osa-control-v2-interface.dml"; // in DML
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"
Python
import simics
class simics.osa_control_v2_interface_t(request=None, release=None,
clear_state=None)
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.
Execution Context
Global Context for all methods.
Name
osa_machine_notification — get notifications for cpu updates in an OS awareness tracker
Synopsis
C and DML
#include <simics/simulator-iface/osa-machine-interfaces.h> // in C
import "simics/simulator-iface/osa-machine-interfaces.dml"; // in DML
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"
Python
import simics
class simics.osa_machine_notification_interface_t(notify_mode_change=None,
notify_exception=None, notify_control_reg=None,
notify_exec_breakpoint=None, notify_read_breakpoint=None,
notify_write_breakpoint=None, cancel=None,
notify_control_reg_read=None)
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 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.
Execution Context
Cell Context for all methods.
Name
osa_machine_query — get cpu state and read memory in an OS awareness tracker
Synopsis
C and DML
#include <simics/simulator-iface/osa-machine-interfaces.h> // in C
import "simics/simulator-iface/osa-machine-interfaces.dml"; // in DML
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_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"
Python
import simics
simics.OSA_Read_Four_Byte
simics.OSA_Read_Eight_Byte
simics.OSA_Read_One_Byte
simics.OSA_Read_Two_Byte
class simics.osa_machine_query_interface_t(read_register=None,
get_register_number=None, read_phys_memory=None,
read_phys_bytes=None, virtual_to_physical=None, cpu_mode=None,
get_all_processors=None, get_exception_number=None)
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.
Execution Context
Cell Context for all methods.
Name
osa_mapper_admin — implemented by OS awareness mappers to receive updates
Synopsis
C and DML
#include <simics/simulator-iface/osa-mapper-interfaces.h> // in C
import "simics/simulator-iface/osa-mapper-interfaces.dml"; // in DML
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"
Python
import simics
class simics.osa_mapper_admin_interface_t(tracker_updated=None)
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]},}
Execution Context
Cell Context for all methods.
Name
osa_mapper_control — for the OS awareness framework to control a mapper
Synopsis
C and DML
#include <simics/simulator-iface/osa-mapper-interfaces.h> // in C
import "simics/simulator-iface/osa-mapper-interfaces.dml"; // in DML
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"
Python
import simics
class simics.osa_mapper_control_interface_t(disable=None, enable=None,
clear_state=None)
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.
Execution Context
Cell Context for all methods.
Name
osa_mapper_query — for querying an OS awareness mapper about it’s nodes
Synopsis
C and DML
#include <simics/simulator-iface/osa-mapper-interfaces.h> // in C
import "simics/simulator-iface/osa-mapper-interfaces.dml"; // in DML
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"
Python
import simics
class simics.osa_mapper_query_interface_t(get_process_list=None, get_mapper=None)
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.
Execution Context
Global Context for all methods.
Name
osa_micro_checkpoint — get notifications when restoring of state starts and finishes
Synopsis
C and DML
#include <simics/simulator-iface/osa-micro-checkpoint-interface.h> // in C
import "simics/simulator-iface/osa-micro-checkpoint-interface.dml"; // in DML
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"
Python
import simics
class simics.osa_micro_checkpoint_interface_t(started=None, finished=None)
Description
This interface is used to get information when resting of a snapshot starts and finishes. The functions will only be called when the tracker framework is enabled.
started is called when a saved state is about to be restored, 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 snapshot.
This interface is optional and can be implemented by either a tracker or a mapper.
Execution Context
Global Context for all methods.
Name
osa_node_path — OS Awareness node path handling
Synopsis
C and DML
#include <simics/simulator-iface/osa-node-path-interface.h> // in C
import "simics/simulator-iface/osa-node-path-interface.dml"; // in DML
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"
Python
import simics
class simics.osa_node_path_interface_t(matching_nodes=None, node_path=None)
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.
Execution Context
Global Context for all methods.
Name
osa_node_tree_admin — used by mapper to communicate with OS awareness framework
Synopsis
C and DML
#include <simics/simulator-iface/osa-node-tree-admin-interface.h> // in C
import "simics/simulator-iface/osa-node-tree-admin-interface.dml"; // in DML
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"
Python
import simics
class simics.osa_node_tree_admin_interface_t(begin=None, end=None, create=None,
add=None, update=None, remove=None, event=None, activate=None,
deactivate=None, register_formatter=None, unregister_formatter=None,
reset=None, set_property=None)
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.
Execution Context
Cell Context for all methods.
Name
osa_node_tree_notification — listen to OS awareness node tree updates
Synopsis
C and DML
#include <simics/simulator-iface/osa-node-tree-interfaces.h> // in C
import "simics/simulator-iface/osa-node-tree-interfaces.dml"; // in DML
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"
Python
import simics
class simics.osa_node_tree_notification_interface_t(notify_create=None,
notify_destroy=None, notify_property_change=None,
notify_cpu_move_from=None, notify_cpu_move_to=None,
notify_event=None, notify_enable=None, notify_disable=None,
cancel_notify=None, notify_callbacks_done=None)
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 the node ID of a node that is to be created later is known, for example when re-running the same simulation after restoring a snapshot.
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.
Execution Context
Cell Context for all methods.
Name
osa_node_tree_query — query OS awareness node trees
Synopsis
C and DML
#include <simics/simulator-iface/osa-node-tree-interfaces.h> // in C
import "simics/simulator-iface/osa-node-tree-interfaces.dml"; // in DML
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"
Python
import simics
class simics.osa_node_tree_query_interface_t(get_root_nodes=None, get_node=None,
get_current_nodes=None, get_current_processors=None,
get_all_processors=None, get_mapper=None, get_parent=None,
get_children=None, get_formatted_properties=None)
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"}
Execution Context
Cell Context for all methods.
Name
osa_parameters — get and set OS awareness tracker parameters
Synopsis
C and DML
#include <simics/simulator-iface/osa-parameters-interface.h> // in C
import "simics/simulator-iface/osa-parameters-interface.dml"; // in DML
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"
Python
import simics
class simics.osa_parameters_interface_t(get_parameters=None, set_parameters=None,
is_kind_supported=None)
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.
Execution Context
Global Context for all methods.
Name
osa_tracker_component — get associated OS awareness trackers or mappers
Synopsis
C and DML
#include <simics/simulator-iface/osa-tracker-component-interface.h> // in C
import "simics/simulator-iface/osa-tracker-component-interface.dml"; // in DML
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"
Python
import simics
class simics.osa_tracker_component_interface_t(get_tracker=None, get_mapper=None)
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.
Execution Context
Cell Context for all methods.
Name
osa_tracker_control — control OS awareness trackers
Synopsis
C and DML
#include <simics/simulator-iface/osa-tracker-control-interface.h> // in C
import "simics/simulator-iface/osa-tracker-control-interface.dml"; // in DML
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"
Python
import simics
class simics.osa_tracker_control_interface_t(disable=None, enable=None,
clear_state=None, add_processor=None, remove_processor=None)
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.
Execution Context
Global Context for enable, disable and clear_state. Cell Context for add_processor and remove_processor.
Name
osa_tracker_state_admin — used by OS awareness trackers to modify state in framework
Synopsis
C and DML
#include <simics/simulator-iface/osa-tracker-state-interfaces.h> // in C
import "simics/simulator-iface/osa-tracker-state-interfaces.dml"; // in DML
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"
Python
import simics
class simics.osa_tracker_state_admin_interface_t(begin=None, end=None, add=None,
remove=None, remove_all=None, set_attribute=None, update=None,
event=None)
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.
Execution Context
Cell Context for all methods.
Name
osa_tracker_state_notification — for OS awareness mappers to get tracker updates from framework
Synopsis
C and DML
#include <simics/simulator-iface/osa-tracker-state-interfaces.h> // in C
import "simics/simulator-iface/osa-tracker-state-interfaces.dml"; // in DML
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"
Python
import simics
class simics.osa_tracker_state_notification_interface_t(subscribe_tracker=None,
unsubscribe_tracker=None)
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.
Execution Context
Cell Context for all methods.
Name
osa_tracker_state_query — query OS awareness framework for tracker state
Synopsis
C and DML
#include <simics/simulator-iface/osa-tracker-state-interfaces.h> // in C
import "simics/simulator-iface/osa-tracker-state-interfaces.dml"; // in DML
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"
Python
import simics
class simics.osa_tracker_state_query_interface_t(_deprecated=None,
get_entities=None, get_entity=None)
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.
Execution Context
Cell Context for all methods.
Name
probe_array — defines multiple probes with array access
Synopsis
C and DML
#include <simics/simulator-iface/probe-interface.h> // in C
import "simics/simulator-iface/probe-interface.dml"; // in DML
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"
Python
import simics
class simics.probe_array_interface_t(num_indices=None, value=None,
all_values=None, properties=None)
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.
Execution Context
Global Context for all methods.
Name
probe_index — defines multiple probes
Synopsis
C and DML
#include <simics/simulator-iface/probe-interface.h> // in C
import "simics/simulator-iface/probe-interface.dml"; // in DML
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"
Python
import simics
class simics.probe_index_interface_t(num_indices=None, value=None,
properties=None)
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.
Execution Context
Global Context for all methods.
Name
probe_key_t, probe — defines a probe in the system
Synopsis
C and DML
#include <simics/simulator-iface/probe-interface.h> // in C
import "simics/simulator-iface/probe-interface.dml"; // in DML
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_Histogram_Options = 21, /* list: histogram presentation
options */
} probe_key_t;
SIM_INTERFACE(probe) {
attr_value_t (*value)(conf_object_t *obj);
attr_value_t (*properties)(conf_object_t *obj);
};
#define PROBE_INTERFACE "probe"
Python
import simics
simics.Probe_Key_Description
simics.Probe_Key_Metric_Prefix
simics.Probe_Key_Float_Decimals
simics.Probe_Key_Cause_Slowdown
simics.Probe_Key_Kind
simics.Probe_Key_Aggregate_Function
simics.Probe_Key_Display_Name
simics.Probe_Key_Histogram_Options
simics.Probe_Key_Binary_Prefix
simics.Probe_Key_Categories
simics.Probe_Key_Value_Notifier
simics.Probe_Key_Unit
simics.Probe_Key_Width
simics.Probe_Key_Aggregate_Scope
simics.Probe_Key_Owner_Object
simics.Probe_Key_Time_Format
simics.Probe_Key_Float_Percent
simics.Probe_Key_Type
simics.Probe_Key_Aggregates
simics.Probe_Key_Definition
class simics.probe_interface_t(value=None, properties=None)
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 integer using the enum probe_key_t type, and the second value is a key specific data item described below.
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. 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 <
- 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 (1010241024), 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_Histogram_Options
-
The value for this key is a list of key/value pairs that controls histogram presentation. The supported option is percent, a boolean specifying whether tools should show a percentage column and combine omitted values when truncating output. It defaults to true. If false, tools should omit percentages and report only the number of omitted rows.
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”, “median”, “object-histogram” and “class-histogram”. 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.
Execution Context
Global Context for all methods.
Name
probe_sampler_cache — enable and disable probe caching
Synopsis
C and DML
#include <simics/simulator-iface/probe-interface.h> // in C
import "simics/simulator-iface/probe-interface.dml"; // in DML
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"
Python
import simics
class simics.probe_sampler_cache_interface_t(enable=None, disable=None,
get_generation=None)
Description
This interface is implemented by the singleton probes object, created by the enable-probes command. The interface is expected to be used by either probe-samplers (enable and 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.
Execution Context
Global Context for all methods.
Name
probe_subscribe — subscribe and unsubscribe to a probe
Synopsis
C and DML
#include <simics/simulator-iface/probe-interface.h> // in C
import "simics/simulator-iface/probe-interface.dml"; // in DML
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"
Python
import simics
class simics.probe_subscribe_interface_t(subscribe=None, unsubscribe=None,
num_subscribers=None)
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.
Execution Context
Global Context for all methods.
Name
recorder_v2 — interfaces used to help with recording of external interactions
Synopsis
C and DML
#include <simics/simulator-iface/recorder.h> // in C
import "simics/simulator-iface/recorder.dml"; // in DML
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"
Python
import simics
class simics.recorder_v2_interface_t(record=None, playback=None)
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.
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.
Execution Context
Cell Context
Name
screenshot — interface used with graphics console
Synopsis
C and DML
#include <simics/simulator-iface/consoles.h> // in C
import "simics/simulator-iface/consoles.dml"; // in DML
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"
Python
import simics
class simics.screenshot_interface_t(save_png=None, save_bmp=None)
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.
Execution Context
Global Context
Name
serial_console_frontend — interface for serial console communication
Synopsis
C and DML
#include <simics/simulator-iface/consoles.h> // in C
import "simics/simulator-iface/consoles.dml"; // in DML
SIM_INTERFACE(serial_console_frontend) {
void (*write)(conf_object_t *NOTNULL obj, uint8 value);
};
#define SERIAL_CONSOLE_FRONTEND_INTERFACE "serial_console_frontend"
Python
import simics
class simics.serial_console_frontend_interface_t(write=None)
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.
Execution Context
Cell Context
Name
table_key_t, column_key_t, extra_header_key_t, table — interface to help present table data
Synopsis
C and DML
#include <simics/simulator-iface/table.h> // in C
import "simics/simulator-iface/table.dml"; // in DML
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;
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;
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;
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"
Python
import simics
simics.Table_Key_Description
simics.Table_Key_Extra_Headers
simics.Table_Key_Stream_Header_Repeat
simics.Table_Key_Columns
simics.Table_Key_Name
simics.Table_Key_Default_Sort_Column
simics.Column_Key_Name
simics.Column_Key_Time_Format
simics.Column_Key_Width
simics.Column_Key_Metric_Prefix
simics.Column_Key_Generate_Acc_Percent_Column
simics.Column_Key_Alignment
simics.Column_Key_Int_Pad_Width
simics.Column_Key_Generate_Percent_Column
simics.Column_Key_Int_Radix
simics.Column_Key_Sort_Descending
simics.Column_Key_Footer_Sum
simics.Column_Key_Word_Delimiters
simics.Column_Key_Hide_Homogeneous
simics.Column_Key_Float_Percent
simics.Column_Key_Int_Grouping
simics.Column_Key_Float_Decimals
simics.Column_Key_Description
simics.Column_Key_Binary_Prefix
simics.Column_Key_Footer_Mean
simics.Column_Key_Unique_Id
simics.Extra_Header_Key_Description
simics.Extra_Header_Key_First_Column
simics.Extra_Header_Key_Last_Column
simics.Extra_Header_Key_Name
simics.Extra_Header_Key_Row
class simics.table_interface_t(data=None, properties=None)
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.
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.
- 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.
- Identifies a new header row.
- The name printed for the extra header element.
- 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.
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.
Column_Key_Footer_Sum Boolean
- If True, all columns values are summed up and displayed in a footer row, below the actual table.
Column_Key_Footer_Mean Boolean 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.
Execution Context
Global Context
Name
telnet_connection_v2 — interface used to control the telnet server
Synopsis
C and DML
#include <simics/simulator-iface/consoles.h> // in C
import "simics/simulator-iface/consoles.dml"; // in DML
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"
Python
import simics
class simics.telnet_connection_v2_interface_t(listening=None, connected=None,
disconnect=None)
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.
Execution Context
Global Context
Name
vnc_server_v2 — interface used to control the vnc server
Synopsis
C and DML
#include <simics/simulator-iface/consoles.h> // in C
import "simics/simulator-iface/consoles.dml"; // in DML
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"
Python
import simics
class simics.vnc_server_v2_interface_t(listening=None, num_clients=None,
disconnect=None)
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.
Execution Context
Global Context