The following types and functions are still available when a module is compiled for an obsolete API. Compiling for an obsolete API is described in the Model Builder User's Guide.
The DBuffer library is part of the Simics API. Up to Simics 4.0, it was
the preferred method to transfer data blocks, such as network packets,
inside the simulation. For code using the new link based on the link
library, and for new models, we recommend using the frags_t
data type instead.
typedef struct dbuffer dbuffer_t;
The type is not inherently thread safe, so each instance must have a single thread as owner, and only the owner can read or write from the instance, however ownership can be transferred to another thread. To share the data with other threads, the instance must first be cloned using dbuffer_clone.
typedef struct { bool batch_mode; bool quiet; bool verbose; bool python_verbose; bool disable_istc; bool disable_dstc; bool module_cache_enable; bool rdp; bool sign_module; const char *log_file; /* The Simics project to use */ const char *project; // NULL to use saved prefs value const char *workspace; // Deprecated, do not use gui_mode_t gui_mode; // GUI_Mode_Default to use saved prefs value cpu_variant_t cpu_mode; // CPU_Any to use saved prefs value const char *package_list; // internal, do not use const char *license_file; // NULL to use saved prefs value const char *expire_time; bool no_windows; bool fail_on_warnings; const char *deprecation_level; // see sim->warn_deprecated bool warn_deprecated; // same as deprecation_level == 2 bool no_warn_deprecated; // same as deprecation_level == 0 bool warn_multithread; /* deprecated and ignored (bug 21597) */ bool check_ifaces; bool no_global_settings; // do not read preferences and recent-files const char *alt_settings_dir; // internal - for test usage /* the following should be -1 if not set by command line options to tell SIM_init_simulator() to use the saved preference value */ int log_enable; bool allow_license_gui; // internal, do not use const char *eclipse_params; // internal, do not use } init_prefs_t;
typedef enum { GUI_Mode_None, GUI_Mode_Mixed, GUI_Mode_Only, GUI_Mode_Default } gui_mode_t;
typedef enum { Cpu_None, /* internal, do not use */ Cpu_Any, Cpu_Fast, Cpu_Stall } cpu_variant_t;
init_prefs_t
, gui_mode_t
and
cpu_variant_t
types are deprecated and should not be used in
new code.
typedef enum { Sim_Log_Info, // Normal informational message Sim_Log_Error, // Simics error Sim_Log_Spec_Violation, // target program violates the specification Sim_Log_Unimplemented, // not implemented in Simics Sim_Log_Critical, // Critical error stopping Simics Sim_Log_Trace, // Breakpoint trace messages Sim_Log_Num_Types, // Do not use } log_type_t;
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 new memory area is not guaranteed to be initialized.
The returned pointer is also only valid until the next operation on the dbuffer function, except for calling dbuffer_len.
uint8 * dbuffer_append_external_data(dbuffer_t *dbuffer, void *data, size_t len, bool adopt);
uint8 * dbuffer_prepend_external_data(dbuffer_t *dbuffer, void *data, size_t len, bool adopt);
If the adopt flag is true, the control of the data block is transferred to the dbuffer. It is assumed to be a block allocated with MM_MALLOC, and will be freed with MM_FREE when the dbuffer is released.
If the adopt flag is false, the dbuffer will not free the memory. Since there is no way to control the lifetime of the external reference if the dbuffer reference has been passed to another function, this option should never be used to point to memory on the stack or to memory that will eventually deallocated. Pointing to static memory is usually safe. This should also only be used for buffers that will only be read from, since there is no way to know when the external pointer is used, and when a copy is used.
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);
See also src/include/simics/util/dbuffer.h
size_t dbuffer_len(const dbuffer_t *dbuffer);
const uint8 * dbuffer_read(dbuffer_t *dbuffer, size_t offset, size_t len);
const uint8 * dbuffer_read_all(dbuffer_t *dbuffer);
const uint8 * dbuffer_read_some(dbuffer_t *dbuffer, size_t offset, size_t len, size_t *actual_len);
The returned pointer is only valid until the next operation on the dbuffer, except for calling dbuffer_len.
The offset and len must specify a valid region, so that the end of the region is not past the end of the dbuffer.
The dbuffer_read_some function takes an
actual_len parameter, and may return a smaller
buffer than requested. The actual number of valid bytes in the
returned buffer is stored in *actual_len. It will
return a smaller buffer if it would have had to copy memory to
return a pointer to the whole region. This means that you can use
this function repeatedly to extract all the requested data in the
most efficient way. If NULL
is passed for
actual_len, it will return the full region.
The dbuffer_read_all function assumes 0 for
offset, and buffer_len(dbuffer)
for
len.
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.
The size of data to remove must be available in the buffer. For example offset + remove_len must not be greater than the buffers length. Similarly for the dbuffer_truncate function there must be at least new_size bytes in the current buffer.
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 offset and len must specify a valid region, so that the end of the region is not past the end of the dbuffer.
The dbuffer_replace_some function takes an
actual_len parameter, and may return a smaller
buffer than requested. The actual number of valid bytes in the
returned buffer is stored in *actual_len. It will
return a smaller buffer if it would have had to copy memory to
return a pointer to the whole region. This means that you can use
this function repeatedly to write all the requested data in the
most efficient way. If NULL
is passed for
actual_len, it will return the full region.
The dbuffer_replace_all function assumes 0 for
offset, and buffer_len(dbuffer)
for
len.
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 offset and len must specify a valid region, so that the end of the region is not past the end of the dbuffer.
The dbuffer_update_some function takes an
actual_len parameter, and may return a smaller
buffer than requested. The actual number of valid bytes in the
returned buffer is stored in *actual_len. It will
return a smaller buffer if it would have had to copy memory to
return a pointer to the whole region. This means that you can use
this function repeatedly to access all the requested data in the
most efficient way. If NULL
is passed for
actual_len, it will return the full region.
The dbuffer_update_all function assumes 0 for
offset, and buffer_len(dbuffer)
for
len.
dbuffer_t * new_dbuffer(void);
See also src/include/simics/util/dbuffer.h