MM_FREE | free vtmem object |
MM_MALIGN | allocate aligned memory |
MM_MALLOC | allocate memory object |
MM_REALLOC | reallocate memory |
MM_STRDUP | duplicate a string |
PCIE_send_message | send a message to root complex |
PCI_add_config_register | add device specific configuration register |
PCI_bridge_default_access_not_taken | default handling of unclaimed accesses |
PCI_bridge_default_interrupt_lowered | default handling of secondary interrupts |
PCI_bridge_default_interrupt_raised | default handling of secondary interrupts |
PCI_bridge_default_system_error | default system error handling for bridges |
PCI_bridge_init | Initialize generic PCI bridge device |
PCI_bridge_map_setup | Set optional memory mapping attributes |
PCI_config_register_name | return name of a configuration register |
PCI_config_register_size | return size of a configuration register |
PCI_configuration_access | access the configuration space |
PCI_data_from_memory | read/write raw data from memory space |
PCI_data_to_memory | read/write raw data from memory space |
PCI_default_configuration_read_access | default function for configuration register reads |
PCI_default_configuration_write_access | default function for configuration register writes |
PCI_default_device_reset | default PCI device reset handling |
PCI_device_init | initialize the generic PCI device |
PCI_get_bus_address | get the bus address of a device |
PCI_get_config_register_mask | get write mask of a configuration register |
PCI_get_map_always_on | query and modify base address mapping |
PCI_get_map_base | query and modify base address mapping |
PCI_get_map_enable | query and modify base address mapping |
PCI_get_map_ignore_command | query and modify base address mapping |
PCI_get_map_offset | query and modify base address mapping |
PCI_get_map_size | query and modify base address mapping |
PCI_get_may_stall | Specifies if memory accesses are stallable |
PCI_handle_mapping32 | handle base address register |
PCI_handle_mapping64 | handle base address register |
PCI_lower_interrupt | raise and lower a PCI interrupt |
PCI_lower_interrupt_pin | raise and lower a PCI interrupt |
PCI_raise_interrupt | raise and lower a PCI interrupt |
PCI_raise_interrupt_pin | raise and lower a PCI interrupt |
PCI_read_config_register | read a configuration register |
PCI_read_sized_config_register | read a configuration register |
PCI_register_bridge_attributes | register generic PCI bridge attributes |
PCI_register_device_attributes | register generic PCI device attributes |
PCI_set_config_register_mask | set write mask of a configuration register |
PCI_set_map_always_on | query and modify base address mapping |
PCI_set_map_base | query and modify base address mapping |
PCI_set_map_enable | query and modify base address mapping |
PCI_set_map_ignore_command | query and modify base address mapping |
PCI_set_map_offset | query and modify base address mapping |
PCI_set_map_size | query and modify base address mapping |
PCI_set_may_stall | Specifies if memory accesses are stallable |
PCI_system_error | assert system error |
PCI_value_from_memory | read/write value from memory space |
PCI_value_to_memory | read/write value from memory space |
PCI_write_config_register | read a configuration register |
PCI_write_sized_config_register | write a configuration register |
SIM_STC_flush_cache | flush or remove entries in the STCs of a cpu |
SIM_add_configuration | set configuration from Python |
SIM_add_directory | add directory to search path |
SIM_add_mode_counter | obsolete API function |
SIM_add_output_handler | register output handler |
SIM_all_classes | obsolete API function |
SIM_all_objects | obsolete API function |
SIM_alloc_attr_dict | create empty attribute dictionary |
SIM_alloc_attr_list | create empty attribute list |
SIM_alloc_conf_object | allocate object |
SIM_alpha_mem_trans_from_generic | convert generic transaction to CPU specific |
SIM_arm_mem_trans_from_generic | convert generic transaction to CPU specific |
SIM_ascanf | parse list attribute values |
SIM_attribute_error | specify reason for attribute error |
SIM_break_cycle | insert breakpoint in time queue |
SIM_break_message | stop the simulation |
SIM_break_simulation | stop the simulation |
SIM_break_step | set a step breakpoint |
SIM_breakpoint | set breakpoint |
SIM_breakpoint_action | obsolete API function |
SIM_breakpoint_remove | delete breakpoint range |
SIM_c_frontend_exception | obsolete API function |
SIM_c_get_mem_op_value_buf | get value for a memory operation |
SIM_c_hap_occurred | trigger a hap occurrence |
SIM_c_hap_occurred_always | trigger a hap occurrence |
SIM_c_hap_occurred_always_vararg | trigger a hap occurrence |
SIM_c_hap_occurred_vararg | trigger a hap occurrence |
SIM_c_set_mem_op_value_buf | set value for a memory operation |
SIM_cancel_realtime_event | cancel callback in host time |
SIM_change_attribute_attribute | change requiredness of attribute |
SIM_check_exception | obsolete API function |
SIM_class_has_attribute | check if class implements attribute |
SIM_clear_atomic_reservation_bit | obsolete API function |
SIM_clear_directories | clear the search path |
SIM_clear_exception | clear pending exception |
SIM_command_clear_problem | signal error in command |
SIM_command_has_problem | signal error in command |
SIM_command_problem_status | signal error in command |
SIM_continue | continue the simulation |
SIM_copyright | get version info about Simics |
SIM_cpu_by_mid | obsolete API function |
SIM_cpu_enabled | obsolete API function |
SIM_cpu_issue_cycles | obsolete API function |
SIM_cpu_privilege_level | obsolete API function |
SIM_create_object | create and initialise object |
SIM_current_processor | get current processor |
SIM_cycle_count | query time queue for current time |
SIM_delete_breakpoint | delete breakpoint |
SIM_delete_object | delete object |
SIM_device_log | obsolete API function |
SIM_disable_processor | enable or disable a processor |
SIM_disassemble | disassemble instruction |
SIM_disassemble_physical | obsolete API function |
SIM_dump_caches | obsolete API function |
SIM_enable_processor | enable or disable a processor |
SIM_ensure_partial_attr_order | ensure attribute order |
SIM_exception_has_occurred | obsolete API function |
SIM_flush | text output routines |
SIM_flush_D_STC_logical | flush or remove entries in the STCs of a cpu |
SIM_flush_D_STC_physical | flush or remove entries in the STCs of a cpu |
SIM_flush_I_STC_logical | flush or remove entries in the STCs of a cpu |
SIM_flush_I_STC_physical | flush or remove entries in the STCs of a cpu |
SIM_flush_all_caches | clear Simics's internal caches |
SIM_for_all_hap_types | obsolete API function |
SIM_for_all_memory_pages | apply callback function to all memory pages |
SIM_for_all_modules | obsolete API function |
SIM_for_all_modules_failed | obsolete API function |
SIM_for_all_processors | obsolete API function |
SIM_free_attribute | free attribute |
SIM_frontend_exception | raise an exception |
SIM_get_No_Exception | obsolete API function |
SIM_get_all_classes | get list of all classes |
SIM_get_all_exceptions | processor exception conversion utilities |
SIM_get_all_failed_modules | return a list of all modules that failed to load |
SIM_get_all_hap_types | get list of all hap types |
SIM_get_all_modules | return a list of all modules |
SIM_get_all_objects | get list of all objects |
SIM_get_all_processors | get list of all processors |
SIM_get_all_registers | get all register numbers |
SIM_get_attribute | get attribute |
SIM_get_attribute_attributes | get attribute flags |
SIM_get_attribute_idx | get attribute |
SIM_get_base_pointer | obsolete API function |
SIM_get_batch_mode | return setting of the batch-mode |
SIM_get_class | get class |
SIM_get_class_attribute | get attribute |
SIM_get_class_attribute_idx | get attribute |
SIM_get_class_interface | get interface |
SIM_get_class_name | get class name |
SIM_get_class_port_interface | get interface |
SIM_get_configuration_file_prefix | get filename prefix |
SIM_get_control_register_name | obsolete API function |
SIM_get_control_register_number | obsolete API function |
SIM_get_current_proc_no | obsolete API function |
SIM_get_directories | get the current search path |
SIM_get_exception_name | processor exception conversion utilities |
SIM_get_exception_number | processor exception conversion utilities |
SIM_get_file_size | obsolete API function |
SIM_get_history_match | obsolete API function |
SIM_get_interface | get interface |
SIM_get_mem_op_type | get type of transaction |
SIM_get_mem_op_type_name | get name of memory operation type |
SIM_get_mem_op_value_be | get value for a memory operation |
SIM_get_mem_op_value_buf | get value for a memory operation |
SIM_get_mem_op_value_cpu | get value for a memory operation |
SIM_get_mem_op_value_le | get value for a memory operation |
SIM_get_mmu_data | obsolete API function |
SIM_get_mode_counter | obsolete API function |
SIM_get_object | get object |
SIM_get_pending_exception | get current pending exception |
SIM_get_port_interface | get interface |
SIM_get_proc_no | obsolete API function |
SIM_get_processor | get processor pointer from number |
SIM_get_processor_number | get the number of a processor |
SIM_get_program_counter | read/write program counter |
SIM_get_quiet | return setting of the quiet flag |
SIM_get_register_name | convert between register name and register number |
SIM_get_register_number | convert between register name and register number |
SIM_get_simics_home | obsolete API function |
SIM_get_stack_pointer | obsolete API function |
SIM_get_trap_time | obsolete API function |
SIM_get_unique_memory_transaction_id | Micro-Architecture Interface functions |
SIM_get_unique_memory_transaction_id | get unique memory transaction ID |
SIM_get_verbose | get the verbose flag |
SIM_hap_add_callback | install callback on a hap |
SIM_hap_add_callback_index | install callback on a hap |
SIM_hap_add_callback_obj | install callback on a hap |
SIM_hap_add_callback_obj_index | install callback on a hap |
SIM_hap_add_callback_obj_range | install callback on a hap |
SIM_hap_add_callback_range | install callback on a hap |
SIM_hap_add_type | register a new hap type |
SIM_hap_callback_exists | get callback status |
SIM_hap_delete_callback | delete installed hap callback |
SIM_hap_delete_callback_id | delete installed hap callback |
SIM_hap_delete_callback_obj | delete installed hap callback |
SIM_hap_delete_callback_obj_id | delete installed hap callback |
SIM_hap_get_name | get hap name by number |
SIM_hap_get_number | get hap number by name |
SIM_hap_install_callback | obsolete API function |
SIM_hap_install_callback_idx | obsolete API function |
SIM_hap_install_callback_range | obsolete API function |
SIM_hap_is_active | check if hap has callbacks |
SIM_hap_new_type | obsolete API function |
SIM_hap_occurred | trigger hap occurrence |
SIM_hap_occurred_always | trigger hap occurrence |
SIM_hap_register_callback | obsolete API function |
SIM_hap_register_callback_idx | obsolete API function |
SIM_hap_register_callback_range | obsolete API function |
SIM_hap_remove_callback | obsolete API function |
SIM_hap_remove_type | remove a hap type |
SIM_hap_unregister_callback | obsolete API function |
SIM_ia64_mem_trans_from_generic | convert generic transaction to CPU specific |
SIM_inc_cur_mode_counter | obsolete API function |
SIM_inc_mode_counter | obsolete API function |
SIM_initial_configuration_ok | get configuration status |
SIM_install_default_ASI_handler | obsolete API function |
SIM_install_user_ASI_handler | obsolete API function |
SIM_instruction_begin | Micro-Architecture Interface functions |
SIM_instruction_child | Micro-Architecture Interface functions |
SIM_instruction_commit | Micro-Architecture Interface functions |
SIM_instruction_cpu | Micro-Architecture Interface functions |
SIM_instruction_decode | Micro-Architecture Interface functions |
SIM_instruction_end | Micro-Architecture Interface functions |
SIM_instruction_execute | Micro-Architecture Interface functions |
SIM_instruction_fetch | Micro-Architecture Interface functions |
SIM_instruction_force_correct | Micro-Architecture Interface functions |
SIM_instruction_get_field_value | Micro-Architecture Interface functions |
SIM_instruction_get_reg_info | Micro-Architecture Interface functions |
SIM_instruction_get_user_data | Micro-Architecture Interface functions |
SIM_instruction_handle_exception | Micro-Architecture Interface functions |
SIM_instruction_handle_interrupt | Micro-Architecture Interface functions |
SIM_instruction_id_from_mem_op_id | Micro-Architecture Interface functions |
SIM_instruction_info | obsolete API function |
SIM_instruction_insert | Micro-Architecture Interface functions |
SIM_instruction_is_sync | Micro-Architecture Interface functions |
SIM_instruction_length | Micro-Architecture Interface functions |
SIM_instruction_nth_id | Micro-Architecture Interface functions |
SIM_instruction_opcode | Micro-Architecture Interface functions |
SIM_instruction_parent | Micro-Architecture Interface functions |
SIM_instruction_phase | Micro-Architecture Interface functions |
SIM_instruction_proceed | Micro-Architecture Interface functions |
SIM_instruction_read_input_reg | Micro-Architecture Interface functions |
SIM_instruction_read_output_reg | Micro-Architecture Interface functions |
SIM_instruction_remaining_stall_time | Micro-Architecture Interface functions |
SIM_instruction_retire | Micro-Architecture Interface functions |
SIM_instruction_rewind | Micro-Architecture Interface functions |
SIM_instruction_set_stop_phase | Micro-Architecture Interface functions |
SIM_instruction_set_user_data | Micro-Architecture Interface functions |
SIM_instruction_speculative | Micro-Architecture Interface functions |
SIM_instruction_squash | Micro-Architecture Interface functions |
SIM_instruction_stalling_mem_op | Micro-Architecture Interface functions |
SIM_instruction_status | Micro-Architecture Interface functions |
SIM_instruction_store_queue_mem_op | Micro-Architecture Interface functions |
SIM_instruction_type | Micro-Architecture Interface functions |
SIM_instruction_write_input_reg | Micro-Architecture Interface functions |
SIM_instruction_write_output_reg | Micro-Architecture Interface functions |
SIM_is_interactive | running interactive command predicate |
SIM_iter_addr | Iterate over address profile counters |
SIM_iter_free | Iterate over address profile counters |
SIM_iter_next | Iterate over address profile counters |
SIM_last_error | get error message from last exception |
SIM_license | get version info about Simics |
SIM_load_binary | read an executable file into memory |
SIM_load_file | read a file into memory |
SIM_load_module | load/unload modules |
SIM_log_constructor | initiate log class |
SIM_log_error | output log message |
SIM_log_info | output log message |
SIM_log_message | print and log message |
SIM_log_register_groups | register names of log groups |
SIM_log_spec_violation | output log message |
SIM_log_target_error | output log message |
SIM_log_undefined | output log message |
SIM_log_unimplemented | output log message |
SIM_logical_to_physical | translate logical to physical |
SIM_lookup_file | find a file using simics-path |
SIM_make_attr_boolean | make boolean attribute |
SIM_make_attr_data | create raw data attribute |
SIM_make_attr_floating | make floating point attribute |
SIM_make_attr_integer | make integer attribute |
SIM_make_attr_invalid | make invalid attribute |
SIM_make_attr_list | make list attribute |
SIM_make_attr_list_vararg | make list attribute |
SIM_make_attr_nil | make empty attribute |
SIM_make_attr_object | make object attribute |
SIM_make_attr_string | make string attribute |
SIM_mem_op_is_control | transaction control predicates |
SIM_mem_op_is_data | transaction data/instruction predicates |
SIM_mem_op_is_from_cache | Cache initiated transaction |
SIM_mem_op_is_from_cpu | CPU initiated transaction |
SIM_mem_op_is_from_cpu_arch | CPU initiated transaction |
SIM_mem_op_is_from_device | Device initiated transaction |
SIM_mem_op_is_instruction | transaction data/instruction predicates |
SIM_mem_op_is_prefetch | transaction control predicates |
SIM_mem_op_is_read | transaction read/write predicates |
SIM_mem_op_is_write | transaction read/write predicates |
SIM_mips_mem_trans_from_generic | convert generic transaction to CPU specific |
SIM_module_list_refresh | refresh list of loadable modules |
SIM_native_path | convert path to its native form |
SIM_new_object | create object |
SIM_next_queue | get next object that owns a queue |
SIM_no_windows | obsolete API function |
SIM_notify_on_descriptor | register notification on host I/O events |
SIM_notify_on_object | register notification on host I/O events |
SIM_notify_on_socket | register notification on host I/O events |
SIM_num_control_registers | obsolete API function |
SIM_number_processors | number of processors |
SIM_object_by_id | obsolete API function |
SIM_object_constructor | base class constructor |
SIM_object_is_processor | test if object is a processor |
SIM_pci_mem_trans_from_generic | convert generic transaction to CPU specific |
SIM_post_command | post callback to be run when simulation is stopped |
SIM_postponing_continue | ask if continue will be postponed |
SIM_ppc_mem_trans_from_generic | convert generic transaction to CPU specific |
SIM_printf | text output routines |
SIM_printf_vararg | text output routines |
SIM_proc_no_2_ptr | obsolete API function |
SIM_processor_break | obsolete API function |
SIM_processor_enabled | check if processor is enabled |
SIM_processor_privilege_level | return the current privilege level for a processor |
SIM_putchar | text output routines |
SIM_puts | text output routines |
SIM_quit | quit Simics |
SIM_raise_general_exception | obsolete API function |
SIM_read_byte | read/write byte from a memory space |
SIM_read_configuration | read configuration |
SIM_read_control_register | obsolete API function |
SIM_read_fp_register | obsolete API function |
SIM_read_fp_register_d | obsolete API function |
SIM_read_fp_register_i | obsolete API function |
SIM_read_fp_register_s | obsolete API function |
SIM_read_fp_register_x | obsolete API function |
SIM_read_global_register | obsolete API function |
SIM_read_phys_memory | read data from a physical address |
SIM_read_phys_memory_tags | access auxiliary bits in physical memory |
SIM_read_register | get register value |
SIM_read_window_register | obsolete API function |
SIM_readme | get version info about Simics |
SIM_realtime_event | schedule callback in host time |
SIM_register_arch_decoder | install/uninstall instruction decoders |
SIM_register_attribute | register attribute |
SIM_register_class | register class |
SIM_register_class_alias | register class alias |
SIM_register_class_attribute | register attribute |
SIM_register_copyright | register copyright information |
SIM_register_decoder | deprecated install/uninstall user decoders |
SIM_register_interface | register interface |
SIM_register_port_interface | register interface |
SIM_register_typed_attribute | register attribute |
SIM_register_typed_class_attribute | register attribute |
SIM_release_stall | Micro-Architecture Interface functions |
SIM_release_stall | release stalling transaction |
SIM_remove_output_handler | unregister output handler |
SIM_reset_processor | reset the processor |
SIM_run_command_file | read CLI commands from file |
SIM_set_attribute | set attribute |
SIM_set_attribute_idx | set attribute |
SIM_set_class_attribute | set attribute |
SIM_set_class_attribute_idx | set attribute |
SIM_set_configuration | set configuration from data |
SIM_set_mem_op_type | set type of transaction |
SIM_set_mem_op_value_be | set value for a memory operation |
SIM_set_mem_op_value_buf | set value for a memory operation |
SIM_set_mem_op_value_cpu | set value for a memory operation |
SIM_set_mem_op_value_le | set value for a memory operation |
SIM_set_mode_counter | obsolete API function |
SIM_set_program_counter | read/write program counter |
SIM_set_prompt | change prompt in Simics |
SIM_set_quiet | enable/disable quiet mode |
SIM_set_verbose | set the verbose flag |
SIM_simics_is_running | check if Simics is running |
SIM_snapshot_date | get version info about Simics |
SIM_source_python | execute Python source file |
SIM_source_python_in_module | execute Python source file |
SIM_sparc_ASI_info | obsolete API function |
SIM_stacked_post | insert an event that runs as soon as possible |
SIM_stall | stall execution a specified number of cycles |
SIM_stall_count | get number of cycles a processor has been stalled |
SIM_stall_cycle | stall execution a specified number of cycles |
SIM_stalled_until | query how many cycles that remains of stall |
SIM_step_clean | remove events from the step queue |
SIM_step_count | query step queue count |
SIM_step_next_occurrence | get number of steps until a step queue event occurs |
SIM_step_post | add an event in step queue |
SIM_thread_safe_callback | call function synchronized with main thread |
SIM_time | query time queue for current time |
SIM_time_clean | remove all matching events from time queue |
SIM_time_next_occurrence | get cycles to matching event |
SIM_time_post | add event to time queue |
SIM_time_post_cycle | add event to time queue |
SIM_unload_module | load/unload modules |
SIM_unregister_arch_decoder | install/uninstall instruction decoders |
SIM_unregister_decoder | deprecated install/uninstall user decoders |
SIM_v9_mem_trans_from_generic | convert generic transaction to CPU specific |
SIM_version | get version info about Simics |
SIM_version_sub | get version info about Simics |
SIM_void_to_processor_t | obsolete API function |
SIM_write | text output routines |
SIM_write_byte | read/write byte from a memory space |
SIM_write_configuration_to_file | write configuration |
SIM_write_control_register | obsolete API function |
SIM_write_fp_register | obsolete API function |
SIM_write_fp_register_d | obsolete API function |
SIM_write_fp_register_i | obsolete API function |
SIM_write_fp_register_s | obsolete API function |
SIM_write_fp_register_x | obsolete API function |
SIM_write_global_register | obsolete API function |
SIM_write_phys_memory | write data to a physical address |
SIM_write_phys_memory_tags | access auxiliary bits in physical memory |
SIM_write_register | set register value |
SIM_write_window_register | obsolete API function |
SIM_x86_mem_trans_from_generic | convert generic transaction to CPU specific |
cli.arg | define a command argument |
cli.eval_cli_line | evaluate a CLI command line |
cli.get_available_object_name | return a non-allocated object name |
cli.new_command | define a new CLI command |
cli.number_str | return a ready-to-print representation of a number |
cli.object_expander | Standard expander for an object argument |
cli.quiet_run_command | Run a CLI command and return output |
cli.run_command | Run a CLI command |
dbuffer_append | Add data to a dbuffer |
dbuffer_append_external_data | Add static data |
dbuffer_append_value | Add data with uniform content |
dbuffer_clone | Make a full copy of another buffer |
dbuffer_copy_append | Copy data from a dbuffer |
dbuffer_copy_prepend | Copy data from a dbuffer |
dbuffer_free | Release a dbuffer |
dbuffer_insert | Add data to a dbuffer |
dbuffer_len | Get the size of a dbuffer |
dbuffer_prepend | Add data to a dbuffer |
dbuffer_prepend_external_data | Add static data |
dbuffer_prepend_value | Add data with uniform content |
dbuffer_read | Extract data for reading |
dbuffer_read_all | Extract data for reading |
dbuffer_read_some | Extract data for reading |
dbuffer_remove | Remove data from a dbuffer |
dbuffer_remove_head | Remove data from a dbuffer |
dbuffer_remove_tail | Remove data from a dbuffer |
dbuffer_replace | Replace data |
dbuffer_replace_all | Replace data |
dbuffer_replace_some | Replace data |
dbuffer_split | Split a dbuffer |
dbuffer_update | Extract data for updating |
dbuffer_update_all | Extract data for updating |
dbuffer_update_some | Extract data for updating |
new_dbuffer | Create a new dbuffer |
sim_commands.new_info_command | define a new info command |
sim_commands.new_status_command | define a new status command |
attr_value_t SIM_alloc_attr_dict(int length);
attr_value_t SIM_alloc_attr_list(int length);
int SIM_ascanf(attr_value_t *list, const char *fmt, ...);
The characters in the format string mean:
format char argument element must be i integer_t * Sim_Val_Integer f double * Sim_Val_Floating s const char ** Sim_Val_String S const char ** Sim_Val_String or Sim_Val_Nil o conf_object_t ** Sim_Val_Object O conf_object_t ** Sim_Val_Object or Sim_Val_Nil l attr_value_t ** Sim_Val_List d attr_value_t ** Sim_Val_Data a attr_value_t ** any except Sim_Val_Invalid
The fmt string may also include a period (.) at the end, taken to mean that more elements may follow. If the period is not present, the length of the list must equal the number of specified elements.
attr_value_t SIM_make_attr_boolean(integer_t b);
attr_value_t SIM_make_attr_data(integer_t size, void *data);
attr_value_t SIM_make_attr_floating(double d);
attr_value_t SIM_make_attr_integer(integer_t i);
attr_value_t SIM_make_attr_invalid(void);
attr_value_t SIM_make_attr_list(int length, ...);
attr_value_t SIM_make_attr_list_vararg(int length, va_list va);
attr_value_t SIM_make_attr_nil(void);
attr_value_t SIM_make_attr_object(conf_object_t *obj);
attr_value_t SIM_make_attr_string(const char *str);
void SIM_break_cycle(conf_object_t *obj, integer_t cycles);
void SIM_break_step(conf_object_t *obj, integer_t steps);
breakpoint_id_t SIM_breakpoint(conf_object_t *obj, breakpoint_kind_t kind, access_t access, uint64 address, uint64 length, unsigned flags);
The kind argument sets what type of address to break on:
typedef enum { Sim_Break_Physical = 0, Sim_Break_Virtual = 1, Sim_Break_Linear = 2 /* x86 only */ } breakpoint_kind_t;
The access argument is a bit-field setting the type of access. Any combination of the tree alternatives can be given (or'ed together).
typedef enum { Sim_Access_Read = 1, Sim_Access_Write = 2, Sim_Access_Execute = 4 } access_t;
The address is the start of the breakpoint range and length is its length in bytes. This range will be truncated as necessary to fit in the address space. An access intersecting the given range will trigger the breakpoint. If length is zero, the breakpoint range will be the entire address space.
The flags argument should be passed a bitwise or of zero or more enumeration constants from enum breakpoint_flag:
enum breakpoint_flag { Sim_Breakpoint_Temporary = 1, Sim_Breakpoint_Simulation = 2, Sim_Breakpoint_Private = 4 };
If the Sim_Breakpoint_Temporary bit is set, the breakpoint is automatically disabled when triggered the first time.
If the Sim_Breakpoint_Simulation bit is set, the breakpoint will not show up in the list-breakpoints command, nor can it be removed by the unbreak command. Also, there will be no message printed on the Simics console when this breakpoint is triggered. This bit should be set when using breakpoints to simulate the target system; it will prevent Simics from temporarily disabling the breakpoint as an optimization measure. This could otherwise happen during certain reverse execution operations.
If the Sim_Breakpoint_Private bit is set, the breakpoint will not show up in the list-breakpoints command, nor can it be removed by the unbreak command. Also, there will be no message printed on the Simics console when this breakpoint is triggered.
The default action for a triggered breakpoint is to return to the frontend (this can be changed by using haps). On execution breakpoints Simics will return to the frontend before the instructions is executed, while instructions triggering read or write breakpoints will complete before control is returned to the frontend.
Several breakpoints can be set on the same address and Simics will break on them in turn. If hap handlers are connected to the breakpoints they will also be executed in turn. Hap handlers are called before the access is performed, allowing the user to read a memory value that may be overwritten by the access. See the Simics Reference Manual for a description of hap handlers.
Several attributes can be set for a breakpoint for breaking only when some conditions are true. See the breakpoints attribute in the sim class.
This function returns the breakpoint id which is used for further reference to the breakpoint:
typedef int breakpoint_id_t;
Breakpoints can be removed using SIM_delete_breakpoint().
void SIM_breakpoint_remove(int id, access_t access, generic_address_t address, generic_address_t length);
access is a bitfield describing the type of breakpoint to remove using the enumeration constants of the access_t enum.
start is the start address of the range and length is the length of the range in bytes.
void SIM_delete_breakpoint(breakpoint_id_t id);
void SIM_add_configuration(pre_conf_object_set_t *set, const char *file);
The file argument in the name of the file that a configuration was read from, and should be set to None/NULL if not used.
conf_object_t * SIM_alloc_conf_object(parse_object_t *pa);
void SIM_attribute_error(const char *msg);
int SIM_change_attribute_attribute(conf_class_t *cls, const char *name, attr_attr_t attr);
typedef enum { Sim_Attr_Required = 0, Sim_Attr_Optional = 1, Sim_Attr_Session = 3, Sim_Attr_Pseudo = 4, Sim_Attr_Flag_Mask = 0xff, Sim_Init_Phase_Shift = 8, Sim_Init_Phase_0 = 0 << Sim_Init_Phase_Shift, Sim_Init_Phase_1 = 1 << Sim_Init_Phase_Shift, Sim_Attr_Integer_Indexed = 0x1000, Sim_Attr_String_Indexed = 0x2000, Sim_Attr_List_Indexed = 0x4000, Sim_Attr_Persistent = 0x20000, /* set by SIM_register_*_attribute() */ Sim_Attr_Read_Only = 0x40000, Sim_Attr_Write_Only = 0x80000 } attr_attr_t;
int SIM_class_has_attribute(conf_class_t *cls, const char *attr);
conf_object_t * SIM_create_object(conf_class_t *cls, const char *name, attr_value_t attrs);
The new object is initialised with attributes from attrs, which must be a list of (attribute-name, value) pairs as two-element lists. All required attributes for the class cl must be present in attrs.
int SIM_delete_object(conf_object_t *obj);
void SIM_ensure_partial_attr_order(conf_class_t *cls, const char *attr1, const char *attr2);
This function checks the registration order of attr1 and attr2 in the class cls. If attr1 is not registered before attr2, or if at least one of the two are not registered at all, an ASSERT is triggered.
Use this function to ensure that e.g. code refactoring does not break a required attribute order.
void SIM_free_attribute(attr_value_t value);
When called with a Sim_Val_List argument, it calls SIM_free_attribute() on each element of the list before freeing the list itself.
attr_value_t SIM_get_all_classes(void);
attr_value_t SIM_get_all_objects(void);
attr_value_t SIM_get_attribute(conf_object_t *obj, const char *name);
attr_value_t SIM_get_class_attribute(conf_class_t *cls, const char *name);
attr_value_t SIM_get_attribute_idx(conf_object_t *obj, const char *name, attr_value_t *index);
attr_value_t SIM_get_class_attribute_idx(conf_class_t *cls, const char *name, attr_value_t *index);
Return values of kind Sim_Val_List or Sim_Val_Dict have to be freed using SIM_free_attribute().
attr_attr_t SIM_get_attribute_attributes(conf_class_t *cls, const char *attr);
SIM_get_attribute_attributes() with an object as parameter is deprecated since Simics 3.0.
conf_class_t * SIM_get_class(const char *name);
const char * SIM_get_class_name(const conf_class_t *class_data);
const char * SIM_get_configuration_file_prefix(void);
void * SIM_get_interface(const conf_object_t *obj, const char *name);
void * SIM_get_class_interface(const conf_class_t *cls, const char *name);
void * SIM_get_port_interface(const conf_object_t *obj, const char *name, const char *portname);
void * SIM_get_class_port_interface(const conf_class_t *cls, const char *name, const char *portname);
SIM_get_port_interface() returns an port interface instance as registered with SIM_register_port_interface(). The portname selects a particular implementation of the interface by obj's class. If no instance name is supplied, the function behaves as SIM_get_interface().
If a class only defines a single port interface, it may be looked up using SIM_get_interface() as well.
SIM_get_class_interface and SIM_get_class_port_interface are similar but return the interface for a class instead of an object.
conf_object_t * SIM_get_object(const char *name);
struct conf_object { conf_class_t *class_data; /* class data */ const char *name; /* instance name */ struct conf_object *queue; /* queue */ lang_void *object_data; /* internal to class implementation */ int object_id; /* deprecated, do not use */ int configured; /* set when configuration ready */ };
typedef struct conf_object conf_object_t;
int SIM_initial_configuration_ok(void);
conf_object_t * SIM_new_object(conf_class_t *cls, const char *name);
void SIM_object_constructor(conf_object_t *obj, parse_object_t *pobj);
int SIM_object_is_processor(conf_object_t *obj);
void SIM_read_configuration(const char *file);
int SIM_register_attribute( conf_class_t *cls, const char *name, attr_value_t (*get_attr)(lang_void *user_data, conf_object_t *obj, attr_value_t *idx), lang_void *user_data_get, set_error_t (*set_attr)(lang_void *user_data, conf_object_t *obj, attr_value_t *val, attr_value_t *idx), lang_void *user_data_set, attr_attr_t attr, const char *desc);
int SIM_register_class_attribute( conf_class_t *cls, const char *name, attr_value_t (*get_attr)(lang_void *ptr, conf_class_t *c, attr_value_t *idx), lang_void *user_data_get, set_error_t (*set_attr)(lang_void *ptr, conf_class_t *c, attr_value_t *val, attr_value_t *idx), lang_void *user_data_set, attr_attr_t attr, const char *desc);
conf_class_t * SIM_register_class(const char *name, class_data_t *class_data);
class_data may be freed when the function has returned.
typedef enum { Sim_Class_Kind_Vanilla, /* object is saved at checkpoints */ Sim_Class_Kind_Session, /* object is saved as part of a * session only */ Sim_Class_Kind_Pseudo /* object is never saved */ } class_kind_t;
typedef struct class_data { conf_object_t *(*new_instance)(parse_object_t *parse_obj); int (*delete_instance)(conf_object_t *obj); void (*finalize_instance)(conf_object_t *obj); attr_value_t (*default_get_attr)(const char *name, conf_object_t *obj, attr_value_t *idx); set_error_t (*default_set_attr)(const char *name, conf_object_t *obj, attr_value_t *val, attr_value_t *idx); conf_class_t *parent; const char *description; class_kind_t kind; } class_data_t;
The new_instance function should return a newly allocated object. The object must begin with a conf_object_t structure which should be initialized with the object_constructor function.
delete_instance must be NULL if the class does not support object deletion.
Attribute If the class_data structure does not include a new_instance function.
void SIM_register_class_alias(const char *alias, const char *name);
Aliases are used to support compatibility with old class names if a class is renamed. They can also be used to allow different modules, which define different specific implementations of the same generic base class, to read the same configuration files.
int SIM_register_interface(conf_class_t *cls, const char *name, void *iface);
int SIM_register_port_interface(conf_class_t *cls, const char *name, void *iface, const char *portname, const char *desc);
SIM_register_port_interface() registers a port instance of an interface that must be looked up using SIM_get_port_interface. The port name may not be the same as any attribute name used by the class.
int SIM_register_typed_attribute( conf_class_t *cls, const char *name, attr_value_t (*get_attr)(lang_void *user_data, conf_object_t *obj, attr_value_t *idx), lang_void *user_data_get, set_error_t (*set_attr)(lang_void *user_data, conf_object_t *obj, attr_value_t *val, attr_value_t *idx), lang_void *user_data_set, attr_attr_t attr, const char *type, const char *idx_type, const char *desc);
int SIM_register_typed_class_attribute( conf_class_t *cls, const char *name, attr_value_t (*get_attr)(lang_void *ptr, conf_class_t *c, attr_value_t *idx), lang_void *user_data_get, set_error_t (*set_attr)(lang_void *ptr, conf_class_t *c, attr_value_t *val, attr_value_t *idx), lang_void *user_data_set, attr_attr_t attr, const char *type, const char *idx_type, const char *desc);
The function get_attr is called with the object and the supplied data in user_data_get as arguments, and returns the current value of the attribute. It may return a value of type Sim_Val_Invalid if the argument has no sensible value. Lists and other compound data structures should be allocated dynamically by get_attr. If get_attr is a null pointer, the attribute will be write-only.
After the initial configuration, set_attr may be called at any time to change the value of an attribute. Compound data structures should be copied if set_attr wants to keep them. If set_attr is a null pointer, the attribute will be read-only.
All attributes that are marked Sim_Attr_Required must be present in all configurations.
typedef enum { Sim_Attr_Required = 0, Sim_Attr_Optional = 1, Sim_Attr_Session = 3, Sim_Attr_Pseudo = 4, Sim_Attr_Flag_Mask = 0xff, Sim_Init_Phase_Shift = 8, Sim_Init_Phase_0 = 0 << Sim_Init_Phase_Shift, Sim_Init_Phase_1 = 1 << Sim_Init_Phase_Shift, Sim_Attr_Integer_Indexed = 0x1000, Sim_Attr_String_Indexed = 0x2000, Sim_Attr_List_Indexed = 0x4000, Sim_Attr_Persistent = 0x20000, /* set by SIM_register_*_attribute() */ Sim_Attr_Read_Only = 0x40000, Sim_Attr_Write_Only = 0x80000 } attr_attr_t;
To make the set_attr function easier to write, Simics provides a simple type system for attributes. You can provide typing information for both simple and indexed access to the attribute via the type and idx_type attributes (note that, in the latter case, you specify the type of the attribute for indexed access, not the type of the index). Setting either parameter to NULL will prevent typechecking for that access mode (normal or indexed).
A type is described by a string composed with the following rules:
set_error_t SIM_set_attribute(conf_object_t *obj, const char *name, attr_value_t *value);
set_error_t SIM_set_class_attribute(conf_class_t *cls, const char *name, attr_value_t *value);
set_error_t SIM_set_attribute_idx(conf_object_t *obj, const char *name, attr_value_t *index, attr_value_t *value);
set_error_t SIM_set_class_attribute_idx(conf_class_t *cls, const char *name, attr_value_t *index, attr_value_t *value);
The _idx version of the function can be used to get a single entry in a list or data attribute. For this to work, the attribute must support indexing.
void SIM_set_configuration(attr_value_t conf);
This function is an alternative to reading the configuration from a file. A configuration is an attr_value_t which should have the following structure.
(("name", "class", ("attr_name", attr_val) ... ), ... )
That is a list of object specifiers containing name, class, and a list of attribute specifiers. An attribute specifier is a list of length 2 containing the attribute name and its value. SIM_set_configuration() allows an easy way of parameterizing the configuration, especially if called from Python.
from configuration import *
SIM_set_configuration([
["cpu0", "x86",
["queue", OBJ("cpu0")],
["freq_mhz", 20],
["physical_memory", OBJ("phys_mem0")]],
["phys_mem0", "memory-space",
["map", [[0xa0000, OBJ("vga0"), 1, 0, 0x20000],
[0x00000, OBJ("mem0"), 0, 0x00000, 0xA0000],
[0xc0000, OBJ("mem0"), 0, 0xc0000, 0x8000],
[0xc8000, OBJ("setmem0"), 0, 0, 0x28000],
[0xf0000, OBJ("mem0"), 0, 0xf0000, 0x10000],
[0x100000, OBJ("mem0"), 0, 0x100000, 0x3ff00000],
[0xfee00000, OBJ("apic0"), 0, 0, 0x4000]]]],
... ])
int SIM_write_configuration_to_file(const char *file);
Classes that wish to create additional files can use the SIM_get_configuration_file_prefix call to get a suitable filename prefix.
void SIM_register_copyright(const char *str);
The string should contain only standard ASCII characters, be pre-formatted for at most 80-character width terminal, be non-indented, and have no spurious new-line characters before or after the last line (except for the new-line that marks the end of the last line).
The string will not be copied so needs to be either static or a copy generated by the callee (preferably static).
const char * SIM_version(void);
const char * SIM_version_sub(void);
const char * SIM_readme(void);
const char * SIM_snapshot_date(void);
void SIM_license(void);
void SIM_copyright(void);
sim_exception_t SIM_clear_exception(void);
SimExc_No_Exception if none available.
void SIM_command_has_problem(void);
void SIM_command_clear_problem(void);
int SIM_command_problem_status(void);
The current problem status can be queried with SIM_command_problem_status where a return value of zero means no problem. The status can be cleared by calling SIM_command_clear_problem(), allowing script files to continue executing.
void SIM_frontend_exception(sim_exception_t exc_type, const char *str);
The state of the pending exception can be read with SIM_get_pending_exception() and cleared with SIM_clear_exception().
sim_exception_t SIM_get_pending_exception(void);
const char * SIM_last_error(void);
int SIM_c_hap_occurred(hap_type_t hap, conf_object_t *obj, integer_t value, ...);
int SIM_c_hap_occurred_vararg(hap_type_t hap, conf_object_t *obj, integer_t value, va_list ap);
int SIM_c_hap_occurred_always(hap_type_t hap, conf_object_t *obj, integer_t value, ...);
int SIM_c_hap_occurred_always_vararg(hap_type_t hap, conf_object_t *obj, integer_t value, va_list ap);
SIM_hap_occurred() will only run callback functions for a specific hap once per simulated cycle. The SIM_hap_occurred_always() function will always run the callbacks.
The functions SIM_c_hap_occurred_vararg() and SIM_c_hap_occurred_always_vararg() are vararg versions of these functions.
attr_value_t SIM_get_all_hap_types(void);
hap_handle_t SIM_hap_add_callback(const char *hap, obj_hap_func_t func, typed_lang_void *user_data);
hap_handle_t SIM_hap_add_callback_index(const char *hap, obj_hap_func_t func, typed_lang_void *user_data, integer_t index);
hap_handle_t SIM_hap_add_callback_range(const char *hap, obj_hap_func_t func, typed_lang_void *user_data, integer_t start, integer_t end);
hap_handle_t SIM_hap_add_callback_obj(const char *hap, conf_object_t *obj, hap_flags_t flags, obj_hap_func_t func, typed_lang_void *user_data);
hap_handle_t SIM_hap_add_callback_obj_index(const char *hap, conf_object_t *obj, hap_flags_t flags, obj_hap_func_t func, typed_lang_void *user_data, integer_t index);
hap_handle_t SIM_hap_add_callback_obj_range(const char *hap, conf_object_t *obj, hap_flags_t flags, obj_hap_func_t func, typed_lang_void *user_data, integer_t start, integer_t end);
Some hap add functions also take a flags argument. This flag is currently Simics internal and should be set to 0.
The hap callback functions should not return any data. In C, the functions are declared to have a void return type and in Python, any return value is ignored. Since callback functions with different arguments may be installed using the same API function, the compiler may warn about a type mismatch. The solution is to cast the callback function pointer to the obj_hap_func_t type.
In hap functions, the execution can be interrupted by calling SIM_break_simulation. If a frontend or Python exception is raised, an error message will be printed incuding a stack trace if the callback is written in Python.
The _index_ and _range_ versions will install callbacks that only trigger for a specified index, or range of indices. The index is specific for each hap type, see the hap documentation.
typedef int hap_handle_t;
hap_type_t SIM_hap_add_type(const char *hap, const char *params, const char *param_desc, const char *index, const char *desc, int old_had_obj);
The params parameter specifies the argument that callbacks for this hap is called with, e.g., "s" or "II". The first two arguments are always lang_void * and conf_object_t * respectively, and should not be included in that string. The table below shows which characters may be used, and what their meaning is:
i | an int |
I | an integer_t (64 bit integer) |
e | an exception_type_t |
o | a script specific object; i.e., void * in C and any Python object in Python |
s | a string |
m | a memory transaction (generic_transaction_t * in C) |
c | a configuration object (conf_object_t * in C) |
v | a void *; a pointer to a C structure within Simics |
parm_desc should be a string of space-separated words describing these parameters, or NULL if params is the empty string.
index is a string describing the index value for this hap, or NULL if there is no index value.
Hap types that used to have a conf_object_t pointer as first argument (before all haps were associated with an object) should set the old_had_obj argument to 1. This tells Simics to call old-style callbacks with a conf_object_t argument although the hap doesn't include any 'c' first in the parameter list anymore. Old style callbacks are functions installed with the now obsolete SIM_hap_register_callback... and SIM_hap_install_callback... functions.
desc is a description string for the hap.
int SIM_hap_callback_exists(const char *hap, obj_hap_func_t func, typed_lang_void *user_data);
void SIM_hap_delete_callback(const char *hap, obj_hap_func_t func, typed_lang_void *user_data);
void SIM_hap_delete_callback_obj(const char *hap, conf_object_t *obj, obj_hap_func_t func, typed_lang_void *user_data);
void SIM_hap_delete_callback_id(const char *hap, hap_handle_t handle);
void SIM_hap_delete_callback_obj_id(const char *hap, conf_object_t *obj, hap_handle_t handle);
The SIM_hap_delete_callback_obj...() functions will remove a callback that is installed on the specified object obj.
SIM_hap_delete_callback() removes any callbacks with the callback function func and the same user_data. The SIM_hap_delete_callback_..._id() functions take a hap handle argument instead, as returned by the SIM_hap_add_callback...() functions.
These function will trigger the Core_Hap_Callback_Removed hap for each removed callback. NOTE: Callbacks registered to be called on Core_Hap_Callback_Removed, are not allowed to make recursive calls to remove or unregister any callbacks on the same hap.
const char * SIM_hap_get_name(hap_type_t hap);
hap_type_t SIM_hap_get_number(const char *hap);
int SIM_hap_is_active(hap_type_t hap);
int SIM_hap_occurred(hap_type_t hap, conf_object_t *obj, integer_t value, attr_value_t *list);
int SIM_hap_occurred_always(hap_type_t hap, conf_object_t *obj, integer_t value, attr_value_t *list);
SIM_hap_occurred() will only call the callbacks once in a simulated cycle; i.e., it is safe to call SIM_hap_occurred() and request the simulation to stop every time. The SIM_hap_occurred_always() function will always call the hap functions every time.
void SIM_hap_remove_type(const char *hap);
int SIM_get_quiet(void);
int SIM_get_verbose(void);
void SIM_log_constructor(log_object_t *log_obj, parse_object_t *parse_obj);
static void SIM_log_info(int lvl, log_object_t *dev, int grp, const char *str, ...);
static void SIM_log_error(log_object_t *dev, int grp, const char *str, ...);
static void SIM_log_undefined(int lvl, log_object_t *dev, int grp, const char *str, ...);
static void SIM_log_spec_violation(int lvl, log_object_t *dev, int grp, const char *str, ...);
static void SIM_log_target_error(int lvl, log_object_t *dev, int grp, const char *str, ...);
static void SIM_log_unimplemented(int lvl, log_object_t *dev, int grp, const char *str, ...);
void SIM_log_message(conf_object_t *obj, int level, int group_ids, log_type_t log_type, const char *message);
level should be between 1 and 4:
Messages of the Sim_Log_Error type are always printed on level 1. The group_ids should have a bit set for each log group that the message corresponds to, as defined by the SIM_log_register_groups(). The log_type argument is documented with the log_type_t type.
void SIM_log_register_groups(conf_class_t *cls, const char **names);
void SIM_set_quiet(int mode);
void SIM_set_verbose(int mode);
void SIM_for_all_memory_pages(void (*func)(integer_t addr), int i_or_d);
The callback func is passed the physical address of the first byte on the page. Each page is S_PSIZE bytes large.
If i_or_d is 0, then func is only applied to pages that have had code executed on them (i.e. intermediate code has been allocated at some time).
physical_address_t SIM_load_binary(conf_object_t *obj, const char *file, physical_address_t offset, int use_pa, int verbose);
The file will be loaded at the address formed by adding the virtual load address from the file, with the offset offset. If the flag use_pa is set, the ELF physical load address is used instead. The verbose flag will cause Simics to print info about the binary to the console.
The memory space to load into is given in the obj parameter. If the given space is a CPU object, its current virtual address space will be used, and addresses will be translated before writing to the physical memory space attached to the CPU.
If the file is not found in the current directory, the search path (see add-directory) is used to find the file.
void SIM_load_file(conf_object_t *obj, const char *file, physical_address_t base_address, int verbose);
physical_address_t SIM_logical_to_physical(conf_object_t *cpu, data_or_instr_t data_or_instr, logical_address_t vaddr);
uint8 SIM_read_byte(conf_object_t *obj, generic_address_t paddr);
void SIM_write_byte(conf_object_t *obj, generic_address_t paddr, uint8 value);
uinteger_t SIM_read_phys_memory(conf_object_t *cpu, physical_address_t paddr, int length);
Up to 8 bytes can be read in one call. The memory access will be of inquiry type, i.e. no timing-model or snoop device will be called.
uint64 SIM_read_phys_memory_tags(conf_object_t *mem_space, physical_address_t paddr, unsigned ntags);
void SIM_write_phys_memory_tags(conf_object_t *mem_space, physical_address_t paddr, uint64 tag_bits, unsigned ntags);
void SIM_write_phys_memory(conf_object_t *cpu, physical_address_t paddr, uinteger_t value, int length);
Up to 8 bytes can be written in one call. The memory access will be of inquiry type, i.e. no timing-model or snoop device will be called.
struct alpha_memory_transaction * SIM_alpha_mem_trans_from_generic(generic_transaction_t *mop);
struct arm_memory_transaction * SIM_arm_mem_trans_from_generic(generic_transaction_t *mop);
struct ia64_memory_transaction * SIM_ia64_mem_trans_from_generic(generic_transaction_t *mop);
struct mips_memory_transaction * SIM_mips_mem_trans_from_generic(generic_transaction_t *mop);
struct ppc_memory_transaction * SIM_ppc_mem_trans_from_generic(generic_transaction_t *mop);
struct v9_memory_transaction * SIM_v9_mem_trans_from_generic(generic_transaction_t *mop);
struct x86_memory_transaction * SIM_x86_mem_trans_from_generic(generic_transaction_t *mop);
struct pci_memory_transaction * SIM_pci_mem_trans_from_generic(generic_transaction_t *mop);
void SIM_c_get_mem_op_value_buf(generic_transaction_t *mop, char *dst);
attr_value_t SIM_get_mem_op_value_buf(generic_transaction_t *mop);
uinteger_t SIM_get_mem_op_value_cpu(generic_transaction_t *mop);
uinteger_t SIM_get_mem_op_value_le(generic_transaction_t *mop);
uinteger_t SIM_get_mem_op_value_be(generic_transaction_t *mop);
The SIM_c_get_mem_op_value_buf() function is only available from C/C++. It places the data into the buffer pointed to by dst. No endian conversion is performed, i.e. data is returned in target endianness. There is no alignment requirement on the dst parameter.
void SIM_c_set_mem_op_value_buf(generic_transaction_t *mop, char *src);
void SIM_set_mem_op_value_buf(generic_transaction_t *mop, attr_value_t value);
void SIM_set_mem_op_value_cpu(generic_transaction_t *mop, uinteger_t value);
void SIM_set_mem_op_value_le(generic_transaction_t *mop, uinteger_t value);
void SIM_set_mem_op_value_be(generic_transaction_t *mop, uinteger_t value);
SIM_c_set_mem_op_value_buf() is only available from C/C++, it operates on data in target endian order. There is no alignment requirement on the buf parameter.
SIM_set_mem_op_value_be() takes data in host endian order and sets it in big-endian.
SIM_set_mem_op_value_le() takes data in host endian order and sets it in little-endian.
SIM_set_mem_op_value_cpu() takes data in host endian order and sets it in the default endian order for the initiating processor.
FORCE_INLINE mem_op_type_t SIM_get_mem_op_type(const generic_transaction_t *NOTNULL mop);
const char * SIM_get_mem_op_type_name(mem_op_type_t type);
int SIM_get_unique_memory_transaction_id(conf_object_t *obj);
FORCE_INLINE int SIM_mem_op_is_control(const generic_transaction_t *NOTNULL mop);
FORCE_INLINE int SIM_mem_op_is_data(const generic_transaction_t *NOTNULL mop);
FORCE_INLINE int SIM_mem_op_is_instruction(const generic_transaction_t *NOTNULL mop);
FORCE_INLINE int SIM_mem_op_is_from_cache(const generic_transaction_t *NOTNULL mop);
FORCE_INLINE int SIM_mem_op_is_from_cpu(const generic_transaction_t *NOTNULL mop);
FORCE_INLINE int SIM_mem_op_is_from_cpu_arch(const generic_transaction_t *NOTNULL mop, ini_type_t arch);
FORCE_INLINE int SIM_mem_op_is_from_device(const generic_transaction_t *NOTNULL mop);
FORCE_INLINE int SIM_mem_op_is_prefetch(const generic_transaction_t *NOTNULL mop);
FORCE_INLINE int SIM_mem_op_is_read(const generic_transaction_t *NOTNULL mop);
FORCE_INLINE int SIM_mem_op_is_write(const generic_transaction_t *NOTNULL mop);
FORCE_INLINE void SIM_set_mem_op_type(generic_transaction_t *NOTNULL mop, mem_op_type_t type);
attr_value_t SIM_get_all_failed_modules(void);
attr_value_t SIM_get_all_modules(void);
void SIM_load_module(const char *module);
void SIM_unload_module(const char *module);
Modules should be placed in the simics lib directory or in a directory present in the SIMICS_EXTRA_LIB environment variable.
void SIM_module_list_refresh(void);
void SIM_add_output_handler(output_handler_t func, lang_void *user_data);
This is the definition of output_handler_t:
typedef void (*output_handler_t)(lang_void *data, const char *src, size_t length);
void SIM_remove_output_handler(output_handler_t func, typed_lang_void *user_data);
int SIM_write(const void *src, int length);
int SIM_flush(void);
int SIM_putchar(int c);
int SIM_puts(const char *s);
int SIM_printf(const char *format, ...);
int SIM_printf_vararg(const char *format, va_list ap);
The output will be sent to stdout, but more output recipients can be added using the SIM_add_output_handler() function. Output is line buffered. SIM_flush() will force output of an unterminated line.
By default, simics_api.h will define a number of macros, changing calls to the abovementioned C library functions to call the Simics versions instead:
#undef printf
#if defined(HAVE_VARARG_MACROS)
#define printf(...) SIM_printf(__VA_ARGS__)
#else
#define printf SIM_printf
#endif
#undef vprintf
#define vprintf(str, ap) SIM_printf_vararg(str, ap)
#undef puts
#define puts(str) SIM_puts(str)
#undef putchar
#define putchar(c) SIM_putchar(c)
#undef fwrite
#define fwrite(ptr, size, nmemb, stream) \
((stream) == stdout \
? (size_t)SIM_write((ptr), (size) * (nmemb)) \
: fwrite(ptr, size, nmemb, stream))
#undef fputs
#define fputs(str, stream) \
((stream) == stdout \
? SIM_write((str), strlen(str)) \
: fputs((str), (stream)))
#undef fflush
#define fflush(stream) ((stream) == stdout ? SIM_flush() : fflush(stream))
This behavior can be overridden, see the information about the SIM_BC_NO_STDOUT_REDEFINE macro in section 3.4.1.
void SIM_add_directory(const char *directory, int prepend);
The directory argument is first converted using SIM_native_path, to yield a path on host native form. If the path does not exist, a warning is printed and the path is ignored.
If prepend is set, the directory is inserted first in the list of directories.
This list of directories is saved as the attribute simics-path when doing write-configuration. Each directory is first converted to absolute form if relative.
This function replaces the obsolete function SIM_set_simics_path().
void SIM_clear_directories(void);
attr_value_t SIM_get_directories(void);
const char * SIM_lookup_file(const char *file);
The returned path will always be in host native format, so the returned path will not need to be converted. See SIM_native_path for more details on what "host native format" means.
The search algorithm is as follows.
If the function fails, NULL is returned.
If the file was found, a pointer to the full path to the file is returned. The returned string should not be modified.
char * SIM_native_path(const char *path);
On Windows, this function translates Cygwin style paths into Windows native form. This is implemented internally, the cygpath utility is not invoked. If the path contains a colon (:) or a backslash, the path is assumed to be on native form already, and no translation will be performed.
Translating a Cygwin paths is done by looking up Cygwin mount prefixes in the registry, and replacing any matching prefixes with their native counterpart. Also, Cygwin symlinks are resolved and followed. Finally, any slashes in the path is converted to backslash. The path is not normalized, i.e. the resulting path may contain "..".
Note: the symlink lookup mechanism does not handle the case when nowinsymlink is set in the CYGWIN environment-variable.
The function uses a static buffer to store its result, which will be overwritten at the next call.
conf_object_t * SIM_current_processor(void);
tuple_int_string_t * SIM_disassemble(conf_object_t *cpu, generic_address_t addr, int type);
typedef struct { int integer; const char *string; } tuple_int_string_t;For the Sparc, Alpha, and PowerPC targets the length is always 4 bytes. On IA-64, the length is undefined.
void SIM_enable_processor(conf_object_t *cpu);
void SIM_disable_processor(conf_object_t *cpu);
This function can not be called during the execution of an instruction, for example, in a device or a timing-model. If you wish to call them in these situations, use SIM_stacked_post() to post a callback that will be run as soon as possible after the instruction finished.
attr_value_t SIM_get_all_processors(void);
attr_value_t SIM_get_all_registers(conf_object_t *cpu);
const char * SIM_get_exception_name(conf_object_t *cpu, int exc);
int SIM_get_exception_number(conf_object_t *cpu, const char *name);
attr_value_t SIM_get_all_exceptions(conf_object_t *cpu);
conf_object_t * SIM_get_processor(int proc_no);
int SIM_get_processor_number(const conf_object_t *cpu);
logical_address_t SIM_get_program_counter(conf_object_t *cpu);
void SIM_set_program_counter(conf_object_t *cpu, logical_address_t pc);
The actual registers that are read/written depend on the target architecture. For example on the x86-64 architecture the program counter is the RIP register and the stack pointer is the RSP register.
For IA-64, the program counter is the ip register, with the current slot number added to the lowest two bits of the address.
int SIM_get_register_number(conf_object_t *cpu, const char *name);
const char * SIM_get_register_name(conf_object_t *cpu, int reg);
int SIM_number_processors(void);
int SIM_processor_enabled(conf_object_t *cpu);
int SIM_processor_privilege_level(conf_object_t *cpu);
uinteger_t SIM_read_register(conf_object_t *cpu, int reg);
For the ARM target, this function returns the value of the register in the bank corresponding to the current mode. To access copies of the register in other banks, use the read_register_mode function in the arm interface.
void SIM_register_arch_decoder(decoder_t *decoder, const char *arch, int arch_mode);
void SIM_unregister_arch_decoder(decoder_t *decoder, const char *arch, int arch_mode);
SIM_unregister_arch_decoder unregisters decoders registered with SIM_register_arch_decoder. SIM_unregister_arch_decoder must not be called while an instruction is executing. This is the case the decode and service routine functions of instruction decoders, in the operate function of the timing-model interface, and in the operation function of the io-memory interface. It is also the case for callbacks for some haps. In these cases, post an event using SIM_stacked_post and unregister the decoder from the event handler.
When Simics decodes an instruction, it will first see if any instruction decoders are registered for the current architecture. For any decoders it finds, Simics will let it try to decode the instruction. The decoders are called in order, starting with the last registered decoder, and if one decoder accepts the instruction, the rest of the decoders will not be called.
When a decoder accepts an instruction, it creates a structure describing the decoded instruction, including a pointer to a function that Simics will call each time the instruction is executed.
decoder is the decoder to register
arch is the target architecture that the decoder can decode instruction for. It is matched against the architecture attribute on CPU objects to determine whether the decoder applies. It can also be given as NULL, which means that the decoders will be used for all CPU architectures. The simplest way to find the value to use is to load a configuration into Simics and check the value of the architecture attribute in the CPU object.
arch_mode is the instruction mode of the architecture. This should always be 0.
The decoder_t type is a structure providing the functions used to invoke the decoder.
typedef struct { void *user_data; int (*NOTNULL decode)(unsigned char *code, int valid_bytes, conf_object_t *cpu, instruction_info_t *ii, void *user_data); int (*NOTNULL disassemble)(unsigned char *code, int valid_bytes, conf_object_t *cpu, char *buffer, void *user_data); int (*NOTNULL flush)(conf_object_t *cpu, instruction_info_t *ii, void *user_data); } decoder_t;
The decode function is called to decode an instruction pointed to by code. The first byte represents the lowest address of the instruction in the simulated memory. valid_bytes tells how many bytes can be read. The current CPU is given in the cpu parameter. When the decoder has successfully decoded the instruction, it fills in the ii structure, and returns the number of bytes used in the decoding. If it does not apply to the given instruction, it should return zero. If the decoder needs more data it should return a negative number corresponding to the total number of bytes needed. Simics will then call the decoder again with more available bytes. This process is repeated until the decoder accepts or rejects the instruction.
Note that in a shared memory multiprocessor, the cpu used in decoding may differ from the CPU that executes the instruction, since the decoded instructions are cached by Simics.
The disassemble function is called to disassemble an instruction. It uses the same code, valid_bytes, and cpu parameters as the decode function. In addition, it takes a pointer to a string buffer, buffer. The disassembly should be written to this buffer as a null-terminated string with a maximum length of 256 characters, including the null terminator. The return value is handled identically to the that of the decode function.
The flush function is called to free any memory allocated when decoding an instruction, including the register info array. Just like the other functions, it should return zero if it doesn't recognize the instruction, and non-zero if it has handled it. Usually, the way to recognize if a decoded instruction is the right one is to compare ii->ii_ServiceRoutine with what is set in the decode function. Note that the cpu parameter is the processor that caused the flush. It is more or less an arbitrary processor and should be ignored.
In addition to the function pointers, the structure contains a user_data pointer that is passed to all the functions. This can be used for passing any data to the decoder functions.
The instruction_info_t is defined like this.
typedef struct instruction_info { service_routine_t ii_ServiceRoutine; unsigned int ii_Arg; unsigned int ii_Type; reg_info_t *ii_RegInfo; lang_void *ii_UserData; logical_address_t ii_LogicalAddress; physical_address_t ii_PhysicalAddress; } instruction_info_t;
ii_ServiceRoutine is a pointer to a service routine to be called by Simics every time the instruction is executed. It has the following prototype:
typedef exception_type_t (*service_routine_t)(conf_object_t *cpu, unsigned int arg, lang_void *user_data);
ii_Arg is the argument that will be passed on to the service routine. It typically contains a bit-field of parameters to the instruction such as register numbers or intermediate values. It can also be a pointer to a structure if more appropriate.
ii_Type is either UD_IT_SEQUENTIAL or UD_IT_CONTROL_FLOW. A sequential type means that the instruction does not perform any branches and the update of the program counter(s) is handled by Simics. In a control flow instruction on the other hand it is up to the user to set the program counter(s).
ii_RegInfo should be used if Simics is running in out of order mode. An array of reg_info_t should be allocated that describes the registers the instruction uses and if they are used as input and/or output. The array should be terminated with a dummy register (id equal to 0) which is neither input nor output (in and out both zero).
struct reg_info { register_type_t type; /* register type */ register_id_t id; /* register id */ unsigned input:1; /* used as input */ unsigned output:1; /* used as output */ };
typedef struct reg_info reg_info_t;
The register_id of the PC(s) should not be filled in, Simics handles that automatically. If the instruction manipulates a register not listed the value Sim_RI_Sync should be used, this will disallow the instruction to run out of order.
The array needs to be deallocated when the instruction is flushed, see below.
ii_UserData can be filled in with other data.
The service routine function should return an exception when it is finished to signal its status. If no exception occurs Sim_PE_No_Exception should be returned.
See exception_type_t in core/types.h for the different exceptions available.
A special return value, Sim_PE_Default_Semantics, can be returned; this signals Simics to run the default semantics for the instruction. This is useful if the semantics of an instruction should be changed but the user routine does not want to handle it all the time.
IllegalValue Thrown if the decoder doesn't have all function pointers set.
void SIM_register_decoder(user_decoder_t decoder);
void SIM_unregister_decoder(user_decoder_t decoder);
SIM_register_decoder makes it possible to install user decoders in Simics. This gives the user an interface to the instruction set allowing changes to the instructions semantics, adding new instructions or removing implemented ones.
When simics decodes an instructions it will first see if any user decoder is supplied and in that case call it first. Several decoders can be installed and Simics will call them in the reverse order they were registered; i.e., the last one first. Every decoder has the option of either accepting the opcode given or pass it on to the next decoder.
If a decoder accepts the instruction it fills in an information structure which contains a function pointer that Simics will call each time the instruction should be executed.
user_decoder is the decoder to register, it is defined like this:
typedef int (*NOTNULL user_decoder_t)(unsigned char *code, int valid_bytes, conf_object_t *cpu, instruction_info_t *ii, int action, char *string_buffer);
code is a pointer to the instruction to decode. The first byte represents the lowest address of the instruction in the simulated memory. valid_bytes tells how many bytes can be read. If the decoder needs more data it should return a negative number corresponding to the total number of bytes needed. Simics will then call the decoder again with more available bytes. This process is repeated until the decoder accepts or rejects the instruction. If the instruction is accepted its length in bytes should be returned, otherwise zero.
cpu is the cpu decoding the instruction. Note that in a shared memory multiprocessor, this may differ from the one executing the instruction since decoded instructions are cached.
action is whether Simics wants to decode, disassemble or flush a previously decoded instruction. For decoding, the value is UD_ACTION_DECODE and the instruction_info_t structure ii should be filled in. The structure has the following fields:
typedef struct instruction_info { service_routine_t ii_ServiceRoutine; unsigned int ii_Arg; unsigned int ii_Type; reg_info_t *ii_RegInfo; lang_void *ii_UserData; logical_address_t ii_LogicalAddress; physical_address_t ii_PhysicalAddress; } instruction_info_t;
ii_ServiceRoutine is a pointer to a service routine to be called by Simics every time the instruction is executed. It has the following prototype:
typedef exception_type_t (*service_routine_t)(conf_object_t *cpu, unsigned int arg, lang_void *user_data);
ii_Arg is the argument that will be passed on to the service routine. It typically contains a bit-field of parameters to the instruction such as register numbers or intermediate values. It can also be a pointer to a structure if more appropriate.
ii_Type is either UD_IT_SEQUENTIAL or UD_IT_CONTROL_FLOW. A sequential type means that the instruction does not perform any branches and the update of the program counter(s) is handled by Simics. In a control flow instruction on the other hand it is up to the user to set the program counter(s).
ii_RegInfo should be used if Simics is running in out of order mode. An array of reg_info_t should be allocated that describes the registers the instruction uses and if they are used as input and/or output. The array should be terminated with a dummy register (id equal to 0) which is neither input nor output (in and out both zero).
struct reg_info { register_type_t type; /* register type */ register_id_t id; /* register id */ unsigned input:1; /* used as input */ unsigned output:1; /* used as output */ };
typedef struct reg_info reg_info_t;
The register_id of the PC(s) should not be filled in, Simics handles that automatically. If the instruction manipulates a register not listed the value Sim_RI_Sync should be used, this will disallow the instruction to run out of order.
The array needs to be deallocated when the instruction is flushed, see below.
ii_UserData can be filled in with other data.
The service routine function should return an exception when it is finished to signal its status. If no exception occurs Sim_PE_No_Exception should be returned.
See exception_type_t in core/types.h for the different exceptions available.
A special return value, Sim_PE_Default_Semantics, can be returned; this signals Simics to run the default semantics for the instruction. This is useful if the semantics of an instruction should be changed but the user routine does not want to handle it all the time.
If Simics wants to disassemble the instruction the action value will be UD_ACTION_DISASS and the string_buffer should be filled with the disassembled instruction (max length is 256 characters). The ii structure should be ignored.
A value of UD_ACTION_FLUSH (code and string_buffer will be null, valid_bytes zero) means that Simics wants to flush a cached decoded instruction. The instruction_info_t structure ii will then hold the values previously stored there. If the user-decoder recognizes the ii->ii_ServiceRoutine function as its own it should now free all allocated user data including the register info array, if allocated, and return a non-zero value to indicate success. Otherwise zero should be returned letting other user-decoders have a shot.
Use SIM_unregister_decoder to remove a user-decoder.
void SIM_reset_processor(conf_object_t *cpu, int hard_reset);
void SIM_write_register(conf_object_t *cpu, int reg, uinteger_t value);
For the ARM target, this function sets the value of the register in the bank corresponding to the current mode. To access copies of the register in other banks, use the write_register_mode function in the arm interface.
FORCE_INLINE uint64 SIM_iter_next(addr_prof_iter_t *iter);
FORCE_INLINE generic_address_t SIM_iter_addr(addr_prof_iter_t *iter);
FORCE_INLINE void SIM_iter_free(addr_prof_iter_t *iter);
EXPERIMENTAL. While this functionality is expected to be retained in future releases, the interface is likely to change.
An address profile iterator visits some of the counters of an address profiler in some order. It is obtained from the iter function of the address_profiler interface.
SIM_iter_next advances the address profile iterator iter to the next nonzero counter and returns the count. It will return 0 when there are no more counters to visit. Note that the order in which the counters are visited is unspecified.
SIM_iter_addr returns the address of the counter returned by the most recent call to iter_next.
When you are done with the iterator, deallocate it with SIM_iter_free.
void SIM_break_message(const char *msg);
This is similar to SIM_break_simulation, with the difference that it doesn't actually break the simulation. It can be used by code that wants to display a break message and stop the simulation by some other means.
void SIM_break_simulation(const char *msg);
Simics will normally stop before the next instruction is executed. If this function is called when an instruction has started executing, and the instruction can be aborted, it will rewind to before the instruction. This might leave the simulation is a state where some repeatable part of the instruction is already executed.
pc_step_t SIM_continue(integer_t steps);
The function may return before completing steps steps if a breakpoint is reached, user code requests the simulation to be interrupted, or execution is interrupted via the user interface. In such cases the current CPU may have changed (see SIM_current_processor()) since Simics may have been executing in another processor's time quantum.
If steps is 0, Simics will run forever or until it is interrupted as described above.
If this function is called from a context where simulation cannot continue, e.g., from a callback function passed to SIM_post_command(), SIM_continue() will return immediately with return value 0 but the simulation will not be started until the calling function has exited. If this is the case, any exceptions returned from the simulation core will be discarded but the return value from the simulation can be read as an argument to the Core_Simulation_Stopped hap. You can query whether the current state will result in such a postponed continuation by calling the SIM_postponing_continue() function.
int SIM_postponing_continue(void);
int SIM_simics_is_running(void);
int SIM_cancel_realtime_event(integer_t id);
Returns 0 if the callback existed and was cancelled, or -1 if no callback with that identifier existed. (No exception is raised.)
void SIM_notify_on_socket(int sock, notify_mode_t mode, int run_in_thread, void (*callback)(lang_void *data), lang_void *data);
void SIM_notify_on_object(HANDLE obj, int run_in_thread, void (*callback)(lang_void *data), lang_void *data);
void SIM_notify_on_descriptor(int fd, notify_mode_t mode, int run_in_thread, void (*callback)(lang_void *data), lang_void *data);
If run_in_thread is nonzero, the callback function may be run in a thread where it cannot access or call anything in Simics except for these functions and SIM_thread_safe_callback. If run_in_thread is zero, the callback function is always run in the main thread. This may incur a small penalty in latency (time between the occurrence of the host event and execution of callback).
Notification on a specific event will be blocked during the execution of its callback function.
SIM_notify_on_socket will call a registered callback depending on mode:
mode | condition |
Sim_NM_Read | Socket is readable, closed, or incoming connection accepted |
Sim_NM_Write | Socket is writeable, or outgoing connection has completed |
Unix only: SIM_notify_on_descriptor will call a registered callback depending on mode for a given file descriptor in a way similar to SIM_notify_on_socket.
Windows only: SIM_notify_on_object will call a registered callback when object (which must be a waitable object) is in signalled state. The signalling object is modified in the same way as the Windows wait functions (WaitForMultipleObjects etc).
integer_t SIM_realtime_event(unsigned delay, void (*callback)(lang_void *data), lang_void *data, int run_in_thread, const char *desc);
If run_in_thread is nonzero, the callback may be run in a thread where it cannot access or call anything in Simics except for SIM_thread_safe_callback. If run_in_thread is zero, the callback function is always run in the main thread. This may cause the call to occur slightly later than requested, depending on what Simics is doing at the time.
The desc parameter is only present for debugging and has no other effect; it should be a static string describing the callback but may also be left NULL if desired.
The callback is only called once.
The return value is a non-zero identifier that can be used to cancel the callback using SIM_cancel_realtime_event.
void SIM_thread_safe_callback(void (*f)(lang_void *data), lang_void *data);
void SIM_STC_flush_cache(conf_object_t *cpu);
void SIM_flush_I_STC_logical(conf_object_t *cpu, logical_address_t vaddr, logical_address_t length);
void SIM_flush_D_STC_logical(conf_object_t *cpu, logical_address_t vaddr, logical_address_t length);
void SIM_flush_I_STC_physical(conf_object_t *cpu, physical_address_t paddr, physical_address_t length);
void SIM_flush_D_STC_physical(conf_object_t *cpu, physical_address_t paddr, physical_address_t length, read_or_write_t read_or_write);
SIM_STC_flush_cache() flushes the entire contents of the STCs (both instruction and data) from the specified cpu.
The SIM_flush_xxx functions removes specified memory ranges in the instruction or data STC. The address range is either the logical or the physical address. The read_or_write parameter specifies whether the read or the write D-STC should be flushed. If the function doesn't have such a parameter, both read and write D-STCs are flushed. The flushed address range is at least [ vaddr ... (vaddr + length − 1) ], but may be larger. SIM_flush_D_STC_logical() currently always flushes an entire page.
void SIM_flush_all_caches(void);
void SIM_release_stall(conf_object_t *obj, int id);
This function changes the stalling period for a memory transaction with id id on CPU cpu to zero. This means that the memory transaction may be issued the second time in the next cycle.
cycles_t SIM_stall_count(conf_object_t *obj);
void SIM_stall_cycle(conf_object_t *obj, cycles_t cycles);
void SIM_stall(conf_object_t *obj, double seconds);
SIM_stall does the same thing as SIM_stall_cycle but the stall time is given in seconds.
cycles_t SIM_stalled_until(conf_object_t *obj);
cycles_t SIM_cycle_count(conf_object_t *obj);
double SIM_time(conf_object_t *obj);
SIM_time returns current time at obj. Time is counted in seconds and has a maximum resolution of one clock cycle.
conf_object_t* SIM_next_queue(conf_object_t *obj);
void SIM_stacked_post(conf_object_t *obj, event_handler_t func, lang_void *user_data);
Time is undefined when the function is called. If several functions are registered this way before any of them has had a chance to run, the last registered will run first.
This call is mainly useful for actions that for various reasons cannot be done inside an instruction.
void SIM_step_clean(conf_object_t *obj, event_handler_t func, typed_lang_void *user_data);
pc_step_t SIM_step_count(conf_object_t *obj);
pc_step_t SIM_step_next_occurrence(conf_object_t *obj, event_handler_t func, typed_lang_void *user_data);
void SIM_step_post(conf_object_t *obj, pc_step_t steps, event_handler_t func, lang_void *user_data);
void SIM_time_clean(conf_object_t *obj, sync_t sync, event_handler_t func, typed_lang_void *user_data);
cycles_t SIM_time_next_occurrence(conf_object_t *obj, event_handler_t func, typed_lang_void *user_data);
void SIM_time_post(conf_object_t *obj, double seconds, sync_t sync, event_handler_t func, lang_void *user_data);
void SIM_time_post_cycle(conf_object_t *obj, cycles_t cycles, sync_t sync, event_handler_t func, lang_void *user_data);
typedef enum { Sim_Sync_Processor = 0, /* Sim_Sync_Node = 1, not supported yet */ Sim_Sync_Machine = 2 } sync_t;
If sync is set to Sim_Sync_Machine, all other objects will have the same local time when the event occurs. This requires that the delta is larger than the simulation time quantum if the simulation is not currently synchronized. If the delta is smaller than the quantum and time is not synchronized, it will be set to the quantum before the event is inserted.
SIM_time_post_cycle does the same as SIM_time_post but time is specified as a number of clock cycles, not in seconds. zero cycles is not rounded up to one cycle. Note that the clock cycle length is typically set in the simics configuration and may differ between processors.
SIM_time_next_occurrence finds first event in the time queue associated with obj that matches func and user_data. If the user_data argument is NULL, it will match any parameter. Returns the time to occurrence + 1, or zero if there is no match.
SIM_time_clean removes all events in objs associated time queue that matches func and user_data. If user_data is NULL, it will match any parameter, thus removing all functions that match regardless of the argument to func. Note that the older version of SIM_time_clean() without the sync parameter is deprecated since Simics 1.6.
SIM_cycle_count returns current simulated clock cycle count at obj. Note that if processors are running at different frequency, the number will differ between processors, regardless of simulation quantum effects.
SIM_time returns current time at obj. Time is counted in seconds and has a maximum resolution of a clock cycle.
SIM_stall_cycle set the stall time at obj. cycle is the number of clock cycles the processor will stall. A call to this function will overwrite the current time left to stall at obj. No compensation is made if time differs between obj and where the function is called from.
SIM_stall does the same thing as SIM_stall_cycle but the stall time is given in seconds.
SIM_stalled_until returns how may more cycles the processor will stall.
SIM_stall_count returns the total number of cycles the processor has been stalled.
int SIM_get_batch_mode(void);
int SIM_is_interactive(void);
void SIM_post_command(void (*f)(lang_void *data), lang_void *data);
Note that the simulation will be stopped when f returns, but any call to SIM_continue() from within f will cause the simulation to restart immediately after.
void SIM_quit(int exit_code);
void SIM_run_command_file(const char *file);
This function is functionally equivalent to the -x command line option.
void SIM_set_prompt(const char *new_prompt);
void SIM_source_python(const char *file);
void SIM_source_python_in_module(const char *file, const char *module);
The PCI Device API is a set of functions that simplifies the work of writing PCI devices in Simics. The functions are implemented in the file src/devices/pci-device/pci-device.c. This file has to be included as a source file in modules using the API. The Simics User Guide contain descriptions of PCI in Simics, and how to write own PCI devices.
void PCIE_send_message(pci_device_t *pci, pcie_message_type_t type, byte_string_t payload);
The pcie_message_type_t has the following definition:
typedef enum { /* 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_Locked_Transaction = 0x00, /* Slot Power Limit */ PCIE_Set_Slot_Power_Limit = 0x90, /* 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_message_type_t;
void PCI_add_config_register(pci_device_t *pci, uint32 offset, const char *name, int size, uint32 mask, uint32 initial_value);
The newly created config register will contain initial_value.
exception_type_t PCI_bridge_default_access_not_taken( conf_object_t *obj, conf_object_t *src_space, conf_object_t *dst_space, exception_type_t ex, generic_transaction_t *mem_op, map_info_t mapinfo);
static void PCI_bridge_default_interrupt_lowered(conf_object_t *obj, conf_object_t *irq_obj, int dev, int pin);
static void PCI_bridge_default_interrupt_raised(conf_object_t *obj, conf_object_t *irq_obj, int dev, int pin);
void PCI_bridge_default_system_error(conf_object_t *obj);
void PCI_bridge_init(pci_device_t *pci, void (*system_error)(conf_object_t *obj), exception_type_t (*access_not_taken)( conf_object_t *obj, conf_object_t *src_space, conf_object_t *dst_space, exception_type_t ex, generic_transaction_t *mem_op, map_info_t mapinfo), void (*interrupt_raised)( conf_object_t *obj, conf_object_t *dev_obj, int device, int pin), void (*interrupt_lowered)( conf_object_t *obj, conf_object_t *dev_obj, int device, int pin), int forward_io, int forward_io32, int forward_mem, int forward_prefetchable, int forward_prefetchable64);
void PCI_bridge_map_setup( pci_device_t *pci, int io_down_priority, int io_down_align_size, int io_down_endian, int mem_down_priority, int mem_down_align_size, int mem_down_endian, int pref_down_priority, int pref_down_align_size, int pref_down_endian, int io_up_priority, int io_up_align_size, int io_up_endian, int mem_up_priority, int mem_up_align_size, int mem_up_endian);
const char * PCI_config_register_name(pci_device_t *pci, uint32 offset);
uint32 PCI_config_register_size(pci_device_t *pci, uint32 offset);
exception_type_t PCI_configuration_access(pci_device_t *pci, generic_transaction_t *mop);
exception_type_t PCI_data_from_memory(pci_device_t *pci, addr_space_t space, uint8 *buffer, uint64 address, uint64 size);
exception_type_t PCI_data_to_memory(pci_device_t *pci, addr_space_t space, uint8 *buffer, uint64 address, uint64 size);
uint32 PCI_default_configuration_read_access(conf_object_t *obj, uint32 offset, uint32 size);
void PCI_default_configuration_write_access(conf_object_t *obj, uint32 offset, uint32 size, uint32 value);
void PCI_default_device_reset(conf_object_t *obj);
void PCI_device_init(log_object_t *log, int log_group, pci_device_t *pci, pci_device_t *(*unused)(conf_object_t *), /* call with NULL */ void (*pci_bus_reset)(conf_object_t *obj), uint32 (*conf_read_func)(conf_object_t *obj, uint32 offset, uint32 size), void (*conf_write_func)(conf_object_t *obj, uint32 offset, uint32 size, uint32 value), exception_type_t (*pci_operation)( conf_object_t *obj, generic_transaction_t *mem_op, map_info_t map_info));
The generic PCI device code will use the object_data field of the conf_object_t struct, it should not be modified by the code implementing a specific device.
int PCI_get_bus_address(pci_device_t *pci);
uint32 PCI_get_config_register_mask(pci_device_t *pci, uint32 offset);
void PCI_handle_mapping32(pci_device_t *pci, int reg, addr_space_t space, uint32 size, int function, int priority, uint64 target_offset, conf_object_t *target, int alignment, int inverse_endian);
void PCI_handle_mapping64(pci_device_t *pci, int reg, uint64 size, int function, int priority, uint64 target_offset, conf_object_t *target, int alignment, int inverse_endian);
The space argument specifies if the memory or I/O space is used. The size argument is the size of the memory mappings, and function a function number used to identify the mapping. The priority should be 0, unless the device can have mappings that overlap, in that case each mapping must have unique priority. By default the device itself is mapped at the base address, but in some cases another object should be the target. In that case, the target argument can be set, and target_offset to the byte offset into the target. It is also possible to set an alignment boundary size, and an inverse endian flags. These are documented with the map attribute in the memory-space class.
There are also functions in the PCI Device API that can be used to modify the mapping in run-time. This is not needed for standard PCI devices.
void PCI_raise_interrupt(pci_device_t *pci);
void PCI_lower_interrupt(pci_device_t *pci);
void PCI_raise_interrupt_pin(pci_device_t *pci, int pin);
void PCI_lower_interrupt_pin(pci_device_t *pci, int pin);
uint32 PCI_read_sized_config_register(pci_device_t *pci, uint32 offset, uint32 size);
uint32 PCI_read_config_register(pci_device_t *pci, uint32 offset);
void PCI_write_config_register(pci_device_t *pci, uint32 offset, uint32 value);
void PCI_register_bridge_attributes(conf_class_t *pci_class);
void PCI_register_device_attributes( conf_class_t *pci_class, int (*interrupt_ack)(conf_object_t *obj), void (*special_cycle)(conf_object_t *obj, uint32 value), void (*system_error)(conf_object_t *obj), void (*interrupt_raised)(conf_object_t *obj, int pin), void (*interrupt_lowered)(conf_object_t *obj, int pin));
void PCI_set_config_register_mask(pci_device_t *pci, uint32 offset, uint32 mask);
void PCI_set_map_base(pci_device_t *pci, int reg, uint64 base);
uint64 PCI_get_map_base(pci_device_t *pci, int reg);
void PCI_set_map_size(pci_device_t *pci, int reg, uint64 size);
uint64 PCI_get_map_size(pci_device_t *pci, int reg);
void PCI_set_map_enable(pci_device_t *pci, int reg, int enable);
int PCI_get_map_enable(pci_device_t *pci, int reg);
void PCI_set_map_offset(pci_device_t *pci, int reg, uint64 target_offset);
uint64 PCI_get_map_offset(pci_device_t *pci, int reg);
void PCI_set_map_ignore_command(pci_device_t *pci, int reg, int map_ignore_command);
int PCI_get_map_ignore_command(pci_device_t *pci, int reg);
void PCI_set_map_always_on(pci_device_t *pci, int reg, int always_on);
int PCI_get_map_always_on(pci_device_t *pci, int reg);
void PCI_set_may_stall(pci_device_t *pci, int may_stall);
int PCI_get_may_stall(pci_device_t *pci);
void PCI_system_error(pci_device_t *pci);
uint64 PCI_value_from_memory(pci_device_t *pci, addr_space_t space, exception_type_t *ex, uint64 address, uint32 size);
exception_type_t PCI_value_to_memory(pci_device_t *pci, addr_space_t space, uint64 value, uint64 address, uint32 size);
void PCI_write_sized_config_register(pci_device_t *pci, uint32 offset, uint32 value, uint32 size);
The Micro-Architecture Interface is described in the Simics MAI Guide.
instruction_id_t SIM_instruction_begin(conf_object_t *obj);
instruction_error_t SIM_instruction_end(instruction_id_t ii);
void SIM_instruction_insert(instruction_id_t parent_ii, instruction_id_t ii);
instruction_id_t SIM_instruction_child(instruction_id_t ii, int n);
instruction_id_t SIM_instruction_parent(instruction_id_t ii);
conf_object_t * SIM_instruction_cpu(instruction_id_t ii) /* */ instruction_error_t SIM_instruction_proceed(instruction_id_t ii);
instruction_error_t SIM_instruction_proceed(instruction_id_t ii);
instruction_error_t SIM_instruction_fetch(instruction_id_t ii);
instruction_error_t SIM_instruction_decode(instruction_id_t ii);
instruction_error_t SIM_instruction_execute(instruction_id_t ii);
instruction_error_t SIM_instruction_retire(instruction_id_t ii);
instruction_error_t SIM_instruction_commit(instruction_id_t ii);
instruction_error_t SIM_instruction_squash(instruction_id_t ii);
instruction_error_t SIM_instruction_rewind(instruction_id_t ii, instruction_phase_t phase) /* */ instruction_error_t SIM_instruction_handle_exception(instruction_id_t ii);
instruction_error_t SIM_instruction_handle_exception(instruction_id_t ii);
instruction_error_t SIM_instruction_handle_interrupt(conf_object_t *cpu, exception_type_t vector);
instruction_id_t SIM_instruction_nth_id(int n);
void SIM_instruction_set_stop_phase(conf_object_t *obj, instruction_phase_t phase, int on);
instruction_phase_t SIM_instruction_phase(instruction_id_t ii);
int SIM_instruction_speculative(instruction_id_t ii);
void SIM_instruction_force_correct(instruction_id_t ii);
instr_type_t SIM_instruction_type(instruction_id_t ii);
int SIM_instruction_length(instruction_id_t ii);
instruction_status_t SIM_instruction_status(instruction_id_t ii);
reg_info_t * SIM_instruction_get_reg_info(instruction_id_t ii, int n);
attr_value_t SIM_instruction_read_input_reg(instruction_id_t ii, register_id_t ri);
attr_value_t SIM_instruction_read_output_reg(instruction_id_t ii, register_id_t ri);
void SIM_instruction_write_input_reg(instruction_id_t ii, register_id_t ri, attr_value_t value);
instruction_error_t SIM_instruction_write_output_reg(instruction_id_t ii, register_id_t ri, attr_value_t val);
int SIM_instruction_is_sync(instruction_id_t ii);
lang_void * SIM_instruction_get_user_data(instruction_id_t ii);
void SIM_instruction_set_user_data(instruction_id_t ii, lang_void *);
instruction_id_t SIM_instruction_id_from_mem_op_id(conf_object_t *cpu, int id);
generic_transaction_t * SIM_instruction_stalling_mem_op(conf_object_t *obj, instruction_id_t entry);
generic_transaction_t * SIM_instruction_store_queue_mem_op(instruction_id_t ii, int i);
cycles_t SIM_instruction_remaining_stall_time(conf_object_t *obj, instruction_id_t ii);
integer_t SIM_instruction_get_field_value(instruction_id_t ii, const char *field_name);
attr_value_t SIM_instruction_opcode(instruction_id_t ii);
void SIM_release_stall(conf_object_t *obj, int id);
int SIM_get_unique_memory_transaction_id(conf_object_t *obj);
The DBuffer library is part of the Simics API. It is used to efficiently transfer data blocks, such as network packets, inside the simulation. See the Simics Programming Guide for an introduction to programming with DBuffers.
uint8 * dbuffer_append(dbuffer_t *dbuffer, size_t len);
uint8 * dbuffer_prepend(dbuffer_t *dbuffer, size_t len);
uint8 * dbuffer_insert(dbuffer_t *dbuffer, size_t offset, size_t len);
The returned pointer points to a memory area that is only guaranteed to contain valid data for the newly added bytes, and it is illegal to reference data before it or more than len-1 bytes ahead.
The returned pointer is also only valid until the next operation on the dbuffer function, except for calling dbuffer_len.
uint8 * dbuffer_append_external_data(dbuffer_t *dbuffer, void *data, size_t len, int adopt);
uint8 * dbuffer_prepend_external_data(dbuffer_t *dbuffer, void *data, size_t len, int adopt);
If the adopt flag is true, the control of the data block is transferred to the dbuffer. It is assumed to be a block allocated with MM_MALLOC, and will be freed with MM_FREE when the dbuffer is released.
If the adopt flag is false, the dbuffer will not free the memory. Instead it is up to the caller to free the memory, but it must not do so before the dbuffer is freed. Actually, this reference could be copied to other dbuffers, so great care has to be taken. This should only be used for buffers that will only be read, since it hard to know if a write operation will actually write to the buffer or to a copy.
uint8 * dbuffer_append_value(dbuffer_t *dbuffer, int value, size_t len);
uint8 * dbuffer_prepend_value(dbuffer_t *dbuffer, int value, size_t len);
The return value is a pointer to the data just added.
dbuffer_t * dbuffer_clone(dbuffer_t *dbuffer);
The returned dbuffer should be released with dbuffer_free when it is no longer needed.
void dbuffer_copy_append(dbuffer_t *dst, dbuffer_t *src, size_t offset, size_t len);
void dbuffer_copy_prepend(dbuffer_t *dst, dbuffer_t *src, size_t offset, size_t len);
This can often be done without actually copying any memory, so it is usually very efficient.
void dbuffer_free(dbuffer_t *dbuffer);
size_t dbuffer_len(dbuffer_t *dbuffer);
uint8 * dbuffer_read(dbuffer_t *dbuffer, size_t offset, size_t len);
uint8 * dbuffer_read_all(dbuffer_t *dbuffer);
uint8 * dbuffer_read_some(dbuffer_t *dbuffer, size_t offset, size_t len, size_t *actual_len);
The returned pointer is only valid until the next operation on the dbuffer, except for calling dbuffer_len.
The dbuffer_read_some function takes an actual_len parameter, and may return a smaller buffer than requested. The actual number of valid bytes in the returned buffer is stored in *actual_len. It will return a smaller buffer if it would have had to copy memory to return a pointer to the whole region. This means that you can use this function repeatedly to extract all the requested data in the most efficient way. If NULL is passed for actual_len, it will return the full region.
The dbuffer_read_all function assumes 0 for offset, and buffer_len(dbuffer) for len.
void dbuffer_remove(dbuffer_t *dbuffer, size_t offset, size_t remove_len);
void dbuffer_remove_head(dbuffer_t *dbuffer, size_t remove_len);
void dbuffer_remove_tail(dbuffer_t *dbuffer, size_t remove_len);
This usually doesn't involve moving any memory contents, and should be very efficient even if the buffer is large.
uint8 * dbuffer_replace(dbuffer_t *dbuffer, size_t offset, size_t len);
uint8 * dbuffer_replace_all(dbuffer_t *dbuffer);
uint8 * dbuffer_replace_some(dbuffer_t *dbuffer, size_t offset, size_t len, size_t *actual_len);
The returned pointer is only valid until the next operation on the dbuffer, except for calling dbuffer_len.
The dbuffer_replace_some function takes an actual_len parameter, and may return a smaller buffer than requested. The actual number of valid bytes in the returned buffer is stored in *actual_len. It will return a smaller buffer if it would have had to copy memory to return a pointer to the whole region. This means that you can use this function repeatedly to write all the requested data in the most efficient way. If NULL is passed for actual_len, it will return the full region.
The dbuffer_replace_all function assumes 0 for offset, and buffer_len(dbuffer) for len.
dbuffer_t * dbuffer_split(dbuffer_t *dbuffer, size_t offset);
The returned dbuffer should be released with dbuffer_free when it is no longer needed.
uint8 * dbuffer_update(dbuffer_t *dbuffer, size_t offset, size_t len);
uint8 * dbuffer_update_all(dbuffer_t *dbuffer);
uint8 * dbuffer_update_some(dbuffer_t *dbuffer, size_t offset, size_t len, size_t *actual_len);
The returned pointer is only valid until the next operation on the dbuffer, except for calling dbuffer_len.
The dbuffer_update_some function takes an actual_len parameter, and may return a smaller buffer than requested. The actual number of valid bytes in the returned buffer is stored in *actual_len. It will return a smaller buffer if it would have had to copy memory to return a pointer to the whole region. This means that you can use this function repeatedly to access all the requested data in the most efficient way. If NULL is passed for actual_len, it will return the full region.
The dbuffer_update_all function assumes 0 for offset, and buffer_len(dbuffer) for len.
dbuffer_t * new_dbuffer(void);
device_t *d = MM_MALLOC(13, device_t);
The specified type is used for keeping track of the total amount of memory used for each kind of object, and for knowing the size of the allocation (and being able to return a correctly casted pointer). This means that it must be possible to get a pointer to the type by appending an asterisk to the type name; so struct foo * is acceptable, but int (*)(void) is not. Use a typedef in these cases.
There are also macros for specifying the size in bytes, and variants that return memory initialised with zero bytes. It is also possible to specify a desired address alignment.
Since the allocation sites are tracked by file and line number, it is a good idea to avoid having more than one allocation call in a single source line.
MM_FREE(p);
MM_MALIGN(align, nelems, type);
MM_ZALIGN(align, nelems, type);
MM_ZALIGN does the same thing but in addition zeroes out the allocated memory.
Allocated aligned memory imposes a slightly higher space overhead than ordinary memory as handed out by MM_MALLOC. The overhead is of the order of align bytes per allocation.
MM_MALLOC(nelems, type);
MM_MALLOC_SZ(size, type);
MM_ZALLOC(nelems, type);
MM_ZALLOC_SZ(size, type);
MM_MALLOC_SZ specifies the allocation in bytes, which can be occasionally useful.
MM_ZALLOC and MM_ZALLOC_SZ do the same thing as their Z-less counterparts but in addition zero out the allocated memory.
If nelems or size are zero, a null pointer is returned.
MM_REALLOC(p, nelems, type);
MM_REALLOC_SZ(p, size, type);
MM_ZREALLOC(p, nelems, type);
MM_ZREALLOC_SZ(p, size, type);
MM_REALLOC_SZ specifies the new size in bytes.
MM_ZREALLOC and MM_ZREALLOC_SZ do the same thing as their Z-less counterparts, but in addition zero out the extended part of the allocation.
If the passed pointer is NULL, then these macros are equivalent to an allocation of the desired amount. If nelems or size are zero, a null pointer is returned and the original allocation is freed.
MM_STRDUP(str);
This list describes the Python-specific functions that are available for writing commands, scripts and Python modules in Simics.
arg(handler, name = "", spec = "1", default = None, data = None, doc = "", expander = None, pars = [], is_a = None)
eval_cli_line(text, user_typed = 0)
get_available_object_name(prefix)
new_command(name, fun, args = [], doc = "", type = "misc commands", pri = 0, infix = 0, left = 1, short = "", group_short = "", alias = [], doc_with = "", check_args = 2, doc_items = [], see_also = [], namespace = "", method = "", namespace_copy = (), internal = 0, filename = "", linenumber = "", module = "", object = None, repeat = None, deprecated = None)
number_str(val, radix = -1)
object_expander(kind)
arg(str_t, "cpu", expander = object_expander("processor"))To expand a string to all gcache objects:
arg(str_t, "cache", expander = object_expander("gcache"))
quiet_run_command(text)
run_command(text)
new_info_command(cls, get_info, ctype = None)
new_status_command(cls, get_status, ctype = None)