a20 — access the A20 line
#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"
import simics
class simics.a20_interface_t(set_a20_line=None, get_a20_line=None)
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.
Cell Context for all methods.
aarch64_sysreg — interface for accessing system registers of AArch64 systems
#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"
import simics
class simics.aarch64_sysreg_interface_t(read_register=None, write_register=None)
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.
Cell Context for all methods.
apic_destination_mode_t, apic_delivery_mode_t, apic_trigger_mode_t, apic_bus_status_t, apic_bus — interface for apic buses
#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"
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)
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.
Cell Context for all methods.
apic_bus_to_apic — This interface is provided by APIC to APIC bus
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"
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.
Cell Context for all methods.
apic_bus_v2 — interface for handling 32-bit address mode interrupts
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"
The interface is used to handle extended 32-bit addressing mode supported by x2APIC. See apic_bus documentation.
Cell Context.
local_apic_interrupt_t, apic_cpu — interface for the local APIC
#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"
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)
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.
Cell Context for all methods.
apic_delivery_status_t — APIC delivery status
#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;
import simics
simics.Apic_Delivery_Status_Idle
simics.Apic_Delivery_Status_Send_Pending
apic_rr_status_t — APIC RR status
#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;
import simics
simics.Apic_RR_Pending
simics.Apic_RR_Invalid
simics.Apic_RR_Valid
apic_timer_mode_t — type for expressing APIC timer mode
typedef enum {
Apic_Timer_Mode_One_Shot = 0,
Apic_Timer_Mode_Periodic = 1,
Apic_Timer_Mode_Tsc_Deadline = 2
} apic_timer_mode_t;
apic_type_t — APIC types
typedef enum {
Apic_P6,
Apic_P4,
Apic_X2
} apic_type_t;
arinc429_bus — interface to Arinc-429 serial buses
#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"
import simics
class simics.arinc429_bus_interface_t(send_word=None)
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.
Cell Context for all methods.
arinc429_receiver — interface to Arinc-429 compatible receivers
#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"
import simics
class simics.arinc429_receiver_interface_t(receive_word=None)
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.
Cell Context for all methods.
arm_avic_t, arm_avic — ARM AVIC interface
#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"
import simics
class simics.arm_avic_t(valid=0, address=0)
class simics.arm_avic_interface_t(get_interrupt_address=None)
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.
Cell Context for all methods.
arm_coprocessor — ARM coprocessor interface
#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"
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)
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).
Cell Context for all methods.
arm_cpu_group_event — ARM cpu group event interface
#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"
import simics
class simics.arm_cpu_group_event_interface_t(signal_event=None)
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.
Threaded Context for all methods.
arm_cpu_group_exclusive — ARM cpu group exclusive interface
#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"
import simics
class simics.arm_cpu_group_exclusive_interface_t(mark_exclusive=None,
clear_and_probe_exclusive=None)
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.
Threaded Context for all methods.
arm_cpu_group_tlb — ARM cpu group tlb interface
#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"
import simics
class simics.arm_cpu_group_tlb_interface_t(invalidate_tlb=None)
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.
Threaded Context for all methods.
arm_gic_cpu_state — interface for ARM processors to provide state to gic-models
#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"
import simics
class simics.arm_gic_cpu_state_interface_t(get_cpu_state=None)
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.
Cell Context for all methods.
gic_reg_info_t, arm_gic — interface for ARM cores to access generic interrupt controller
#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"
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)
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.
Cell Context for all methods.
arm — interface that provides various functionality specific for Arm processors
#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"
import simics
class simics.arm_interface_t(read_register_mode=None, write_register_mode=None)
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.
Cell Context for all methods.
arm_trustzone_mode_t, arm_trustzone — ARM Trustzone interface
#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"
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)
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.
Cell Context for all methods.
bridge — implemented by objects that bridge between memory spaces
#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"
import simics
class simics.bridge_interface_t(not_taken=None)
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.
Cell Context for all methods.
can_device — Interface for receiving from CAN controller
SIM_INTERFACE(can_device) {
void (*receive)(conf_object_t *obj, can_frame_t *frame);
};
#define CAN_DEVICE_INTERFACE "can_device"
The can_device interface is implemented by CAN controllers. The receive function is called by can-endpoint to pass CAN frame from other can-endpoint to the connected CAN controller.
The CAN frame is expressed by the frame parameter, which is a pointer of can_frame_t.
Cell Context for all methods.
can_frame_t — CAN frame
typedef struct {
/* arbitration field */
uint32 identifier;
bool extended;
bool rtr;
/* control field */
uint8 data_length;
/* data field */
uint8 data[CAN_DATA_MAX_NUM];
/* crc field */
uint16 crc;
} can_frame_t;
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[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 is used to indicate if the frame is Extended frame or Standard frame.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 contains the arithmetic value of the DLC.crccan_link — Interface for sending to CAN endpoint
SIM_INTERFACE(can_link) {
can_status_t (*send)(conf_object_t *obj, can_frame_t *frame);
};
#define CAN_LINK_INTERFACE "can_link"
The can_link interface is implemented by can-endpoint. The send function is called by CAN controller to pass CAN frame to the connected can-endpoint. Then can-link delivers the CAN frame to other can-endpoints.
Cell Context for all methods.
coreint_reply_t, coreint — interface between CoreInt capable processor and interrupt controller
#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"
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.
Cell Context for all methods.
cxl_type_t, cxl_map — interface used to claim ranges in CXL address spaces
#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"
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)
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.
Cell Context for all methods.
cxl_mem_downstream_port_managing — interface for cxl downstream port memory management
#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"
import simics
class simics.cxl_mem_downstream_port_managing_interface_t(register_port_mem_obj=None,
unregister_port_mem_obj=None)
Functions register_port_mem_obj and unregister_port_mem_obj are used to register and unregister port memory objects.
Cell Context for all methods.
cxl_non_device_decoder_handling — interface for cxl_hdm_port
#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"
import simics
class simics.cxl_non_device_decoder_handling_interface_t(enable_decoder=None,
disable_decoder=None)
Functions enable_decoder and disable_decoder are used to enable and disable HDM decoders on a cxl-hdm-port device.
Cell Context for all methods.
datagram_link — implemented by objects that receive messages from a datagram-link
#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"
import simics
class simics.datagram_link_interface_t(receive=None)
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.
Cell Context
eri_reg_num_t — Registers number used by ERI or DCRA
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;
eri_transaction_t — Transaction info used in x86_eri_v1
typedef struct {
uint64 val; // Read or Write value
bool valid; // Valid or not data in val field
} eri_transaction_t;
eri_v2_transaction_t — Transaction info used in x86_eri_v2
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;
ethernet_cable — ethernet interface used for notification of link status
#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"
import simics
class simics.ethernet_cable_interface_t(link_status=None)
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.
Cell Context
ethernet_common — common ethernet interface used by all ethernet links and devices
#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"
import simics
class simics.ethernet_common_interface_t(frame=None)
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.
Cell Context
eth_probe_side_t, ethernet_probe_snoop_t, ethernet_probe — used to attach to ethernet connections and look at and/or modify frames
#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"
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)
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_snooperattach_probesend_frame function.detachsend_frame<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.
Cell Context for all methods.
ethernet_link_snoop_t, ethernet_snoop — used to attach snooping functions to ethernet links
#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"
import simics
class simics.ethernet_snoop_interface_t(attach=None)
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.
Global Context
ethernet_vlan_snoop — used to attach snoop functions to VLAN network
#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"
import simics
class simics.ethernet_vlan_snoop_interface_t(attach=None)
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.
Global Context
exec_trace — interface for handling registration of trace listeners
#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"
import simics
class simics.exec_trace_interface_t(register_tracer=None, unregister_tracer=None)
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.
Global Context for both methods. Cell Context for the callback.
extended_serial — extension to serial_device interface
#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"
import simics
class simics.extended_serial_interface_t(write_at=None, graphics_mode=None)
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.
Cell Context for all methods.
firewire_ack_code_t, firewire_bus — interface implemented by firewire buses
#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"
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)
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.
Cell Context for all methods.
uint32_array_t, firewire_device — implemented by firewire devices
#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"
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)
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.
Cell Context for all methods.
fmn_station_control — interface for Fast Messaging Network stations
#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"
import simics
class simics.fmn_station_control_interface_t(send_message=None, load_message=None,
wait=None, sync=None)
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.
Cell Context for all methods.
fmn_station_control_v2 — interface for Fast Messaging Network stations
#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"
import simics
class simics.fmn_station_control_v2_interface_t(send_message=None,
load_message=None, wait=None, sync=None)
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.
Cell Context for all methods.
frequency — interface used to publish frequency
#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"
import simics
class simics.frequency_interface_t(get=None)
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.
Cell Context for all methods.
frequency_listener — interface used to model frequency changes
#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"
import simics
class simics.frequency_listener_interface_t(set=None)
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.
Cell Context for all methods.
generic_message_device — Interface for receiving from generic message devices
SIM_INTERFACE(generic_message_device) {
void (*receive_frame)(conf_object_t *dev, conf_object_t *link,
dbuffer_t *frame);
};
#define GENERIC_MESSAGE_DEVICE_INTERFACE "generic_message_device"
This interface is implemented by generic message device objects that connect to generic-message-link objects. It is used by the link object to send messages to the device object. The link should implement the generic_message_link interface.
The receive_frame function is called by the link to send a frame to the device. The frame is passed as a dbuffer_t pointer that may not be modified without cloning it first.
| Function | Context |
|---|---|
receive_frame | Cell Context |
generic_message_link — Interface for gml-link
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"
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.
| Function | Context |
|---|---|
connect_device | Global Context |
disconnect_device | Global Context |
send_frame | Cell Context |
hpi — interface for Host Port Interface
#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"
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.
Cell Context for all methods.
i2c_ack_t, i2c_master_v2 — interface implemented by I2C masters
#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"
import simics
simics.I2C_noack
simics.I2C_ack
class simics.i2c_master_v2_interface_t(acknowledge=None, read_response=None)
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.
Cell Context for all methods.
i2c_slave_v2 — interface used by I2C devices
#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"
import simics
class simics.i2c_slave_v2_interface_t(start=None, read=None, write=None,
stop=None, addresses=None)
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.
The addresses method needs Global Context. All other methods can be used in Cell Context.
i3c_daa_snoop — interface used with I3C monitoring
#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"
import simics
class simics.i3c_daa_snoop_interface_t(assigned_address=None)
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.
Cell Context for all methods.
i3c_hdr_slave, i3c_hdr_master — interfaces for I3C HDR communication
#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"
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)
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:
hdr_read calls needed to read a large amount of 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.
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.
Cell Context for all methods.
i3c_ack_t, i3c_master, i3c_slave — interfaces for I3C bus communication
#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"
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)
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.
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.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.write calls, each call expects a response call to a method acknowledge. This is quite similar to I2C write transaction.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.
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.
Cell Context for all methods.
i8051_interrupt — interface for interrupts in i8051 cores
#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"
import simics
class simics.i8051_interrupt_interface_t(active_interrupt=None, reti=None,
suppress_irq=None)
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.
Cell Context for all methods.
i8051_timer — interface to control timer in i8051 cores
#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"
import simics
class simics.i8051_timer_interface_t(change_mode=None, switch_timer=None)
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.
Cell Context for all methods.
ieee_802_15_4_control — 802.15.4 control interface
SIM_INTERFACE(ieee_802_15_4_control) {
void (*set_rssi)(conf_object_t *NOTNULL obj,
uint64 tgt_ep_id,
uint32 rssi);
void (*remove_rssi)(conf_object_t *NOTNULL obj,
uint64 tgt_ep_id);
void (*clear_all_rssi)(conf_object_t *NOTNULL obj);
};
#define IEEE_802_15_4_CONTROL_INTERFACE "ieee_802_15_4_control"
The ieee_802_15_4_control interface is implemented by the IEEE 802.15.4 link endpoint objects that provide a interface for endpoint configuration. Simics command (Python program) calls set_rssi, remove_rssi and clear_all_rssi to update the RSSI table.
Cell Context for all methods.
ieee_802_15_4_frame_crc_status_t — 802.15.4 frame CRC status
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;
IEEE_802_15_4_Frame_CRC32_Unknown is for 802.15.4g only.ieee_802_15_4_link — An interface for 802.15.4 transmissions
SIM_INTERFACE(ieee_802_15_4_link) {
ieee_802_15_4_transmit_status_t (*transmit)(
conf_object_t *NOTNULL obj,
const frags_t *frame,
uint16 channel_page,
uint16 channel_number,
ieee_802_15_4_frame_crc_status_t crc_status);
};
#define IEEE_802_15_4_LINK_INTERFACE "ieee_802_15_4_link"
The ieee_802_15_4_link interface is implemented by the IEEE 802.15.4 link endpoint objects that provide an interface for frame traffic.
Transceiver calls transmit to send out frames. The return value is using one of the values in the ieee_802_15_4_transmit_status_t enum.
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.
Cell Context for all methods.
ieee_802_15_4_probe — Probe interface for 802.15.4 devices
SIM_INTERFACE(ieee_802_15_4_probe) {
void (*attach_snooper)(conf_object_t *NOTNULL probe,
ieee_802_15_4_probe_snoop_t snoop_fun,
lang_void *user_data);
void (*detach)(conf_object_t *NOTNULL probe);
};
#define IEEE_802_15_4_PROBE_INTERFACE "ieee_802_15_4_probe"
The ieee_802_15_4_probe interface is implemented by the IEEE 802.15.4 probe devices that provide an interface for Simics users to register their own callback to listen to the traffic going-on in the probe. The attach_snooper attaches a snooper function. The probe will pass each frame to the snooper function, then forward it unchanged where it should be going. The detach detaches the currently registered callback from the probe.
This interface should only be used for inspection, and never as part of the actual simulation. The snoop functions must not affect the simulation in any way. The user_data parameter is passed to the snoop function every time it is called.
ieee_802_15_4_probe_snoop_t, ieee_802_15_4_probe_side_t,
Cell Context for all methods.
ieee_802_15_4_probe_side_t — 802.15.4 probe
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;
ieee_802_15_4_probe_snoop_t — Function prototype for 802.15.4 probe snope functions.
typedef void (*ieee_802_15_4_probe_snoop_t)(
lang_void *user_data,
conf_object_t *probe,
ieee_802_15_4_probe_side_t to_side,
const frags_t *frame,
uint32 rssi,
uint16 channel_page,
uint16 channel_number,
ieee_802_15_4_frame_crc_status_t crc_status);
ieee_802_15_4_probe_side_t, ieee_802_15_4_frame_crc_status_t
ieee_802_15_4_receiver — 802.15.4 receiver interface
SIM_INTERFACE(ieee_802_15_4_receiver) {
void (*receive)(conf_object_t *NOTNULL obj,
const frags_t *frame,
uint32 rssi,
uint16 channel_page,
uint16 channel_number,
ieee_802_15_4_frame_crc_status_t crc_status);
void (*frame_lost)(conf_object_t *NOTNULL obj,
uint32 rssi,
uint16 channel_page,
uint16 channel_number);
};
#define IEEE_802_15_4_RECEIVER_INTERFACE "ieee_802_15_4_receiver"
The ieee_802_15_4_receiver interface is implemented by the IEEE 802.15.4 transceivers that provide an interface for traffic. Endpoints call receive to deliver a frame to transceiver. Transceiver should check if the received frame from endpoint is in the channel that it is using. The channel being used is defined by channel_page and channel_number. Endpoints call frame_lost to notify transceivers on that a frame was lost because of low RSSI value.
Cell Context for all methods.
ieee_802_15_4_transmit_status_t — 802.15.4 transmit status
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;
ieee_802_3_mac — interface used for media access control layer
#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"
import simics
class simics.ieee_802_3_mac_interface_t(receive_frame=None,
tx_bandwidth_available=None, link_status_changed=None)
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.
Cell Context for all methods.
ieee_802_3_link_status_t, ieee_802_3_mac_v3 — interface used for media access control layer
#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"
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)
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.
Cell Context for all methods.
ieee_802_3_phy — interface used with 802.3 physical layers
#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"
import simics
class simics.ieee_802_3_phy_interface_t(send_frame=None, check_tx_bandwidth=None,
set_promiscous_mode=None)
Interface that should be implemented by 802.3 physical layers.
use ieee_802_3_phy_v2 instead.
ieee_802_3_phy_v2 — interface used with 802.3 physical layers
#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"
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)
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.
Cell Context for all methods.
ieee_802_3_phy_v3 — interface used with 802.3 physical layers
#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"
import simics
class simics.ieee_802_3_phy_v3_interface_t(send_frame=None,
check_tx_bandwidth=None)
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.
Cell Context for all methods.
instruction_trace_callback_t — Function type for callbacks in exec_trace_interface_t
#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);
It takes the following arguments:
tracer_datatracer_data when registering the listener function with register_tracer() in the exec_trace interface.cpulavapaopcodeint_register — access registers in a processor
#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"
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)
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_CatchableCore_Control_Register_Write and Core_Control_Register_Read are triggered when this register is written or read. Return 0 otherwise.Cell Context for all methods, except for write where the register is a program counter; Global Context in that case.
interrupt_ack — interface used with acked interrupts
#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"
import simics
class simics.interrupt_ack_interface_t(raise_interrupt=None, lower_interrupt=None)
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.
Cell Context for all methods.
interrupt_cpu — interface used with interrupts
#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"
import simics
class simics.interrupt_cpu_interface_t(ack=None)
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.
Cell Context for all methods.
interrupt_subscriber — interface used with interrupts
#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"
import simics
class simics.interrupt_subscriber_interface_t(notify=None, reset=None)
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.
Threaded Context for all methods.
addr_space_t, io_memory — legacy interface for devices that can be mapped into address spaces
#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"
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)
This interface is legacy. New code should use the
transactioninterface.
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.
Cell Context for all methods.
map_demap — interface used to configure memory spaces
#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"
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)
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.
Cell Context for all methods.
mdio45_bus — interface for PHY with MDIO management interface
#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"
import simics
class simics.mdio45_bus_interface_t(read_register=None, write_register=None)
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.
Cell Context for all methods.
mdio45_phy — interface for PHY with MDIO management interface
#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"
import simics
class simics.mdio45_phy_interface_t(read_register=None, write_register=None)
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.
Cell Context for all methods.
memory_space — implemented by classes that provide linear address spaces
#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"
import simics
class simics.memory_space_interface_t(space_lookup=None, access=None, read=None,
write=None, timing_model_operate=None, fill=None)
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.
The read and write methods signal errors by raising frontend exceptions.
Cell Context for all methods.
microwire — interface used to communicate with a 3-wire devices
#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"
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)
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.
Cell Context for all methods.
mii — interface for PHY with MII management interface
#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"
import simics
class simics.mii_interface_t(serial_access=None, read_register=None,
write_register=None)
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.
Cell Context for all methods.
mii_management — interface for PHY with MII management interface
#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"
import simics
class simics.mii_management_interface_t(serial_access=None, read_register=None,
write_register=None)
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.
Cell Context for all methods.
mips_cache_instruction — interface for side effects of cache instructions
#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"
import simics
class simics.mips_cache_instruction_interface_t(cache_instruction=None)
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.
Cell Context.
mips_coprocessor — interface used by MIPS cores to access coprocessors
#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"
import simics
class simics.mips_coprocessor_interface_t(read_register=None, write_register=None)
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.
Cell Context for all methods.
mips_eic — interface used between MIPS cores and external interrupt controllers
#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"
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)
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.
Cell Context for all methods.
mips_exception_query — interface used with instrumentation of MIPS cores
#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"
import simics
class simics.mips_exception_query_interface_t(return_pc=None)
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.
Cell Context for all methods.
mips — MIPS dummy interface
#include <simics/arch/mips.h> // in C
import "simics/arch/mips.dml"; // in DML
SIM_INTERFACE(mips) {
int dummy;
};
#define MIPS_INTERFACE "mips"
import simics
class simics.mips_interface_t()
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.
Not applicable.
mips_ite — interface for MIPS Inter-Thread Communication Unit
#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"
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)
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.
Cell Context for all methods.
multi_level_signal — model a signal with multiple levels, such as an analog signal
#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"
import simics
class simics.multi_level_signal_interface_t(signal_level_change=None,
signal_current_level=None)
Obsoleted by the
uint64_stateinterface.
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.
Cell Context for all methods.
nand_flash — interface implemented by NAND Flash devices
#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"
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)
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.
Cell Context for all methods.
network_breakpoint — used to attach snoop functions to VLAN network
#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"
import simics
class simics.network_breakpoint_interface_t(add=None, remove=None)
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.
Global Context for all methods
nios_cache — NIOS cache interface
#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"
import simics
class simics.nios_cache_interface_t(flushd=None, flushda=None, flushi=None,
flushp=None, initd=None, initda=None, initi=None, sync=None)
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.
Cell Context for all methods.
nios_custom — interface used with the NIOS custom instruction
#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"
import simics
class simics.nios_custom_interface_t(custom=None)
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.
Cell Context
nios_eic — interface for NIOS external interrupt controllers
#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"
import simics
class simics.nios_eic_interface_t(handler=None, level=None, reg_set=None,
nmi=None, handled=None)
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.
Cell Context for all methods.
nios — NIOS dummy interface
#include <simics/arch/nios.h> // in C
import "simics/arch/nios.dml"; // in DML
SIM_INTERFACE(nios) {
int dummy;
};
#define NIOS_INTERFACE "nios"
import simics
class simics.nios_interface_t()
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.
Not applicable.
nvm_subsystem_controller_management — Interface for NVME Subsystem Controller management
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"
This interface is intended for implementing NVM Subsystem Controller management.
register_controllercntid: The controller identifier to registercontroller: The controller object to registerget_all_controllersCell Context for all methods.
nvme_namespace_management — Interface for NVMe namespace management
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"
This interface is intended for implementing NVMe namespace management.
create_namespacecreates 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_namespacedeletes 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 deletedelete_all_namespacesdeletes all existing namespaces.
attach_namespaceattaches a namespace to one or more controllers. Returns 0 on success, or a negative error code on failure. Parameters:
nsid: The namespace identifier to attachcntids: List of controller IDs to attach the namespace todetach_namespacedetaches a namespace from one or more controllers. Returns 0 on success, or a negative error code on failure. Parameters:
nsid: The namespace identifier to detachcntids: List of controller IDs to detach the namespace fromget_max_namespacesreturns the maximum number of namespaces supported by the NVM subsystem.
get_namespacesreturns 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_uuidretrieves the UUID of the specified namespace. Returns the UUID as a string, or NULL if the namespace doesn’t exist. Parameters:
nsid: The namespace identifierget_namespace_sizeretrieves the size in bytes of the specifiednamespace. Returns the size, or 0 if the namespace doesn’t exist. Parameters:
nsid: The namespace identifierget_total_disk_capacityreturns the total disk capacity in bytes available to the NVM subsystem.
get_free_disk_capacityreturns the free (unallocated) disk capacity in bytes available for new namespaces.
sanitizeperforms a sanitize operation on the NVM subsystem using the specified action. Returns 0 on success, or a negative error code on failure.
format_nvmperforms 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 performCell Context for all methods.
packet — interface used to transfer data between devices
#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"
import simics
class simics.packet_interface_t(transfer=None)
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.
pci_bridge — interface used with downstream PCI(e)
#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"
import simics
class simics.pci_bridge_interface_t(system_error=None, raise_interrupt=None,
lower_interrupt=None)
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.
Cell Context for all methods.
pci_bus — interface implemented by all PCI buses
#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"
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)
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_accessfunction is deprecated and must not be called (as it is not implemented by Simics pci-bus object). Theinterrupt_acknowledge,special_cycle,add_defaultandremove_defaultfunctions are also deprecated, but they are still implemented by Simics pci-bus and thus callable.
Cell Context for all methods.
pci_device — interface implemented by PCI devices
#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"
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)
This interface is implemented by all PCI devices (including bridges).
The
interrupt_acknowledgeandspecial_cyclefunctions are deprecated. The functions can be left unimplemented (NULL).
Cell Context for all methods.
pci_downstream — interface used with downstream PCI(e)
#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"
import simics
class simics.pci_downstream_interface_t(operation=None)
The pci_downstream interface is implemented by PCI(e) buses to handle downstream transactions.
Cell Context for all methods.
pci_express_hotplug — deprecated interface part of the old PCIe library
#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"
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)
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.
Cell Context for all methods.
pcie_message_type_t, pci_express — deprecated interface part of the old PCIe library
#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"
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)
Deprecated as part of the old PCIe library. Replaced by the new PCIe library.
This interface is deprecated. The
transactioninterface 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 relatedpcie_typeandpcie_msg_routeATOMs 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.
Cell Context for all methods.
pci_interrupt — interface used with PCI(e) interrupts
#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"
import simics
class simics.pci_interrupt_interface_t(raise_interrupt=None, lower_interrupt=None)
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.
Cell Context for all methods.
pci_multi_function_device — interface used by PCI devices with multiple functions
#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"
import simics
class simics.pci_multi_function_device_interface_t(supported_functions=None)
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.
Global Context for all methods.
pci_upstream — interface used with upstream PCI(e)
#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"
import simics
class simics.pci_upstream_interface_t(operation=None)
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.
Cell Context for all methods.
pci_upstream_operation — interface used with upstream PCI(e)
#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"
import simics
class simics.pci_upstream_operation_interface_t(read=None, write=None)
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:
Other return values are currently unexpected.
Cell Context for all methods.
pcie_adapter_compat — interface used with PCIe
#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"
import simics
class simics.pcie_adapter_compat_interface_t(set_secondary_bus_number=None)
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.
Cell Context for all methods.
pcie_device — interface implemented by PCI devices
#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"
import simics
class simics.pcie_device_interface_t(connected=None, disconnected=None,
hot_reset=None)
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.
Global Context for all methods.
pcie_function_info — interface used with PCIe
#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"
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)
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).
Cell Context for all methods.
pcie_hotplug_pd_t, pcie_hotplug_mrl_t, pcie_hotplug_events — interface implemented by Hot-Plug capable Downstream Ports
#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"
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)
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:
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.
Cell Context for all methods.
pcie_link_control — Interface allowing receiving upstream and downstream
#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"
import simics
class simics.pcie_link_control_interface_t(downstream_component_blocking=None,
upstream_component_blocking=None, request_link_retraining=None)
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.
Cell Context for all methods.
pcie_link_readiness — Interface for receiving link blocking state changes.
#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"
import simics
class simics.pcie_link_readiness_interface_t(link_down=None,
link_not_blocking=None)
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.
Cell Context for all methods.
pcie_link_training — interface used with PCIe training
#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"
import simics
class simics.pcie_link_training_interface_t(trigger=None, invoke=None)
Trigger link training on obj. The trigger function is deprecated and should not be used. The implementation of trigger ignores the device_id.
Cell Context for all methods.
pcie_map — interface used with PCIe address space
#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"
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)
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.
Cell Context for all methods.
pcie_port_control — interface used to configure PCIe downstream ports
#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"
import simics
class simics.pcie_port_control_interface_t(set_secondary_bus_number=None,
hot_reset=None)
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.
Cell Context for all methods.
pmr — PPC performance monitor interface
#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"
import simics
class simics.pmr_interface_t(get=None, set=None)
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.
Cell Context for all methods.
port_space — I/O port interface
#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"
import simics
class simics.port_space_interface_t(port_operation=None, read=None, write=None)
Cell Context for all methods.
ppc_mc_exc_t, ppc — PPC specific interface
#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"
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)
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.
Cell Context for all methods.
pulse — model a pulse, meaning an event that triggers
#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"
import simics
class simics.pulse_interface_t(pulse=None)
Cell Context for all methods.
ram, rom — provide random access memory
#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"
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)
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
ramandrominterfaces 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.
Cell Context for all methods.
riscv_coprocessor — RISC-V coprocessor interface
#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"
import simics
class simics.riscv_coprocessor_interface_t(read_register=None,
write_register=None)
This interface makes it possible for RISC-V processors to read and write externally defined Control and Status Registers (CSRs) like mtime.
Threaded Context for all methods.
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
#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"
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)
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.
Global Context for all methods.
riscv_instruction_action — interface implemented by RISC-V cpus and used to model custom instructions
#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"
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)
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.
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.
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.
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.
get_current_cpu_mode returns current cpu mode.
raise_exception raises exception with xCAUSE CSR set to code and xTVAL CSR set to tval.
Threaded Context for all methods. Must only be called from within an instruction emulation callback registered using the cpu_instruction_decoder interface.
sata — interface implemented by SATA objects
#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"
import simics
class simics.sata_interface_t(receive_fis=None)
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.
Cell Context for all methods.
scale_factor_listener — interface used for modeling changes in frequency scale factors
#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"
import simics
class simics.scale_factor_listener_interface_t(set=None)
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.
Cell Context for all methods.
TTY_ABORT, serial_device — interface used to connect serial devices together
#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"
import simics
class simics.serial_device_interface_t(write=None, receive_ready=None)
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.
Cell Context for all methods.
serial_peripheral_interface_flags_t — type used with serial_peripheral_interface_slave interface
#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;
import simics
simics.SPI_Flags_CPOL
simics.SPI_Flags_CPHA
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.
serial_peripheral_interface_master — interface implemented by SPI master devices
#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"
import simics
class simics.serial_peripheral_interface_master_interface_t(spi_response=None)
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.
Cell Context for all methods.
serial_peripheral_interface_slave — interface implemented by all SPI slave devices
#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"
import simics
class simics.serial_peripheral_interface_slave_interface_t(spi_request=None,
connect_master=None, disconnect_master=None)
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.
Cell Context for all methods.
serial_peripheral_interface_master, serial_peripheral_interface_flags_t
shared_memory_map_demap — Interface for mapping/unmapping shared memory
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"
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.
Cell Context for all methods.
signal — model a logical signal
#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"
import simics
class simics.signal_interface_t(signal_raise=None, signal_lower=None)
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.
Cell Context for all methods.
simple_dispatcher — interface for subscribing to frequency related changes
#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"
import simics
class simics.simple_dispatcher_interface_t(subscribe=None, unsubscribe=None)
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.
Global Context for all methods.
simple_interrupt — obsolete interface used with interrupts
#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"
import simics
class simics.simple_interrupt_interface_t(interrupt=None, interrupt_clear=None)
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
signalinterface.
Cell Context for all methods.
smm_instrumentation_subscribe — x86 specific interface for smm mode instrumentation
#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"
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)
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.
Global Context for all methods.
sparc_v8_ecc_fault_injection — interface for error injection with SPARC V8
#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"
Support the injection of uncorrectable ECC faults. It can be used to inject
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.
Cell Context for all methods.
sparc_v8 — interface for SPARC V8 specific functions
#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"
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.
Cell Context for all methods.
spr — interface for ppc special function registers
#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"
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)
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.
register_user_handlersunregister_user_handlersset_target_valuestash_valuefetch_valuedefault_getterdefault_setterget_nameget_numbertelemetry_class_id_t, telemetry_id_t, telemetry — interface for accessing or providing arbitrary data
#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"
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)
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_namecan return a valid name for sometelemetry_class_idbutget_telemetry_idon 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.
Global Context for all methods.
transaction_translator — interface used to inspect and/or modify transactions
#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"
import simics
class simics.transaction_translator_interface_t(translate=None)
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.
Cell Context for all methods.
translation_t, translation_flush interface, SIM_map_target_flush
translate — implemented by objects that bridge between memory spaces
#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"
import simics
class simics.translate_interface_t(translate=None)
The translate interface is implemented by objects that bridge between memory spaces.
There is the
translatorinterface which is a more restricted version of thetranslateinterface 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.
Cell Context for all methods.
translation_flush — optional interface used with address translation
#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"
import simics
class simics.translation_flush_interface_t(flush_range=None)
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.
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
Cell Context
translator — interface implemented for address translation
#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"
import simics
class simics.translator_interface_t(translate=None)
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).
Cell Context
uint64_state — interface used in transferring state between devices
#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"
import simics
class simics.uint64_state_interface_t(set=None)
Interface to transfer a state representable in an uint64 from one device to another. Examples of what the state might represent includes:
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_stateinterface should be used instead of the deprecatedmulti_level_signalinterface when writing new models.
Cell Context for all methods.
usb_device — interface implemented by USB devices
#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"
import simics
class simics.usb_device_interface_t(submit_transfer=None, abort_transfer=None,
reset=None)
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.
Cell Context for all methods.
usb — interface used in communication with USB hosts
#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"
import simics
class simics.usb_interface_t(connect_device=None, disconnect_device=None,
complete_transfer=None)
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.
connect_devicedisconnect_device Cell Contextcomplete_transfervectored_interrupt — interface used with vectored interrupts
#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"
import simics
class simics.vectored_interrupt_interface_t(set_level=None)
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.
Cell Context for all methods.
vectored_interrupt_source — interface implemented by interrupt sources
#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"
import simics
class simics.vectored_interrupt_source_interface_t(acknowledge=None)
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.
Cell Context for all methods.
virtiofs_fuse — FUSE request handler interface
SIM_INTERFACE(virtiofs_fuse)
{
buffer_t (*handle_request)(conf_object_t * obj, bytes_t req);
};
#define VIRTIOFS_FUSE_INTERFACE "virtiofs_fuse"
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.
Cell Context for all methods.
vmp — control VMP from a user perspective
#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"
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)
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.
Cell Context for all methods.
vmx_instrumentation_subscribe — x86 specific interface for vmx mode instrumentation
#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"
import simics
class simics.vmx_instrumentation_subscribe_interface_t(register_vmx_mode_leave_cb=None,
register_vmx_mode_enter_cb=None)
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.
Global Context for all methods.
x86_access_type — information about the x86_access_type_t enum
#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"
import simics
class simics.x86_access_type_interface_t(get_enum_name=None, get_short_name=None,
get_description=None, implicit=None)
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.
Cell Context for all methods.
x86_address_query — interface for x86 specific address queries
#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"
import simics
class simics.x86_address_query_interface_t(segment=None,
get_page_crossing_info=None)
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).
Cell Context for all methods, but must be called from a callback receiving a handle of type address_handle_t.
x86_cache_flush — flush x86 specific caches
#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"
import simics
class simics.x86_cache_flush_interface_t(flush=None)
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.
Cell Context for all methods.
cpuid_ret_t, x86_cpuid — customize responses to CPUID requests
#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"
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)
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.
Cell Context for all methods.
cpuid_value_t, x86_cpuid_query — query values returned by the CPUID instruction
#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"
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)
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.
Cell Context for all methods.
x86_cstate_event_t — Enumeration of all supported reasons for a C-state change
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;
x86_cstate_t, x86_cstate — interface used with x86 power states
#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"
import simics
class simics.x86_cstate_t(state=0, sub_state=0)
class simics.x86_cstate_interface_t(get_cstate=None, set_cstate=None)
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.
Cell Context for all methods.
x86_cstate_notification — interface used with x86 power states
#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"
import simics
class simics.x86_cstate_notification_interface_t(notification=None)
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.
Cell Context.
x86_cstate_notification_v2 — Interface to notifyabout C-state transitions
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"
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].
x86_cstate_notify_info_t — Contains C-state event info
typedef struct {
x86_cstate_event_t event;
uint32 state;
uint32 sub_state;
} x86_cstate_notify_info_t;
x86_doma_cstate_info_v2_t — Info about cstates
typedef struct {
uint32 state;
uint32 sub_state;
uint64 deadline;
uint64 tsc;
} x86_doma_cstate_info_v2_t;
x86_doma_cstate_v3 — Interface that provides callbacks on cstate changes
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"
For notify_sleep, and notify_resume, the cstate information is in the info x86_doma_cstate_info_v2_t argument.
x86_ept — provides insight into the Extended Page Table (EPT)
#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"
import simics
class simics.x86_ept_interface_t(guest_physical_to_physical=None,
is_ept_active=None)
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.
Cell Context for all methods.
x86_eri_v1 — For read/write of ERI registers
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"
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.
x86_eri_v2 — For read/write of ERI registers
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"
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.
x86_exception — raise x86 exceptions
#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"
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)
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.
The methods in this interface may only be called from user decoder service routines.
x86_exception_query — interface for x86 specific exception queries
#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"
import simics
class simics.x86_exception_query_interface_t(vector=None, source=None,
error_code=None)
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.
Cell Context for all methods, but must be called from a callback receiving a handle of type exception_handle_t.
x86_execution_mode_t, x86_execution_mode — provides insight into the processor execution mode
#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"
import simics
class simics.x86_execution_mode_t
class simics.x86_execution_mode_interface_t(get_execution_mode=None)
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.
Cell Context for all methods.
x86_external_reset — interface that notifies clients of reset
SIM_INTERFACE(x86_external_reset) {
void (*triple_fault_event)(conf_object_t *obj);
};
#define X86_EXTERNAL_RESET_INTERFACE "x86_external_reset"
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.
Cell Context for all methods.
x86_instruction_query — interface for x86 specific instrumentation queries
#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"
import simics
class simics.x86_instruction_query_interface_t(linear_address=None)
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.
Threaded Context for all methods, but must be called from a callback receiving a handle of type instruction_handle_t.
x86_instrumentation_subscribe — interface for x86 specific instrumentation subscribe
#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"
import simics
class simics.x86_instrumentation_subscribe_interface_t(register_mode_switch_cb=None,
register_illegal_instruction_cb=None)
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.
Global Context for all methods.
x86_instrumentation_subscribe_v2 — interface for x86 specific instrumentation subscribe
#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"
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)
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.
Global Context for all methods.
x86_pin_t, tagged_linear_address_t, x86 — x86 specific functionality
#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"
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)
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.
Cell Context for all methods.
x86_alignment_t, x86_read_physical_ret_t, x86_memory_access — access x86 memory from user decoder service routines
#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"
import simics
simics.X86_Alignment_Required
simics.X86_Alignment_Not_Required
class simics.x86_memory_access_interface_t(read_logical=None, write_logical=None)
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.
The methods in this interface may only be called from user decoder service routines.
x86_memory_operation — access memory from a user instruction
#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"
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.
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.
x86_memory_query — interface for x86 specific memory instrumentation queries
#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"
import simics
class simics.x86_memory_query_interface_t(linear_address=None, segment=None,
access_type=None, memory_type=None)
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.
Cell Context for all methods, but must be called from a callback receiving a handle of type memory_handle_t.
x86_monitor — interface for supporting MONITOR/MWAIT instructions
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"
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.
Cell Context for all methods.
x86_monitor_notification — interface for getting a callback for writes to write-ack memory
SIM_INTERFACE(x86_monitor_notification) {
bool (*notify)(conf_object_t *obj);
};
#define X86_MONITOR_NOTIFICATION_INTERFACE "x86_monitor_notification"
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.
Cell Context.
x86_msr_access_type_t, x86_msr_ret_t, x86_msr_getter_ret_t, x86_msr — x86 msr interface
#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"
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)
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.
Cell Context for all methods.
x86_pkg_cstate — interface used with x86 power states
#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"
import simics
class simics.x86_pkg_cstate_interface_t(get_pkg_cstate=None, set_pkg_cstate=None,
pkg_cstate_update=None)
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.
Cell Context for all methods.
x86_rar_interrupt — interface for providing CPU with RAR interrupt info
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"
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.
Cell Context for all methods.
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
#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"
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)
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.
Cell Context for all methods.
x86_sai — interface for retrieving current sai
SIM_INTERFACE(x86_sai) {
uint64 (*get_current_sai)(conf_object_t *obj);
};
#define X86_SAI_INTERFACE "x86_sai"
x86_smm — custom SMRAM state save map
#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"
import simics
class simics.x86_smm_interface_t(save_state=None, restore_state=None)
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.
Cell Context for all methods.
x86_smm_event_type_t, x86_smm_phase_type_t, x86_smm_notification — interface for registering callbacks on SMI
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"
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.
Cell Context.
x86_smm_state — access x86 smm state
#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"
import simics
class simics.x86_smm_state_interface_t(get_state=None, set_state=None,
smram_read=None, smram_write=None)
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.
Cell Context for all methods.
tagged_physical_address_t, x86_tlb — used to communicate between x86 cpu and its TLB
#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"
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)
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.
Cell Context for all methods.
x86_tlb_attrs_t, x86_tlb_entry_t, x86_tlb_v2 — used to communicate between x86 cpu and its TLB
#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"
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)
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.
Cell Context for all methods.
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
#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"
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)
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.
Cell Context for all methods.
x86_txt_chipset — interface to Intel® Trusted Execution Technology (Intel® TXT)
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"
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.
Cell Context for all methods.
x86_unplug — interface for plug and and plug of CPU cores/threads
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"
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).
Cell Context for all methods.
x86_unplug_v2 — interface for plug and and plug of CPU cores/threads
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"
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).
Cell Context for all methods.
x86_vmp_control — block VMP from being used
#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"
import simics
class simics.x86_vmp_control_interface_t(get_block_count=None,
set_block_count=None)
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.
Cell Context for all methods.
xed_access — call into the call Intel\reg; XED library
#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"
import simics
class simics.xed_access_interface_t(get_last=None, decode=None, to_string=None)
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.
Cell Context for all methods.
xtensa_export_state — TIE interface for the export state type
#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"
import simics
class simics.xtensa_export_state_interface_t(register_export_state=None)
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.
Cell Context for all methods.
xtensa_import_wire — TIE interface for the import wire type
#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"
import simics
class simics.xtensa_import_wire_interface_t(register_import_wire=None)
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.
Cell Context for all methods.
xtensa_input_queue — TIE interface for the input queue type
#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"
import simics
class simics.xtensa_input_queue_interface_t(register_input_queue=None)
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.
Cell Context for all methods.
xtensa_internal_memories — interface implemented by all Xtensa cores
#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"
import simics
class simics.xtensa_internal_memories_interface_t(iram_mappings=None,
irom_mappings=None, dram_mappings=None, drom_mappings=None)
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.
Cell Context for all methods.
xtensa_lookup — Xtensa TIE interface for the lookup type
#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"
import simics
class simics.xtensa_lookup_interface_t(register_lookup=None)
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.
Cell Context for all methods.
xtensa_mpu_lookup_t, xtensa_mpu_lookup — interface used with xtensa MPU
#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"
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)
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.
Cell Context for all methods.
xtensa_output_queue — TIE interface for the output queue type
#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"
import simics
class simics.xtensa_output_queue_interface_t(register_output_queue=None)
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.
Cell Context for all methods.
xtensa_reset_configure — interface implemented by Xtensa cores
#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"
import simics
class simics.xtensa_reset_configure_interface_t(set_reset_prid=None,
set_alternative_reset_vector=None)
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.
Threaded Context for all methods.
xtensa_tie_export_state — interface for tie communication with xtensa
#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"
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.
Cell Context for all methods.
xtensa_tie_import_wire — interface for tie communication with xtensa
#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"
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.
Cell Context for all methods.
xtensa_tie_input_queue — interface for tie communication with xtensa
#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"
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.
Cell Context for all methods.
xtensa_tie_lookup — interface for tie communication with xtensa
#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"
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.
Cell Context for all methods.
xtensa_tie_output_queue — interface for tie communication with xtensa
#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"
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.
Cell Context for all methods.
xtensa_wwdt_config — internal interface for WWDT communication
#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"
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)
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.
Cell Context for all methods.
xtensa_wwdt_faultinfo_t, xtensa_wwdt_faultinfo — interface used with Xtensa WWDT timer
#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"
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)
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.
Cell Context for all methods.