From 8aa35a1666ec1b6252bb37f690f8314d78d6b245 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Tue, 2 Jul 2024 17:29:11 -0300 Subject: [PATCH] refactor!: design new simplified C API --- src/jsonrpc-machine-c-api.h | 383 +++--- src/machine-c-api.h | 2253 +++++++---------------------------- src/machine-c-defines.h | 39 - 3 files changed, 626 insertions(+), 2049 deletions(-) delete mode 100644 src/machine-c-defines.h diff --git a/src/jsonrpc-machine-c-api.h b/src/jsonrpc-machine-c-api.h index ad0775037..e9c600bff 100644 --- a/src/jsonrpc-machine-c-api.h +++ b/src/jsonrpc-machine-c-api.h @@ -17,240 +17,205 @@ #ifndef CM_JSONRPC_C_API_H #define CM_JSONRPC_C_API_H -#ifndef __cplusplus -#include -#endif - #include "machine-c-api.h" -#include "machine-c-defines.h" #ifdef __cplusplus extern "C" { #endif -/// \brief Handle of the jsonrpc connection manager -typedef struct cm_jsonrpc_mgr_tag cm_jsonrpc_mgr; // NOLINT(modernize-use-using) - -/// \brief Create a connection manager to the remote Cartesi Machine server -/// \param remote_address Address of the remote Cartesi server -/// \param mgr Receives new connection manager instance -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for success, non zero code for error -CM_API int cm_create_jsonrpc_mgr(const char *remote_address, cm_jsonrpc_mgr **mgr, char **err_msg); - -/// \brief Deletes a connection manager instance -/// \param m Valid pointer to the existing jsonrpc mgr instance -CM_API void cm_delete_jsonrpc_mgr(const cm_jsonrpc_mgr *mgr); - -/// \brief Create remote machine instance -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object -/// \param config Machine configuration. Must be pointer to valid object -/// \param runtime_config Machine runtime configuration. Must be pointer to valid object -/// \param new_machine Receives the pointer to new remote machine instance -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for success, non zero code for error -CM_API int cm_create_jsonrpc_machine(const cm_jsonrpc_mgr *mgr, const cm_machine_config *config, - const cm_machine_runtime_config *runtime_config, cm_machine **new_machine, char **err_msg); - -/// \brief Create remote machine instance from previously serialized directory -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object -/// \param dir Directory where previous machine is serialized -/// \param runtime_config Machine runtime configuration. Must be pointer to valid object -/// \param new_machine Receives the pointer to new remote machine instance -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for success, non zero code for error -CM_API int cm_load_jsonrpc_machine(const cm_jsonrpc_mgr *mgr, const char *dir, - const cm_machine_runtime_config *runtime_config, cm_machine **new_machine, char **err_msg); - -/// \brief Get remote machine instance that was previously created in the server -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object -/// \param new_machine Receives the pointer to new remote machine instance -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for success, non zero code for error -CM_API int cm_get_jsonrpc_machine(const cm_jsonrpc_mgr *mgr, cm_machine **new_machine, char **err_msg); - -/// \brief Ged default machine config from server -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object -/// \param config Receives the default configuration -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for success, non zero code for error -CM_API int cm_jsonrpc_get_default_config(const cm_jsonrpc_mgr *mgr, const cm_machine_config **config, char **err_msg); - -/// \brief Checks the internal consistency of an access log -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object -/// \param log State access log to be verified. -/// \param runtime_config Runtime config to be used -/// \param one_based Use 1-based indices when reporting errors. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_7_error_message -/// \returns 0 for success, non zero code for error -CM_API int cm_jsonrpc_verify_uarch_step_log(const cm_jsonrpc_mgr *mgr, const cm_access_log *log, - const cm_machine_runtime_config *runtime_config, bool one_based, char **err_msg); - -/// \brief Checks the internal consistency of an access log produced by cm_jsonrpc_log_uarch_reset -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object -/// \param log State access log to be verified. -/// \param runtime_config Runtime config to be used -/// \param one_based Use 1-based indices when reporting errors. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_7_error_message -/// \returns 0 for success, non zero code for error -CM_API int cm_jsonrpc_verify_uarch_reset_log(const cm_jsonrpc_mgr *mgr, const cm_access_log *log, - const cm_machine_runtime_config *runtime_config, bool one_based, char **err_msg); - -/// \brief Checks the validity of a state transition caused by uarch state reset -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object -/// \param root_hash_before State hash before step -/// \param log Step state access log created by cm_jsonrpc_log_uarch_reset -/// \param root_hash_after State hash after step -/// \param runtime_config Runtime config to be used -/// \param one_based Use 1-based indices when reporting errors -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for successful verification, non zero code for error -CM_API int cm_jsonrpc_verify_uarch_reset_state_transition(const cm_jsonrpc_mgr *mgr, const cm_hash *root_hash_before, - const cm_access_log *log, const cm_hash *root_hash_after, const cm_machine_runtime_config *runtime_config, - bool one_based, char **err_msg); - -/// \brief Checks the validity of a state transition -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object -/// \param root_hash_before State hash before step -/// \param log Step state access log -/// \param root_hash_after State hash after step -/// \param runtime_config Runtime config to be used -/// \param one_based Use 1-based indices when reporting errors -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for successful verification, non zero code for error -CM_API int cm_jsonrpc_verify_uarch_step_state_transition(const cm_jsonrpc_mgr *mgr, const cm_hash *root_hash_before, - const cm_access_log *log, const cm_hash *root_hash_after, const cm_machine_runtime_config *runtime_config, - bool one_based, char **err_msg); - -/// \brief Forks the server -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object -/// \param address Receives address of new server if function execution succeeds or NULL -/// otherwise. In case of success, address must be deleted by the function caller using -/// cm_delete_cstring. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for successful verification, non zero code for error -CM_API int cm_jsonrpc_fork(const cm_jsonrpc_mgr *mgr, char **address, char **err_msg); +#include +#include +#include + +/// \brief Handle of the jsonrpc connection manager. +typedef struct cm_jsonrpc_mgr_tag cm_jsonrpc_mgr; + +// ------------------------------------- +// Connection manager related + +/// \brief Creates a jsonrpc connection manager instance connected to a remote machine server. +/// \param remote_address Address of the remote machine server to connect to. +/// \param mgr Receives new jsonrpc connection manager instance. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_create_mgr(const char *remote_address, cm_jsonrpc_mgr **mgr); + +/// \brief Destroys a jsonrpc connection manager instance. +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_destroy_mgr(const cm_jsonrpc_mgr *mgr); + +/// \brief Forks the server. +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \param address Receives address of new server if function execution succeeds or NULL otherwise. +/// Remains valid until this same function is called again for the same jsonrpc connection manager instance. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_fork(const cm_jsonrpc_mgr *mgr, char **address); /// \brief Changes the address the server is listening to -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object +/// \param mgr Pointer to a valid jsonrpc connection manager. /// \param address New address that the remote server should bind to -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for successful verification, non zero code for error -CM_API int cm_jsonrpc_rebind(const cm_jsonrpc_mgr *mgr, const char *address, char **err_msg); - -/// \brief Gets the address of a general-purpose register from remote cartesi server -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_rebind(const cm_jsonrpc_mgr *mgr, const char *address); + +/// \brief Performs shutdown +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_shutdown(const cm_jsonrpc_mgr *mgr); + +/// \brief Gets the semantic version of remote server machine +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \param major Receives semantic major version. +/// \param minor Receives semantic minor version. +/// \param patch Receives semantic patch version. +/// \param pre_release Receives pre release string, +/// remains valid until this same function is called again for the same machine. +/// \param build Receives build string, +/// remains valid until this same function is called again for the same machine. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_get_semantic_version(const cm_jsonrpc_mgr *mgr, uint32_t *major, uint32_t *minor, uint32_t *patch, + const char **pre_release, const char **build); + +// ------------------------------------- +// Machine related + +/// \brief Create remote machine instance. +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \param config Machine configuration as a JSON string. +/// \param runtime_config Machine runtime configuration as a JSON string. +/// \param new_machine Receives the pointer to new machine instance. +/// \returns 0 for success, non zero code for error. +CM_API int cm_create_jsonrpc_machine(const cm_jsonrpc_mgr *mgr, const char *config, const char *runtime_config, + cm_machine **new_machine); + +/// \brief Create remote machine instance from previously serialized directory. +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \param dir Directory where previous machine is serialized. +/// \param runtime_config Machine runtime configuration as a JSON string. +/// \param new_machine Receives the pointer to new remote machine instance. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_load_machine(const cm_jsonrpc_mgr *mgr, const char *dir, const char *runtime_config, + cm_machine **new_machine); + +/// \brief Get remote machine instance that was previously created in the server. +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \param new_machine Receives the pointer to new remote machine instance. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_get_machine(const cm_jsonrpc_mgr *mgr, cm_machine **new_machine); + +// ------------------------------------- +// Getting + +/// \brief Get last error message from server. +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \param err_msg Receives the error message. +/// \returns 0 for success, non zero code for error. +/// \details It uses a thread local variable, so it's safe to call from different threads. +/// The string returned by this function must not be changed nor deallocated. +/// In case the last API call was successful it returns an empty string. +/// The error message is only updated by functions that can return a CM_ERROR code. +CM_API int cm_jsonrpc_get_last_error_message(const cm_jsonrpc_mgr *mgr, const char **err_msg); + +/// \brief Get default machine config from server. +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \param config Receives the default configuration +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_get_default_config(const cm_jsonrpc_mgr *mgr, const char **config); + +/// \brief Get default machine runtime config from server. +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \param config Receives the default configuration +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_get_default_runtime_config(const cm_jsonrpc_mgr *mgr, const char **config); + +/// \brief Gets the address of any CSR from remote server. +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \param csr The CSR register. +/// \param val Receives address of the register. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_get_csr_address(const cm_jsonrpc_mgr *mgr, CM_CSR csr, uint64_t *val); + +/// \brief Gets the address of a general-purpose register from remote server. +/// \param mgr Pointer to a valid jsonrpc connection manager. /// \param i Register index. Between 0 and X_REG_COUNT-1, inclusive. -/// \param val Receives address of the register -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for successful verification, non zero code for error -CM_API int cm_jsonrpc_get_x_address(const cm_jsonrpc_mgr *mgr, int i, uint64_t *val, char **err_msg); - -/// \brief Gets the address of a floating-point register from remote cartesi server -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object +/// \param val Receives address of the register. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_get_x_address(const cm_jsonrpc_mgr *mgr, int i, uint64_t *val); + +/// \brief Gets the address of a floating-point register from remote server. +/// \param mgr Pointer to a valid jsonrpc connection manager. /// \param i Register index. Between 0 and F_REG_COUNT-1, inclusive. -/// \param val Receives address of the register -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for successful verification, non zero code for error -CM_API int cm_jsonrpc_get_f_address(const cm_jsonrpc_mgr *mgr, int i, uint64_t *val, char **err_msg); - -/// \brief Gets the address of a general-purpose register in the microemulator from remote cartesi server -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object +/// \param val Receives address of the register. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_get_f_address(const cm_jsonrpc_mgr *mgr, int i, uint64_t *val); + +/// \brief Gets the address of a general-purpose microarchitecture from remote server. +/// \param mgr Pointer to a valid jsonrpc connection manager. /// \param i Register index. Between 0 and UARCH_X_REG_COUNT-1, inclusive. -/// \param val Receives address of the register -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for successful verification, non zero code for error -CM_API int cm_jsonrpc_get_uarch_x_address(const cm_jsonrpc_mgr *mgr, int i, uint64_t *val, char **err_msg); - -/// \brief Gets the address of any CSR from remote server -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object -/// \param w The command and status register -/// \param val Receives address of the register -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for successful verification, non zero code for error -CM_API int cm_jsonrpc_get_csr_address(const cm_jsonrpc_mgr *mgr, CM_PROC_CSR w, uint64_t *val, char **err_msg); +/// \param val Receives address of the register. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_get_uarch_x_address(const cm_jsonrpc_mgr *mgr, int i, uint64_t *val); -/// \brief Gets the semantic version of remote server machine -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object -/// \param version Receives semantic version -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for successful verification, non zero code for error -CM_API int cm_jsonrpc_get_semantic_version(const cm_jsonrpc_mgr *mgr, const cm_semantic_version **version, - char **err_msg); +// ------------------------------------- +// Verifying -/// \brief Performs shutdown -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for successful verification, non zero code for error -CM_API int cm_jsonrpc_shutdown(const cm_jsonrpc_mgr *mgr, char **err_msg); - -/// \brief Checks the internal consistency of an access log produced by send_cmio_response -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object -/// \param reason Reason for sending response +/// \brief Checks the internal consistency of an access log. +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \param access_log State access log to be verified as a JSON string. +/// \param one_based Use 1-based indices when reporting errors. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_verify_uarch_step_log(const cm_jsonrpc_mgr *mgr, const char *access_log, bool one_based); + +/// \brief Checks the validity of a state transition. +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \param root_hash_before State hash before step. +/// \param access_log State access log to be verified as a JSON string. +/// \param root_hash_after State hash after step. +/// \param one_based Use 1-based indices when reporting errors. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_verify_uarch_step_state_transition(const cm_jsonrpc_mgr *mgr, const cm_hash *root_hash_before, + const char *access_log, const cm_hash *root_hash_after, bool one_based); + +/// \brief Checks the internal consistency of an access log produced by cm_jsonrpc_log_reset_uarch. +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \param access_log State access log to be verified as a JSON string. +/// \param one_based Use 1-based indices when reporting errors. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_verify_reset_uarch_log(const cm_jsonrpc_mgr *mgr, const char *access_log, bool one_based); + +/// \brief Checks the validity of a state transition caused by uarch state reset. +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \param root_hash_before State hash before step. +/// \param access_log State access log to be verified as a JSON string. +/// \param root_hash_after State hash after step. +/// \param one_based Use 1-based indices when reporting errors. +/// \returns 0 for success, non zero code for error. +CM_API int cm_jsonrpc_verify_reset_uarch_state_transition(const cm_jsonrpc_mgr *mgr, const cm_hash *root_hash_before, + const char *access_log, const cm_hash *root_hash_after, bool one_based); + +/// \brief Checks the internal consistency of an access log produced by send_cmio_response. +/// \param mgr Pointer to a valid jsonrpc connection manager. +/// \param reason Reason for sending response. /// \param data Response data to send. /// \param length Length of data response data. -/// \param log State access log to be verified. -/// \param runtime_config Runtime config to be used +/// \param access_log State access log to be verified as a JSON string. /// \param one_based Use 1-based indices when reporting errors. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successfull function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_7_error_message -/// \returns 0 for success, non zero code for error +/// \returns 0 for success, non zero code for error. CM_API int cm_jsonrpc_verify_send_cmio_response_log(const cm_jsonrpc_mgr *mgr, uint16_t reason, - const unsigned char *data, size_t length, const cm_access_log *log, const cm_machine_runtime_config *runtime_config, - bool one_based, char **err_msg); + const unsigned char *data, size_t length, const char *access_log, bool one_based); -/// \brief Checks the validity of a state transition caused by send_cmio_response -/// \param mgr Cartesi jsonrpc connection manager. Must be pointer to valid object +/// \brief Checks the validity of a state transition caused by send_cmio_response. +/// \param mgr Pointer to a valid jsonrpc connection manager. /// \param reason Reason for sending response. /// \param data Response data to send. /// \param length Length of data response data. /// \param root_hash_before State hash before load. -/// \param log State access log to be verified. +/// \param access_log State access log to be verified as a JSON string. /// \param root_hash_after State hash after load. -/// \param runtime_config Runtime config to be used -/// \param one_based Use 1-based indices when reporting errors -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successfull function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for successfull verification, non zero code for error +/// \param one_based Use 1-based indices when reporting errors. +/// \returns 0 for successfull verification, non zero code for error. CM_API int cm_jsonrpc_verify_send_cmio_response_state_transition(const cm_jsonrpc_mgr *mgr, uint16_t reason, - const unsigned char *data, size_t length, const cm_hash *root_hash_before, const cm_access_log *log, - const cm_hash *root_hash_after, const cm_machine_runtime_config *runtime_config, bool one_based, char **err_msg); + const unsigned char *data, size_t length, const cm_hash *root_hash_before, const char *access_log, + const cm_hash *root_hash_after, bool one_based); #ifdef __cplusplus } diff --git a/src/machine-c-api.h b/src/machine-c-api.h index 91c41bbd5..5de94611c 100644 --- a/src/machine-c-api.h +++ b/src/machine-c-api.h @@ -17,48 +17,51 @@ #ifndef CM_C_API_H #define CM_C_API_H -#ifndef __cplusplus -#include -#include -#include -#include -#else -#include -#include -#endif - -#include "machine-c-defines.h" +#include "machine-c-version.h" #ifdef __cplusplus extern "C" { #endif -// --------------------------------- -// API Structures -// --------------------------------- +#include +#include +#include -// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays,modernize-avoid-c-arrays,modernize-use-using) -typedef uint8_t cm_hash[CM_MACHINE_HASH_BYTE_SIZE]; +// ----------------------------------------------------------------------------- +// API definitions +// ----------------------------------------------------------------------------- -/// \brief Array of hashes -typedef struct { // NOLINT(modernize-use-using) - cm_hash *entry; - size_t count; -} cm_hash_array; +// Compiler visibility definition +#ifndef CM_API +#define CM_API __attribute__((visibility("default"))) +#endif -/// brief Error codes returned from machine emulator C API -typedef enum { // NOLINT(modernize-use-using) - CM_ERROR_OK = 0, - // Logic errors +#define CM_MCYCLE_MAX UINT64_MAX + +// ----------------------------------------------------------------------------- +// API enums and structures +// ----------------------------------------------------------------------------- + +/// \brief Constants. +enum { + CM_MACHINE_HASH_BYTE_SIZE = 32, + CM_MACHINE_X_REG_COUNT = 32, + CM_MACHINE_F_REG_COUNT = 32, + CM_MACHINE_UARCH_X_REG_COUNT = 32, + CM_TREE_LOG2_WORD_SIZE = 3, + CM_TREE_LOG2_PAGE_SIZE = 12, + CM_TREE_LOG2_ROOT_SIZE = 64, +}; + +/// \brief Error codes returned from machine emulator C API. +typedef enum CM_ERROR { + CM_ERROR_OK, CM_ERROR_INVALID_ARGUMENT, CM_ERROR_DOMAIN_ERROR, CM_ERROR_LENGTH_ERROR, CM_ERROR_OUT_OF_RANGE, CM_ERROR_LOGIC_ERROR, - CM_LOGIC_ERROR_END, - // Bad optional access error CM_ERROR_BAD_OPTIONAL_ACCESS, - // Runtime errors CM_ERROR_RUNTIME_ERROR, CM_ERROR_RANGE_ERROR, CM_ERROR_OVERFLOW_ERROR, @@ -70,8 +73,6 @@ typedef enum { // NOLINT(modernize-use-using) CM_ERROR_NONEXISTING_LOCAL_TIME, CM_ERROR_AMBIGUOUS_LOCAL_TIME, CM_ERROR_FORMAT_ERROR, - CM_RUNTIME_ERROR_END, - // Other errors CM_ERROR_BAD_TYPEID, CM_ERROR_BAD_CAST, CM_ERROR_BAD_ANY_CAST, @@ -82,1894 +83,544 @@ typedef enum { // NOLINT(modernize-use-using) CM_ERROR_BAD_EXCEPTION, CM_ERROR_BAD_VARIANT_ACCESS, CM_ERROR_EXCEPTION, - CM_OTHER_ERROR_END, - // C API Errors - CM_ERROR_UNKNOWN + CM_ERROR_UNKNOWN, } CM_ERROR; -/// \brief Reasons for a machine run interruption -typedef enum { // NOLINT(modernize-use-using) +/// \brief Reasons for cm_run interruption. +typedef enum CM_BREAK_REASON { CM_BREAK_REASON_FAILED, CM_BREAK_REASON_HALTED, CM_BREAK_REASON_YIELDED_MANUALLY, CM_BREAK_REASON_YIELDED_AUTOMATICALLY, CM_BREAK_REASON_YIELDED_SOFTLY, - CM_BREAK_REASON_REACHED_TARGET_MCYCLE + CM_BREAK_REASON_REACHED_TARGET_MCYCLE, } CM_BREAK_REASON; -/// \brief List of CSRs to use with read_csr and write_csr -typedef enum { // NOLINT(modernize-use-using) - CM_PROC_PC, - CM_PROC_FCSR, - CM_PROC_MVENDORID, - CM_PROC_MARCHID, - CM_PROC_MIMPID, - CM_PROC_MCYCLE, - CM_PROC_ICYCLEINSTRET, - CM_PROC_MSTATUS, - CM_PROC_MTVEC, - CM_PROC_MSCRATCH, - CM_PROC_MEPC, - CM_PROC_MCAUSE, - CM_PROC_MTVAL, - CM_PROC_MISA, - CM_PROC_MIE, - CM_PROC_MIP, - CM_PROC_MEDELEG, - CM_PROC_MIDELEG, - CM_PROC_MCOUNTEREN, - CM_PROC_MENVCFG, - CM_PROC_STVEC, - CM_PROC_SSCRATCH, - CM_PROC_SEPC, - CM_PROC_SCAUSE, - CM_PROC_STVAL, - CM_PROC_SATP, - CM_PROC_SCOUNTEREN, - CM_PROC_SENVCFG, - CM_PROC_ILRSC, - CM_PROC_IFLAGS, - CM_PROC_IUNREP, - CM_PROC_CLINT_MTIMECMP, - CM_PROC_PLIC_GIRQPEND, - CM_PROC_PLIC_GIRQSRVD, - CM_PROC_HTIF_TOHOST, - CM_PROC_HTIF_FROMHOST, - CM_PROC_HTIF_IHALT, - CM_PROC_HTIF_ICONSOLE, - CM_PROC_HTIF_IYIELD, - CM_PROC_UARCH_PC, - CM_PROC_UARCH_CYCLE, - CM_PROC_UARCH_HALT_FLAG, - CM_PROC_UNKNOWN -} CM_PROC_CSR; - -/// \brief Return values of uarch_interpret -typedef enum { // NOLINT(modernize-use-using) +/// \brief Reasons for cm_run_uarch interruption. +typedef enum CM_UARCH_BREAK_REASON { CM_UARCH_BREAK_REASON_REACHED_TARGET_CYCLE, CM_UARCH_BREAK_REASON_UARCH_HALTED, } CM_UARCH_BREAK_REASON; -/// \brief Processor state configuration -typedef struct { // NOLINT(modernize-use-using) - uint64_t x[CM_MACHINE_X_REG_COUNT]; ///< Value of general-purpose registers - uint64_t f[CM_MACHINE_F_REG_COUNT]; ///< Value of floating-point registers - uint64_t pc; ///< Value of pc - uint64_t fcsr; ///< Value of fcsr CSR - uint64_t mvendorid; ///< Value of mvendorid CSR - uint64_t marchid; ///< Value of marchid CSR - uint64_t mimpid; ///< Value of mimpid CSR - uint64_t mcycle; ///< Value of mcycle CSR - uint64_t icycleinstret; ///< Value of icycleinstret CSR - uint64_t mstatus; ///< Value of mstatus CSR - uint64_t mtvec; ///< Value of mtvec CSR - uint64_t mscratch; ///< Value of mscratch CSR - uint64_t mepc; ///< Value of mepc CSR - uint64_t mcause; ///< Value of mcause CSR - uint64_t mtval; ///< Value of mtval CSR - uint64_t misa; ///< Value of misa CSR - uint64_t mie; ///< Value of mie CSR - uint64_t mip; ///< Value of mip CSR - uint64_t medeleg; ///< Value of medeleg CSR - uint64_t mideleg; ///< Value of mideleg CSR - uint64_t mcounteren; ///< Value of mcounteren CSR - uint64_t menvcfg; ///< Value of menvcfg CSR - uint64_t stvec; ///< Value of stvec CSR - uint64_t sscratch; ///< Value of sscratch CSR - uint64_t sepc; ///< Value of sepc CSR - uint64_t scause; ///< Value of scause CSR - uint64_t stval; ///< Value of stval CSR - uint64_t satp; ///< Value of satp CSR - uint64_t scounteren; ///< Value of scounteren CSR - uint64_t senvcfg; ///< Value of senvcfg CSR - uint64_t ilrsc; ///< Value of ilrsc CSR - uint64_t iflags; ///< Value of iflags CSR - uint64_t iunrep; ///< Value of iunrep CSR -} cm_processor_config; - -/// \brief RAM state configuration -typedef struct { // NOLINT(modernize-use-using) - uint64_t length; ///< RAM length - const char *image_filename; ///< RAM image file name -} cm_ram_config; - -/// \brief DTB state configuration -typedef struct { // NOLINT(modernize-use-using) - const char *bootargs; ///< Bootargs to pass to kernel - const char *init; ///< Initialization commands to be executed as root on boot - const char *entrypoint; ///< Commands to execute the main application - const char *image_filename; ///< ROM image file -} cm_dtb_config; - -/// \brief Memory range configuration -typedef struct { // NOLINT(modernize-use-using) - uint64_t start; ///< Memory range start position - uint64_t length; ///< Memory range length - bool shared; ///< Target changes to range affect image file? - const char *image_filename; ///< Memory range image file name -} cm_memory_range_config; - -/// \brief Memory range configuration array -typedef struct { // NOLINT(modernize-use-using) - cm_memory_range_config *entry; - size_t count; -} cm_memory_range_config_array; - -/// \brief TLB device state configuration -typedef struct { // NOLINT(modernize-use-using) - const char *image_filename; ///< TLB image file name -} cm_tlb_config; - -/// \brief CLINT device state configuration -typedef struct { // NOLINT(modernize-use-using) - uint64_t mtimecmp; ///< Value of mtimecmp CSR -} cm_clint_config; - -/// \brief PLIC device state configuration -typedef struct { // NOLINT(modernize-use-using) - uint64_t girqpend; ///< Value of girqpend CSR - uint64_t girqsrvd; ///< Value of girqsrvd CSR -} cm_plic_config; - -/// \brief HTIF device state configuration -typedef struct { // NOLINT(modernize-use-using) - uint64_t fromhost; ///< Value of fromhost CSR - uint64_t tohost; ///< Value of tohost CSR - bool console_getchar; ///< Make console getchar available? - bool yield_manual; ///< Make yield manual available? - bool yield_automatic; ///< Make yield automatic available? -} cm_htif_config; - -/// \brief VirtIO device type -typedef enum { // NOLINT(modernize-use-using) - CM_VIRTIO_DEVICE_CONSOLE, - CM_VIRTIO_DEVICE_P9FS, - CM_VIRTIO_DEVICE_NET_USER, - CM_VIRTIO_DEVICE_NET_TUNTAP -} CM_VIRTIO_DEVICE_TYPE; - -/// \brief VirtIO Plan 9 filesystem device state configuration -typedef struct { // NOLINT(modernize-use-using) - const char *tag; ///< Guest mount tag - const char *host_directory; ///< Path to the host shared directory -} cm_virtio_p9fs_config; - -/// \brief VirtIO host forward state config -typedef struct cm_virtio_hostfwd_config { // NOLINT(modernize-use-using) - bool is_udp; - uint64_t host_ip; - uint64_t guest_ip; - uint16_t host_port; - uint16_t guest_port; -} cm_virtio_hostfwd_config; - -/// \brief VirtIO host forward configuration array -typedef struct { // NOLINT(modernize-use-using) - cm_virtio_hostfwd_config *entry; - size_t count; -} cm_virtio_hostfwd_config_array; - -/// \brief VirtIO user network device state configuration -typedef struct { // NOLINT(modernize-use-using) - cm_virtio_hostfwd_config_array hostfwd; -} cm_virtio_net_user_config; - -/// \brief VirtIO TUN/TAP network device state configuration -typedef struct { // NOLINT(modernize-use-using) - const char *iface; ///< Host's tap network interface (e.g "tap0") -} cm_virtio_net_tuntap_config; - -/// \brief VirtIO device union -typedef union { // NOLINT(modernize-use-using) - cm_virtio_p9fs_config p9fs; ///< Plan 9 filesystem - cm_virtio_net_user_config net_user; ///< User-mode networking - cm_virtio_net_tuntap_config net_tuntap; ///< TUN/TAP networking -} cm_virtio_device_config_union; - -/// \brief VirtIO device state configuration -typedef struct { // NOLINT(modernize-use-using) - CM_VIRTIO_DEVICE_TYPE type; ///< VirtIO device type - cm_virtio_device_config_union device; ///< VirtIO device config -} cm_virtio_device_config; - -/// \brief VirtIO device configuration array -typedef struct { // NOLINT(modernize-use-using) - cm_virtio_device_config *entry; - size_t count; -} cm_virtio_config_array; - -/// \brief CMIO buffer configuration -typedef struct { // NOLINT(modernize-use-using) - bool shared; ///< Target changes to range affect image file? - const char *image_filename; ///< Memory range image file name -} cm_cmio_buffer_config; - -/// \brief Cmio state configuration -typedef struct { // NOLINT(modernize-use-using) - cm_cmio_buffer_config rx_buffer; ///< RX buffer configuration - cm_cmio_buffer_config tx_buffer; ///< TX buffer configuration -} cm_cmio_config; - -/// \brief microarchitecture RAM configuration -typedef struct { // NOLINT(modernize-use-using) - const char *image_filename; ///< RAM image file name -} cm_uarch_ram_config; - -/// \brief Microarchitecture processor configuration -typedef struct { // NOLINT(modernize-use-using) - uint64_t x[CM_MACHINE_UARCH_X_REG_COUNT]; - uint64_t pc; - uint64_t cycle; - bool halt_flag; -} cm_uarch_processor_config; - -/// \brief Microarchitecture state configuration -typedef struct { // NOLINT(modernize-use-using) - cm_uarch_processor_config processor; - cm_uarch_ram_config ram; -} cm_uarch_config; - -/// \brief Machine state configuration -typedef struct { // NOLINT(modernize-use-using) - cm_processor_config processor; - cm_ram_config ram; - cm_dtb_config dtb; - cm_memory_range_config_array flash_drive; - cm_tlb_config tlb; - cm_clint_config clint; - cm_plic_config plic; - cm_htif_config htif; - cm_virtio_config_array virtio; - cm_cmio_config cmio; - cm_uarch_config uarch; -} cm_machine_config; - -/// \brief Merkle tree proof structure -/// \details -/// This structure holds a proof that the node spanning a log2_target_size -/// at a given address in the tree has a certain hash. -typedef struct { // NOLINT(modernize-use-using) - uint64_t target_address; - size_t log2_target_size; - cm_hash target_hash; - size_t log2_root_size; - cm_hash root_hash; - cm_hash_array sibling_hashes; -} cm_merkle_tree_proof; - -/// \brief Type of state access -typedef enum { // NOLINT(modernize-use-using) - CM_ACCESS_READ, ///< Read operation - CM_ACCESS_WRITE, ///< Write operation -} CM_ACCESS_TYPE; - -/// \brief Type of access log -typedef struct { // NOLINT(modernize-use-using) - bool proofs; ///< Includes proofs - bool annotations; ///< Includes annotations - bool large_data; ///< Includes data bigger than 8 bytes -} cm_access_log_type; - -/// \brief Bracket type -typedef enum { // NOLINT(modernize-use-using) - CM_BRACKET_BEGIN, ///< Start of scope - CM_BRACKET_END ///< End of scope -} CM_BRACKET_TYPE; - -/// \brief Bracket note -typedef struct { // NOLINT(modernize-use-using) - CM_BRACKET_TYPE type; ///< Bracket type - uint64_t where; ///< Where it points to in the log - char *text; ///< Note text -} cm_bracket_note; - -/// \brief Records an access to the machine state -typedef struct { // NOLINT(modernize-use-using) - CM_ACCESS_TYPE type; ///< Type of access - uint64_t address; ///< Address of access - int log2_size; ///< Log2 of size of access - cm_hash read_hash; ///< Hash of data before access - uint8_t *read_data; ///< Data before access - size_t read_data_size; ///< Size of data before access in bytes - cm_hash written_hash; ///< Hash of data after access (if writing) - uint8_t *written_data; ///< Data after access (if writing) - size_t written_data_size; ///< Size of data after access in bytes - cm_hash_array *sibling_hashes; ///< Sibling hashes towards root -} cm_access; - -/// \brief Array of accesses -typedef struct { // NOLINT(modernize-use-using) - cm_access *entry; - size_t count; -} cm_access_array; - -/// \brief Array of bracket notes -typedef struct { // NOLINT(modernize-use-using) - cm_bracket_note *entry; - size_t count; -} cm_bracket_note_array; - -/// \brief Array of notes -typedef struct { // NOLINT(modernize-use-using) - const char **entry; - size_t count; -} cm_note_array; - -/// \brief Log of state accesses -typedef struct { // NOLINT(modernize-use-using) - cm_access_array accesses; ///< List of accesses - cm_bracket_note_array brackets; ///< Begin/End annotations - cm_note_array notes; ///< Per-access annotations - cm_access_log_type log_type; ///< Log type -} cm_access_log; - -/// \brief Concurrency runtime configuration -typedef struct { // NOLINT(modernize-use-using) - uint64_t update_merkle_tree; -} cm_concurrency_runtime_config; - -/// \brief HTIF runtime configuration -typedef struct { // NOLINT(modernize-use-using) - bool no_console_putchar; -} cm_htif_runtime_config; - -/// \brief Machine runtime configuration -typedef struct { // NOLINT(modernize-use-using) - cm_concurrency_runtime_config concurrency; - cm_htif_runtime_config htif; - bool skip_root_hash_check; - bool skip_root_hash_store; - bool skip_version_check; - bool soft_yield; -} cm_machine_runtime_config; - -/// \brief Machine instance handle -/// \details cm_machine* is handle used from C api users -/// to pass the machine object when calling C api functions. Currently, -/// it is merely a pointer to internal C++ object that is internally casted -/// back to original C++ machine type. On some obscure CPU arhitectures -/// where pointer size depend on types, this api might not work -typedef struct cm_machine_tag cm_machine; // NOLINT(modernize-use-using) - -/// \brief Semantic version -typedef struct { // NOLINT(modernize-use-using) - uint32_t major; - uint32_t minor; - uint32_t patch; - const char *pre_release; - const char *build; -} cm_semantic_version; - -/// \brief Memory range description -typedef struct { // NOLINT(modernize-use-using) - uint64_t start; - uint64_t length; - const char *description; -} cm_memory_range_descr; - -/// \brief Memory range description array -typedef struct { // NOLINT(modernize-use-using) - cm_memory_range_descr *entry; - size_t count; -} cm_memory_range_descr_array; - -// --------------------------------- +/// \brief Access log types. +typedef enum { + CM_ACCESS_LOG_TYPE_PROOFS = 1 << 1, ///< Includes proofs + CM_ACCESS_LOG_TYPE_ANNOTATIONS = 1 << 2, ///< Includes annotations + CM_ACCESS_LOG_TYPE_LARGE_DATA = 1 << 3 ///< Includes data bigger than 8 bytes +} CM_ACCESS_LOG_TYPE; + +/// \brief List of CSRs to use with cm_read_csr and cm_write_csr. +typedef enum CM_CSR { + CM_CSR_PC, + CM_CSR_FCSR, + CM_CSR_MVENDORID, + CM_CSR_MARCHID, + CM_CSR_MIMPID, + CM_CSR_MCYCLE, + CM_CSR_ICYCLEINSTRET, + CM_CSR_MSTATUS, + CM_CSR_MTVEC, + CM_CSR_MSCRATCH, + CM_CSR_MEPC, + CM_CSR_MCAUSE, + CM_CSR_MTVAL, + CM_CSR_MISA, + CM_CSR_MIE, + CM_CSR_MIP, + CM_CSR_MEDELEG, + CM_CSR_MIDELEG, + CM_CSR_MCOUNTEREN, + CM_CSR_MENVCFG, + CM_CSR_STVEC, + CM_CSR_SSCRATCH, + CM_CSR_SEPC, + CM_CSR_SCAUSE, + CM_CSR_STVAL, + CM_CSR_SATP, + CM_CSR_SCOUNTEREN, + CM_CSR_SENVCFG, + CM_CSR_ILRSC, + CM_CSR_YIELD_MANUAL_FLAG, + CM_CSR_YIELD_AUTOMATIC_FLAG, + CM_CSR_HALT_FLAG, + CM_CSR_IUNREP, + CM_CSR_CLINT_MTIMECMP, + CM_CSR_PLIC_GIRQPEND, + CM_CSR_PLIC_GIRQSRVD, + CM_CSR_HTIF_TOHOST, + CM_CSR_HTIF_FROMHOST, + CM_CSR_HTIF_IHALT, + CM_CSR_HTIF_ICONSOLE, + CM_CSR_HTIF_IYIELD, + CM_CSR_UARCH_PC, + CM_CSR_UARCH_CYCLE, + CM_CSR_UARCH_HALT_FLAG, + CM_CSR_COUNT, ///< Number of CSRs + CM_CSR_UNKNOWN, ///< Unknown CSR + CM_CSR_HTIF_TOHOST_DEV, ///< View of DEV field from HTIF_TOHOST + CM_CSR_HTIF_TOHOST_CMD, ///< View of CMD field from HTIF_TOHOST + CM_CSR_HTIF_TOHOST_DATA, ///< View of DATA field from HTIF_TOHOST + CM_CSR_HTIF_FROMHOST_DEV, ///< View of DEV field from HTIF_FROMHOST + CM_CSR_HTIF_FROMHOST_CMD, ///< View of CMD field from HTIF_FROMHOST + CM_CSR_HTIF_FROMHOST_DATA, ///< View of DATA field from HTIF_FROMHOST +} CM_CSR; + +/// \brief Machine instance handle. +/// \details cm_machine* is handle used to pass the machine object when calling C API functions. +typedef struct cm_machine cm_machine; + +/// \brief Machine hash array. +typedef uint8_t cm_hash[CM_MACHINE_HASH_BYTE_SIZE]; + +// ----------------------------------------------------------------------------- // API function definitions -// --------------------------------- - -/// \brief Create new machine config with default parameters -/// \returns Pointer to new default config object -/// \details Object acquired from this function must not be changed and -/// must be deleted with cm_delete_machine_config. To make a custom config based -/// on default config user must make a deep copy of returned object members and then -/// customize -CM_API const cm_machine_config *cm_new_default_machine_config(void); - -/// \brief Delete machine config acquired from cm_new_default_machine_config -/// \returns void -CM_API void cm_delete_machine_config(const cm_machine_config *config); - -/// \brief Create new machine instance from configuration -/// \param config Machine configuration. Must be pointer to valid object -/// \param runtime_config Machine runtime configuration. Must be pointer to valid object -/// \param new_machine Receives the pointer to new machine instance -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_create_machine(const cm_machine_config *config, const cm_machine_runtime_config *runtime_config, - cm_machine **new_machine, char **err_msg); - -/// \brief Create machine instance from previously serialized directory -/// \param dir Directory where previous machine is serialized -/// \param runtime_config Machine runtime configuration. Must be pointer to valid object -/// \param new_machine Receives the pointer to new machine instance -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_load_machine(const char *dir, const cm_machine_runtime_config *runtime_config, cm_machine **new_machine, - char **err_msg); - -/// \brief Serialize entire state to directory -/// \param m Pointer to valid machine instance +// ----------------------------------------------------------------------------- + +/// \brief Creates a new machine instance from configuration. +/// \param config Machine configuration as a JSON string. +/// \param runtime_config Machine runtime configuration as a JSON string. +/// \param new_machine Receives the pointer to new machine instance. +/// \returns 0 for success, non zero code for error. +CM_API int cm_create(const char *config, const char *runtime_config, cm_machine **new_machine); + +/// \brief Destroys a machine. +/// \returns 0 for success, non zero code for error. +/// \details The machine is deallocated and its pointer cannot be used after this call. +CM_API int cm_destroy(cm_machine *m); + +/// \brief Creates a machine instance from previously serialized directory. +/// \param dir Directory where previous machine is serialized. +/// \param runtime_config Machine runtime configuration as a JSON string. +/// \param new_machine Receives the pointer to new machine instance. +/// \returns 0 for success, non zero code for error. +CM_API int cm_load(const char *dir, const char *runtime_config, cm_machine **new_machine); + +/// \brief Serializes entire machine state to a directory. +/// \param m Pointer to a valid machine instance. /// \param dir Directory where the machine will be serialized -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \details The method changes machine because it updates the root hash -/// \returns 0 for success, non zero code for error -CM_API int cm_store(cm_machine *m, const char *dir, char **err_msg); - -/// \brief Deletes machine instance -/// \param m Valid pointer to the existing machine instance -CM_API void cm_delete_machine(cm_machine *m); +/// \details The method changes machine because it updates the root hash. +/// \returns 0 for success, non zero code for error. +CM_API int cm_store(cm_machine *m, const char *dir); + +/// \brief Returns the machine initial config. +/// \param m Pointer to a valid machine instance. +/// \param config Receives the initial configuration as a JSON string, +/// remains valid until the machine is destroyed. +/// \returns 0 for success, non zero code for error. +/// The string returned by this function must not be changed nor deallocated. +CM_API int cm_get_initial_config(const cm_machine *m, const char **config); + +/// \brief Replaces a memory range. +/// \param m Pointer to a valid machine instance. +/// \param start Memory start physical address. +/// \param length Memory length. +/// \param shared If true changes by the machine will be shared to the image file. +/// \param image_filename Image file name to load into the range. +/// \returns 0 for success, non zero code for error. +/// \details The machine must contain an existing memory range matching the start and length +/// specified in new range. +CM_API int cm_replace_memory_range(cm_machine *m, uint64_t start, uint64_t length, bool shared, + const char *image_filename); + +// ------------------------------------- +// Rolling back + +/// \brief Saves a snapshot of the machine. +/// \param m Pointer to a valid machine instance. +/// \returns 0 for success, non zero code for error. +CM_API int cm_snapshot(cm_machine *m); + +/// \brief Performs commit of the machine, discarding last snapshot. +/// \param m Pointer to a valid machine instance. +/// \returns 0 for success, non zero code for error. +CM_API int cm_commit(cm_machine *m); + +/// \brief Performs rollback of the machine, restoring last snapshot. +/// \param m Pointer to a valid machine instance. +/// \returns 0 for success, non zero code for error. +CM_API int cm_rollback(cm_machine *m); + +// ------------------------------------- +// Running and stepping /// \brief Runs the machine until mcycle reaches mcycle_end or the machine halts. -/// \param m Pointer to valid machine instance -/// \param mcycle_end End cycle value -/// \param break_reason Receives reason for machine run interruption when not NULL -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_machine_run(cm_machine *m, uint64_t mcycle_end, CM_BREAK_REASON *break_reason_result, char **err_msg); +/// \param m Pointer to a valid machine instance. +/// \param mcycle_end End cycle value. +/// \param break_reason Receives reason for machine run interruption when not NULL. +/// \returns 0 for success, non zero code for error. +CM_API int cm_run(cm_machine *m, uint64_t mcycle_end, CM_BREAK_REASON *break_reason); + +/// \brief Runs the machine in the microarchitecture until the mcycle advances by 1 +/// or uarch_cycle counter reaches uarch_cycle_end. +/// \param m Pointer to a valid machine instance. +/// \param uarch_cycle_end End cycle value +/// \param break_reason Receives status of machine run_uarch when not NULL. +/// \returns 0 for success, non zero code for error. +CM_API int cm_run_uarch(cm_machine *m, uint64_t uarch_cycle_end, CM_UARCH_BREAK_REASON *break_reason); /// \brief Runs the machine for one micro cycle logging all accesses to the state. -/// \param m Pointer to valid machine instance -/// \param log_type Type of access log to generate. +/// \param m Pointer to a valid machine instance. +/// \param log_type Type of access log to generate, must be bitwise OR of CM_ACCESS_LOG_TYPE enum. +/// \param one_based Use 1-based indices when reporting errors. +/// \param access_log Receives the state access log as a JSON string, +/// remains valid until this same function is called again for the same machine. +/// \returns 0 for success, non zero code for error. +CM_API int cm_log_uarch_step(cm_machine *m, int log_type, bool one_based, const char **access_log); + +/// \brief Resets the entire uarch state to pristine values. +/// \param m Pointer to a valid machine instance. +/// \returns 0 for success, non zero code for error. +CM_API int cm_reset_uarch(cm_machine *m); + +/// \brief Resets the value of the microarchitecture halt flag. +/// \param m Pointer to a valid machine instance. +/// \param log_type Type of access log to generate, must be bitwise OR of CM_ACCESS_LOG_TYPE enum. /// \param one_based Use 1-based indices when reporting errors. -/// \param access_log Receives the state access log. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_log_uarch_step(cm_machine *m, cm_access_log_type log_type, bool one_based, cm_access_log **access_log, - char **err_msg); - -/// \brief Deletes the instance of cm_access_log acquired from cm_step -/// \param acc_log Valid pointer to cm_access_log object -CM_API void cm_delete_access_log(cm_access_log *acc_log); - -/// \brief Checks the internal consistency of an access log -/// \param log State access log to be verified -/// \param r Machine runtime configuration to use during verification. Must be pointer to valid object -/// \param one_based Use 1-based indices when reporting errors -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_verify_uarch_step_log(const cm_access_log *log, const cm_machine_runtime_config *runtime_config, - bool one_based, char **err_msg); - -/// \brief Checks the validity of a state transition -/// \param root_hash_before State hash before step -/// \param log Step state access log -/// \param root_hash_after State hash after step -/// \param runtime_config Machine runtime configuration to use during verification. Must be pointer to valid object -/// \param one_based Use 1-based indices when reporting errors -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for successful verification, non zero code for error -CM_API int cm_verify_uarch_step_state_transition(const cm_hash *root_hash_before, const cm_access_log *log, - const cm_hash *root_hash_after, const cm_machine_runtime_config *runtime_config, bool one_based, char **err_msg); - -/// \brief Checks the validity of a state transition caused by a uarch state reset -/// \param root_hash_before State hash before step -/// \param log Step state access log produced by cm_log_uarch_reset -/// \param root_hash_after State hash after step -/// \param runtime_config Machine runtime configuration to use during verification. Must be pointer to valid object -/// \param one_based Use 1-based indices when reporting errors -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for successful verification, non zero code for error -CM_API int cm_verify_uarch_reset_state_transition(const cm_hash *root_hash_before, const cm_access_log *log, - const cm_hash *root_hash_after, const cm_machine_runtime_config *runtime_config, bool one_based, char **err_msg); - -/// \brief Checks the internal consistency of an access log produced by cm_log_uarch_reset -/// \param log State access log to be verified -/// \param r Machine runtime configuration to use during verification. Must be pointer to valid object -/// \param one_based Use 1-based indices when reporting errors -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_verify_uarch_reset_log(const cm_access_log *log, const cm_machine_runtime_config *runtime_config, - bool one_based, char **err_msg); - -/// \brief Obtains the proof for a node in the Merkle tree -/// \param m Pointer to valid machine instance -/// \param address Address of target node. Must be aligned to a 2log2_size boundary -/// \param log2_size log2 of size subintended by target node. -/// Must be between 3 (for a word) and 64 (for the entire address space), inclusive -/// \param proof Receives the proof -/// proof must be deleted with the function cm_delete_merkle_tree_proof -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -/// \details If the node is smaller than a page size, then it must lie entirely inside the same PMA range. -CM_API int cm_get_proof(const cm_machine *m, uint64_t address, int log2_size, cm_merkle_tree_proof **proof, - char **err_msg); - -/// \brief Deletes the instance of cm_merkle_tree_proof acquired from cm_get_proof -/// \param proof Valid pointer to cm_merkle_tree_proof object -CM_API void cm_delete_merkle_tree_proof(cm_merkle_tree_proof *proof); - -/// \brief Obtains the root hash of the Merkle tree -/// \param m Pointer to valid machine instance -/// \param hash Valid pointer to cm_hash structure that receives the hash. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_get_root_hash(const cm_machine *m, cm_hash *hash, char **err_msg); +/// \param access_log Receives the state access log as a JSON string, +/// remains valid until this same function is called again for the same machine. +/// \returns 0 for success, non zero code for error. +CM_API int cm_log_reset_uarch(cm_machine *m, int log_type, bool one_based, const char **access_log); + +/// \brief Sends cmio response +/// \param m Pointer to a valid machine instance. +/// \param reason Reason for sending the response. +/// \param data Response data to send +/// \param length Length of response data. +/// \returns 0 for success, non zero code for error. +CM_API int cm_send_cmio_response(cm_machine *m, uint16_t reason, const unsigned char *data, size_t length); + +/// \brief Send cmio response and returns an access log +/// \param m Pointer to a valid machine instance. +/// \param reason Reason for sending the response. +/// \param data Response data to send. +/// \param length Length of response data. +/// \param log_type Type of access log to generate, must be bitwise OR of CM_ACCESS_LOG_TYPE enum. +/// \param one_based Use 1-based indices when reporting errors. +/// \param access_log Receives the state access log as a JSON string, +/// remains valid until this same function is called again for the same machine. +/// \returns 0 for success, non zero code for error. +CM_API int cm_log_send_cmio_response(cm_machine *m, uint16_t reason, const unsigned char *data, size_t length, + int log_type, bool one_based, const char **access_log); /// \brief Verifies integrity of Merkle tree. -/// \param m Pointer to valid machine instance -/// \param result True if tree is self-consistent, false otherwise. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_verify_merkle_tree(const cm_machine *m, bool *result, char **err_msg); - -/// \brief Read the value of any CSR -/// \param m Pointer to valid machine instance -/// \param val Receives value read from the CSR -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_csr(const cm_machine *m, CM_PROC_CSR r, uint64_t *val, char **err_msg); - -/// \brief Write the value of any CSR -/// \param m Pointer to valid machine instance -/// \param w CSR to write -/// \param val Value to write -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_csr(cm_machine *m, CM_PROC_CSR w, uint64_t val, char **err_msg); - -/// \brief Gets the address of any CSR -/// \param w The CSR -/// \returns The address of the specified CSR -CM_API uint64_t cm_get_csr_address(CM_PROC_CSR w); +/// \param m Pointer to a valid machine instance. +/// \param result Receives true if tree is self-consistent, false otherwise. +/// \returns 0 for success, non zero code for error. +CM_API int cm_verify_merkle_tree(const cm_machine *m, bool *result); -/// \brief Read the value of a word in the machine state. -/// \param m Pointer to valid machine instance -/// \param word_address Word address (aligned to 64-bit boundary). -/// \param word_value Receives word value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -/// \warning The current implementation of this function is very slow! -CM_API int cm_read_word(const cm_machine *m, uint64_t word_address, uint64_t *word_value, char **err_msg); +/// \brief Verify if dirty page maps are consistent. +/// \param m Pointer to a valid machine instance. +/// \param result Receives true if dirty page maps are consistent, false if there is an error. +/// \returns 0 for success, non zero code for error. +CM_API int cm_verify_dirty_page_maps(const cm_machine *m, bool *result); + +/// \brief Obtains the proof for a node in the Merkle tree. +/// \param m Pointer to a valid machine instance. +/// \param address Address of target node. Must be aligned to a 2^log2_size boundary. +/// \param log2_size log2 of size subintended by target node. +/// Must be between 3 (for a word) and 64 (for the entire address space), inclusive. +/// \param proof Receives the proof as a JSON string, +/// remains valid until this same function is called again for the same machine. +/// \returns 0 for success, non zero code for error. +/// \details If the node is smaller than a page size, +/// then it must lie entirely inside the same PMA range. +CM_API int cm_get_proof(const cm_machine *m, uint64_t address, int log2_size, const char **proof); + +/// \brief Obtains the root hash of the Merkle tree. +/// \param m Pointer to a valid machine instance. +/// \param hash Valid pointer to cm_hash structure that receives the hash. +/// \returns 0 for success, non zero code for error. +CM_API int cm_get_root_hash(const cm_machine *m, cm_hash *hash); + +// ------------------------------------- +// Reading and writing /// \brief Reads a chunk of data from the machine memory. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param address Physical address to start reading. /// \param data Receives chunk of memory. /// \param length Size of chunk. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -/// \details The entire chunk, from \p address to \p address + \p length must -/// be inside the same PMA region. -CM_API int cm_read_memory(const cm_machine *m, uint64_t address, unsigned char *data, uint64_t length, char **err_msg); +/// \returns 0 for success, non zero code for error. +/// \details The entire chunk must be inside the same PMA region. +CM_API int cm_read_memory(const cm_machine *m, uint64_t address, unsigned char *data, uint64_t length); /// \brief Writes a chunk of data to the machine memory. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param address Physical address to start writing. /// \param data Source for chunk of data. /// \param length Size of chunk. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -/// \details The entire chunk, from \p address to \p address + \p length must -/// be inside the same PMA region. Moreover, this PMA must be a memory PMA, -/// and not a device PMA. -CM_API int cm_write_memory(cm_machine *m, uint64_t address, const unsigned char *data, size_t length, char **err_msg); +/// \returns 0 for success, non zero code for error. +/// \details The entire chunk must be inside the same PMA region. +/// Moreover, this PMA must be a memory PMA, and not a device PMA. +CM_API int cm_write_memory(cm_machine *m, uint64_t address, const unsigned char *data, size_t length); /// \brief Reads a chunk of data from the machine virtual memory. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param address Virtual address to start reading. /// \param data Receives chunk of memory. /// \param length Size of chunk. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_virtual_memory(const cm_machine *m, uint64_t address, unsigned char *data, uint64_t length, - char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_read_virtual_memory(const cm_machine *m, uint64_t address, unsigned char *data, uint64_t length); /// \brief Writes a chunk of data to the machine virtual memory. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param address Virtual address to start writing. /// \param data Source for chunk of data. /// \param length Size of chunk. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_virtual_memory(cm_machine *m, uint64_t address, const unsigned char *data, size_t length, - char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_write_virtual_memory(cm_machine *m, uint64_t address, const unsigned char *data, size_t length); -/// \brief Translates a virtual memory address to its corresponding physical memory address. -/// \param m Pointer to valid machine instance -/// \param vaddr Virtual address to translate. -/// \param paddr Receives the physical memory address. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_translate_virtual_address(cm_machine *m, uint64_t vaddr, uint64_t *paddr, char **err_msg); +/// \brief Read the value of a word in the machine state. +/// \param m Pointer to a valid machine instance. +/// \param address Physical address (aligned to 64-bit boundary). +/// \param value Receives the value of the word. +/// \returns 0 for success, non zero code for error. +/// \warning The current implementation of this function is very slow! +CM_API int cm_read_word(const cm_machine *m, uint64_t address, uint64_t *value); + +/// \brief Write the value of a word in the machine state. +/// \param m Pointer to a valid machine instance. +/// \param address Physical address (aligned to 64-bit boundary). +/// \param value New word value. +/// \returns 0 for success, non zero code for error. +/// \warning The current implementation of this function is very slow! +CM_API int cm_write_word(const cm_machine *m, uint64_t address, uint64_t value); /// \brief Reads the value of a general-purpose register. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param i Register index. Between 0 and X_REG_COUNT-1, inclusive. /// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_x(const cm_machine *m, int i, uint64_t *val, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_read_x(const cm_machine *m, int i, uint64_t *val); /// \brief Writes the value of a general-purpose register. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param i Register index. Between 1 and X_REG_COUNT-1, inclusive. /// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_x(cm_machine *m, int i, uint64_t val, char **err_msg); - -/// \brief Gets the address of a general-purpose register. -/// \param i Register index. Between 0 and X_REG_COUNT-1, inclusive. -/// \returns Address of the specified register -CM_API uint64_t cm_get_x_address(int i); - -/// \brief Gets the address of a general-purpose microarchitecture register. -/// \param i Register index. Between 0 and UARCH_X_REG_COUNT-1, inclusive. -/// \returns Address of the specified register -CM_API uint64_t cm_get_uarch_x_address(int i); +/// \returns 0 for success, non zero code for error. +CM_API int cm_write_x(cm_machine *m, int i, uint64_t val); /// \brief Reads the value of a floating-point register. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param i Register index. Between 0 and F_REG_COUNT-1, inclusive. /// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_f(const cm_machine *m, int i, uint64_t *val, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_read_f(const cm_machine *m, int i, uint64_t *val); /// \brief Writes the value of a floating-point register. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param i Register index. Between 0 and F_REG_COUNT-1, inclusive. /// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_f(cm_machine *m, int i, uint64_t val, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_write_f(cm_machine *m, int i, uint64_t val); -/// \brief Gets the address of a floating-point register. -/// \param i Register index. Between 0 and F_REG_COUNT-1, inclusive. -/// \returns Address of the specified register -CM_API uint64_t cm_get_f_address(int i); +/// \brief Read the value of any CSR. +/// \param m Pointer to a valid machine instance. +/// \param csr CSR to read. +/// \param val Receives value read from the CSR. +/// \returns 0 for success, non zero code for error. +CM_API int cm_read_csr(const cm_machine *m, CM_CSR csr, uint64_t *val); + +/// \brief Write the value of any CSR. +/// \param m Pointer to a valid machine instance. +/// \param csr CSR to write. +/// \param val Value to write. +/// \returns 0 for success, non zero code for error. +CM_API int cm_write_csr(cm_machine *m, CM_CSR csr, uint64_t val); /// \brief Reads the value of the pc register. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param val Receives the value of the register -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_pc(const cm_machine *m, uint64_t *val, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_read_pc(const cm_machine *m, uint64_t *val); /// \brief Writes the value of the pc register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_pc(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the fcsr register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_fcsr(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the fcsr register. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_fcsr(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the mvendorid register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_mvendorid(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Reads the value of the marchid register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_marchid(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Reads the value of the mimpid register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_mimpid(const cm_machine *m, uint64_t *val, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_write_pc(cm_machine *m, uint64_t val); /// \brief Reads the value of the mcycle register. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_mcycle(const cm_machine *m, uint64_t *val, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_read_mcycle(const cm_machine *m, uint64_t *val); /// \brief Writes the value of the mcycle register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_mcycle(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the icycleinstret register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_icycleinstret(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the icycleinstret register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_icycleinstret(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the mstatus register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_mstatus(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the mstatus register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_mstatus(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the menvcfg register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_menvcfg(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the menvcfg register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_menvcfg(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the mtvec register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_mtvec(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the mtvec register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_mtvec(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the mscratch register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_mscratch(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the mscratch register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_mscratch(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the mepc register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_mepc(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the mepc register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_mepc(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the mcause register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_mcause(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the mcause register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_mcause(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the mtval register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_mtval(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the mtval register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_mtval(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the misa register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_misa(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the misa register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_misa(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the mie register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_mie(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Reads the value of the mie register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_mie(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the mip register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_mip(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Reads the value of the mip register. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_mip(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the medeleg register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_medeleg(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the medeleg register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_medeleg(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the mideleg register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_mideleg(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the mideleg register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_mideleg(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the mcounteren register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_mcounteren(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the mcounteren register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_mcounteren(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the stvec register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_stvec(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the stvec register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_stvec(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the sscratch register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_sscratch(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the sscratch register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_sscratch(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the sepc register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_sepc(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the sepc register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_sepc(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the scause register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_scause(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the scause register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_scause(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the stval register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_stval(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the stval register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_stval(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the satp register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_satp(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the satp register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_satp(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the scounteren register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_scounteren(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the scounteren register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_scounteren(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the senvcfg register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_senvcfg(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the senvcfg register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_senvcfg(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the ilrsc register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_ilrsc(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the ilrsc register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_ilrsc(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the iflags register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_iflags(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Returns packed iflags from its component fields. -/// \param val Receives value of the register. -CM_API uint64_t cm_packed_iflags(int PRV, int X, int Y, int H); - -/// \brief Reads the value of the iflags register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_iflags(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of the iunrep register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_iunrep(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of the iunrep register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_iunrep(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of HTIF's tohost register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_htif_tohost(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Reads the value of the device field of HTIF's tohost register. -/// \param m Pointer to valid machine instance -/// \param val Receives the value of the field -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_htif_tohost_dev(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Reads the value of the command field of HTIF's tohost register. -/// \param m Pointer to valid machine instance -/// \param val Receives the value of the field -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_htif_tohost_cmd(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Reads the value of the data field of HTIF's tohost register. -/// \param m Pointer to valid machine instance -/// \param val Receives the value of the field -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_htif_tohost_data(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of HTIF's tohost register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_htif_tohost(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of HTIF's fromhost register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_htif_fromhost(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of HTIF's fromhost register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_htif_fromhost(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Writes the value of the data field in HTIF's fromhost register. -/// \param m Pointer to valid machine instance -/// \param val New value for the field. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_htif_fromhost_data(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of HTIF's halt register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_htif_ihalt(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of HTIF's halt register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_htif_ihalt(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of HTIF's console register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_htif_iconsole(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of HTIF's console register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_htif_iconsole(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of HTIF's yield register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_htif_iyield(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of HTIF's yield register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_htif_iyield(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of CLINT's mtimecmp register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_clint_mtimecmp(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of CLINT's mtimecmp register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_clint_mtimecmp(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of PLIC's girqpend register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_error_message. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_plic_girqpend(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of PLIC's girqpend register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_error_message. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_plic_girqpend(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Reads the value of PLIC's girqsrvd register. -/// \param m Pointer to valid machine instance -/// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_error_message. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_plic_girqsrvd(const cm_machine *m, uint64_t *val, char **err_msg); - -/// \brief Writes the value of PLIC's girqsrvd register. -/// \param m Pointer to valid machine instance -/// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_error_message. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_plic_girqsrvd(cm_machine *m, uint64_t val, char **err_msg); - -/// \brief Checks the value of the iflags_X flag. -/// \param m Pointer to valid machine instance -/// \param val Receives the flag value -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_iflags_X(const cm_machine *m, bool *val, char **err_msg); - -/// \brief Resets the value of the iflags_X flag. -/// \param m Pointer to valid machine instance -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_reset_iflags_X(cm_machine *m, char **err_msg); - -/// \brief Sets the iflags_X flag. -/// \param m Pointer to valid machine instance -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_set_iflags_X(cm_machine *m, char **err_msg); - -/// \brief Checks the value of the iflags_Y flag. -/// \param m Pointer to valid machine instance -/// \param val Receives the flag value -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_iflags_Y(const cm_machine *m, bool *val, char **err_msg); - -/// \brief Resets the value of the iflags_Y flag. -/// \param m Pointer to valid machine instance -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_reset_iflags_Y(cm_machine *m, char **err_msg); - -/// \brief Sets the iflags_Y flag. -/// \param m Pointer to valid machine instance -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_set_iflags_Y(cm_machine *m, char **err_msg); - -/// \brief Checks the value of the iflags_H flag. -/// \param m Pointer to valid machine instance -/// \param val Receives the flag value -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_iflags_H(const cm_machine *m, bool *val, char **err_msg); - -/// \brief Sets the iflags_H flag. -/// \param m Pointer to valid machine instance -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_set_iflags_H(cm_machine *m, char **err_msg); - -/// \brief Verify if dirty page maps are consistent. -/// \param m Pointer to valid machine instance -/// \param result True if dirty page maps are consistent, false if there is an error. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_verify_dirty_page_maps(const cm_machine *m, bool *result, char **err_msg); - -/// \brief Returns copy of initialization config. -/// \param m Pointer to valid machine instance -/// \param config Receives the initial configuration. -/// It should be deleted with cm_delete_machine_config. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -/// \details Object acquired from this function must not be changed and -/// must be deleted with cm_delete_machine_config -CM_API int cm_get_initial_config(const cm_machine *m, const cm_machine_config **config, char **err_msg); - -/// \brief Returns copy of default system config. -/// \param config Receives the default configuration. -/// It should be deleted with cm_delete_machine_config -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -/// \details Object acquired from this function must not be changed and -/// must be deleted with cm_delete_machine_config -CM_API int cm_get_default_config(const cm_machine_config **config, char **err_msg); - -/// \brief Replaces a memory range -/// \param m Pointer to valid machine instance -/// \param new_range Configuration of the new memory range -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -/// \details The machine must contain an existing memory range matching the start and length specified in new_range -CM_API int cm_replace_memory_range(cm_machine *m, const cm_memory_range_config *new_range, char **err_msg); - -/// \brief Deletes a machine memory range config -/// \returns void -CM_API void cm_delete_memory_range_config(const cm_memory_range_config *config); - -/// \brief Deletes the error message -/// \param err_msg Pointer to error message received from some other function -/// \details This C API is meant to be used for various language bindings. -/// Many of them could not directly call C free function, -/// so this is a convenience function for cleanup of error messages -CM_API void cm_delete_cstring(const char *err_msg); - -/// \brief Deletes machine runtime config -/// \returns void -CM_API void cm_delete_machine_runtime_config(const cm_machine_runtime_config *config); - -/// \brief Deletes allocated microarchitecture ram config -/// \returns void -CM_API void cm_delete_uarch_ram_config(const cm_uarch_ram_config *config); - -/// \brief Deletes allocated dhd microarchitecture config -/// \returns void -CM_API void cm_delete_uarch_config(const cm_uarch_config *config); - -/// \brief Deletes semantic version instance -/// \param m Valid pointer to the existing semantic version instance -CM_API void cm_delete_semantic_version(const cm_semantic_version *version); - -/// \brief Destroys machine -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_destroy(cm_machine *m, char **err_msg); - -/// \brief Do a snapshot of the machine -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_snapshot(cm_machine *m, char **err_msg); - -/// \brief Performs commit of the machine, discarding last snapshot. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_commit(cm_machine *m, char **err_msg); - -/// \brief Performs rollback of the machine, restoring last snapshot. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_rollback(cm_machine *m, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_write_mcycle(cm_machine *m, uint64_t val); /// \brief Reads the value of a microarchitecture general-purpose register. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param i Register index. Between 0 and UARCH_X_REG_COUNT-1, inclusive. /// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_uarch_x(const cm_machine *m, int i, uint64_t *val, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_read_uarch_x(const cm_machine *m, int i, uint64_t *val); /// \brief Writes the value of a microarchitecture general-purpose register. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param i Register index. Between 1 and UARCH_X_REG_COUNT-1, inclusive. /// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_uarch_x(cm_machine *m, int i, uint64_t val, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_write_uarch_x(cm_machine *m, int i, uint64_t val); /// \brief Reads the value of the microarchitecture pc register. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param val Receives the value of the register -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_uarch_pc(const cm_machine *m, uint64_t *val, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_read_uarch_pc(const cm_machine *m, uint64_t *val); /// \brief Writes the value of the microarchitecture pc register. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_uarch_pc(cm_machine *m, uint64_t val, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_write_uarch_pc(cm_machine *m, uint64_t val); /// \brief Reads the value of the microarchitecture cycle register. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param val Receives value of the register. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_read_uarch_cycle(const cm_machine *m, uint64_t *val, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_read_uarch_cycle(const cm_machine *m, uint64_t *val); /// \brief Writes the value of the microarchitecture cycle register. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param val New register value. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_write_uarch_cycle(cm_machine *m, uint64_t val, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_write_uarch_cycle(cm_machine *m, uint64_t val); /// \brief Gets the value of the microarchitecture halt flag. -/// \param m Pointer to valid machine instance +/// \param m Pointer to a valid machine instance. /// \param val Receives value of the halt flag. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for success, non zero code for error -CM_API int cm_read_uarch_halt_flag(const cm_machine *m, bool *val, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_read_uarch_halt_flag(const cm_machine *m, bool *val); /// \brief Sets the value of the microarchitecture halt flag. -/// \param m Pointer to valid machine instance -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for success, non zero code for error -CM_API int cm_set_uarch_halt_flag(cm_machine *m, char **err_msg); +/// \param m Pointer to a valid machine instance. +/// \returns 0 for success, non zero code for error. +CM_API int cm_set_uarch_halt_flag(cm_machine *m); -/// \brief Resets the entire uarch state to pristine values. -/// \param m Pointer to valid machine instance -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for success, non zero code for error -CM_API int cm_reset_uarch(cm_machine *m, char **err_msg); +/// \brief Translates a virtual memory address to its corresponding physical memory address. +/// \param m Pointer to a valid machine instance. +/// \param vaddr Virtual address to translate. +/// \param paddr Receives the physical memory address. +/// \returns 0 for success, non zero code for error. +CM_API int cm_translate_virtual_address(cm_machine *m, uint64_t vaddr, uint64_t *paddr); + +/// \brief Returns count of memory ranges in the machine. +/// \param m Pointer to a valid machine instance. +/// \param count Receives the memory range count. +/// \returns 0 for success, non zero code for error. +CM_API int cm_get_memory_range_count(cm_machine *m, int *count); + +/// \brief Returns memory range in the machine at given index. +/// \param m Pointer to a valid machine instance. +/// \param i Index of the memory range, must be less than cm_get_memory_range_count(). +/// \param start Receives the memory range start address. +/// \param length Receives the memory range length. +/// \param description Receives the memory range description. +/// Should not be modified or deallocated, remains valid until the machine is destroyed. +/// \returns 0 for success, non zero code for error. +CM_API int cm_get_memory_range(cm_machine *m, int i, uint64_t *start, uint64_t *length, const char **description); + +// ------------------------------------- +// Getting + +/// \brief Returns the error message set by the very last C API call. +/// \returns A C string, remains valid until next C API call that can return error codes. +/// \details It uses a thread local variable, so it's safe to call from different threads. +/// The string returned by this function must not be changed nor deallocated. +/// In case the last API call was successful it returns an empty string. +/// The error message is only updated by functions that can return a CM_ERROR code. +CM_API const char *cm_get_last_error_message(); + +/// \brief Returns a JSON string for the default machine config. +/// \returns A C string, remains valid until program ends. +/// The string returned by this function must not be changed nor deallocated. +/// The returned config is not complete to run a machine yet, configurations such as +/// ram length, ram image, flash drives, bootargs and entrypoint still need to be set. +CM_API const char *cm_get_default_config(); + +/// \brief Returns a JSON string for the default machine runtime config. +/// \returns A C string, remains valid until program ends. +/// The string returned by this function must not be changed nor deallocated. +CM_API const char *cm_get_default_runtime_config(); + +/// \brief Gets the address of a CSR. +/// \param csr The CSR register. +/// \returns The address of the specified CSR. +CM_API uint64_t cm_get_csr_address(CM_CSR csr); -/// \brief Resets the value of the microarchitecture halt flag. -/// \param m Pointer to valid machine instance -/// \param log_type Type of access log to generate. +/// \brief Gets the address of a general-purpose register. +/// \param i Register index. Between 0 and X_REG_COUNT-1, inclusive. +/// \returns Address of the specified register. +CM_API uint64_t cm_get_x_address(int i); + +/// \brief Gets the address of a floating-point register. +/// \param i Register index. Between 0 and F_REG_COUNT-1, inclusive. +/// \returns Address of the specified register. +CM_API uint64_t cm_get_f_address(int i); + +/// \brief Gets the address of a general-purpose microarchitecture register. +/// \param i Register index. Between 0 and UARCH_X_REG_COUNT-1, inclusive. +/// \returns Address of the specified register. +CM_API uint64_t cm_get_uarch_x_address(int i); + +// ------------------------------------- +// Verifying + +/// \brief Checks the internal consistency of an access log produced by cm_log_uarch_step. +/// \param access_log State access log to be verified as a JSON string. /// \param one_based Use 1-based indices when reporting errors. -/// \param access_log Receives the state access log. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for success, non zero code for error -CM_API int cm_log_uarch_reset(cm_machine *m, cm_access_log_type log_type, bool one_based, cm_access_log **access_log, - char **err_msg); - -/// \brief Runs the machine in the microarchitecture until the mcycle advances by one unit or the micro cycles counter -/// (uarch_cycle) reaches uarch_cycle_end -/// \param m Pointer to valid machine instance -/// \param mcycle_end End cycle value -/// \param status_result Receives status of machine run_uarch when not NULL -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_machine_run_uarch(cm_machine *m, uint64_t uarch_cycle_end, CM_UARCH_BREAK_REASON *status_result, - char **err_msg); - -/// \brief Returns an array with the description of each memory range in the machine. -/// \param m Pointer to valid machine instance -/// \param mrda Receives pointer to array of memory range descriptions. Must be deleted by the function caller using -/// cm_delete_memory_range_descr_array. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successful function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring. -/// err_msg can be NULL, meaning the error message won't be received. -/// \returns 0 for success, non zero code for error -CM_API int cm_get_memory_ranges(cm_machine *m, cm_memory_range_descr_array **mrda, char **err_msg); - -/// \brief Delete memory range description array acquired from cm_get_memory_ranges. -/// \param mrda Pointer to array of memory range descriptions to delete. -/// \returns void -CM_API void cm_delete_memory_range_descr_array(cm_memory_range_descr_array *mrda); +/// \returns 0 for success, non zero code for error. +CM_API int cm_verify_uarch_step_log(const char *access_log, bool one_based); -/// \brief Sends cmio response -/// \param m Pointer to valid machine instance -/// \param reason Reason for sending the response. -/// \param data Response data to send -/// \param length Length of response data. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successfull function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for success, non zero code for error -CM_API int cm_send_cmio_response(cm_machine *m, uint16_t reason, const unsigned char *data, size_t length, - char **err_msg); +/// \brief Checks the validity of a state transition produced by cm_log_uarch_step. +/// \param root_hash_before State hash before step. +/// \param access_log State access log to be verified as a JSON string. +/// \param root_hash_after State hash after step. +/// \param one_based Use 1-based indices when reporting errors. +/// \returns 0 for successful verification, non zero code for error. +CM_API int cm_verify_uarch_step_state_transition(const cm_hash *root_hash_before, const char *access_log, + const cm_hash *root_hash_after, bool one_based); -/// \brief Send cmio response and returns an access log -/// \param m Pointer to valid machine instance -/// \param reason Reason for sending the response. -/// \param data Response data to send. -/// \param length Length of response data. -/// \param log_type Type of access log to generate. +/// \brief Checks the internal consistency of an access log produced by cm_log_reset_uarch. +/// \param access_log State access log to be verified as a JSON string. /// \param one_based Use 1-based indices when reporting errors. -/// \param access_log Receives the state access log. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successfull function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for success, non zero code for error -CM_API int cm_log_send_cmio_response(cm_machine *m, uint16_t reason, const unsigned char *data, size_t length, - cm_access_log_type log_type, bool one_based, cm_access_log **access_log, char **err_msg); +/// \returns 0 for success, non zero code for error. +CM_API int cm_verify_reset_uarch_log(const char *access_log, bool one_based); -/// \brief Checks the internal consistency of an access log produced by cm_send_cmio_response +/// \brief Checks the validity of a state transition produced by cm_reset_uarch. +/// \param root_hash_before State hash before step. +/// \param access_log State access log to be verified as a JSON string. +/// \param root_hash_after State hash after step. +/// \param one_based Use 1-based indices when reporting errors. +/// \returns 0 for successful verification, non zero code for error. +CM_API int cm_verify_reset_uarch_state_transition(const cm_hash *root_hash_before, const char *access_log, + const cm_hash *root_hash_after, bool one_based); + +/// \brief Checks the internal consistency of an access log produced by cm_send_cmio_response. /// \param reason Reason for sending the response. /// \param data The response sent when the log was generated. /// \param length Length of response. -/// \param log State access log to be verified. -/// \param runtime_config Runtime configuration of the machine. +/// \param access_log State access log to be verified as a JSON string. /// \param one_based Use 1-based indices when reporting errors. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successfull function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for success, non zero code for error +/// \returns 0 for success, non zero code for error. CM_API int cm_verify_send_cmio_response_log(uint16_t reason, const unsigned char *data, size_t length, - const cm_access_log *log, const cm_machine_runtime_config *runtime_config, bool one_based, char **err_msg); + const char *access_log, bool one_based); -/// \brief Checks the validity of state transitions caused by cm_send_cmio_response +/// \brief Checks the validity of state transitions produced by cm_send_cmio_response. /// \param reason Reason for sending the response. /// \param data The response sent when the log was generated. -/// \param length Length of response +/// \param length Length of response. /// \param root_hash_before State hash before load. -/// \param log State access log to be verified. +/// \param access_log State access log to be verified as a JSON string. /// \param root_hash_after State hash after load. -/// \param runtime_config Runtime configuration of the machine. /// \param one_based Use 1-based indices when reporting errors. -/// \param err_msg Receives the error message if function execution fails -/// or NULL in case of successfull function execution. In case of failure error_msg -/// must be deleted by the function caller using cm_delete_cstring -/// \returns 0 for success, non zero code for error +/// \returns 0 for success, non zero code for error. CM_API int cm_verify_send_cmio_response_state_transition(uint16_t reason, const unsigned char *data, size_t length, - const cm_hash *root_hash_before, const cm_access_log *log, const cm_hash *root_hash_after, - const cm_machine_runtime_config *runtime_config, bool one_based, char **err_msg); + const cm_hash *root_hash_before, const char *access_log, const cm_hash *root_hash_after, bool one_based); #ifdef __cplusplus } diff --git a/src/machine-c-defines.h b/src/machine-c-defines.h deleted file mode 100644 index b899e1b36..000000000 --- a/src/machine-c-defines.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright Cartesi and individual authors (see AUTHORS) -// SPDX-License-Identifier: LGPL-3.0-or-later -// -// This program is free software: you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License as published by the Free -// Software Foundation, either version 3 of the License, or (at your option) any -// later version. -// -// This program is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -// PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License along -// with this program (see COPYING). If not, see . -// - -#ifndef MACHINE_EMULATOR_SDK_MACHINE_C_DEFINES_H -#define MACHINE_EMULATOR_SDK_MACHINE_C_DEFINES_H - -// Compiler visibility definition -#ifndef CM_API -#define CM_API __attribute__((visibility("default"))) // NOLINT(cppcoreguidelines-macro-usage) -#endif - -#define CM_MACHINE_HASH_BYTE_SIZE 32 // NOLINT(cppcoreguidelines-macro-usage, modernize-macro-to-enum) -#define CM_MACHINE_X_REG_COUNT 32 // NOLINT(cppcoreguidelines-macro-usage, modernize-macro-to-enum) -#define CM_MACHINE_F_REG_COUNT 32 // NOLINT(cppcoreguidelines-macro-usage, modernize-macro-to-enum) -#define CM_MACHINE_UARCH_X_REG_COUNT 32 // NOLINT(cppcoreguidelines-macro-usage, modernize-macro-to-enum) - -#define CM_TREE_LOG2_WORD_SIZE 3 // NOLINT(cppcoreguidelines-macro-usage, modernize-macro-to-enum) -#define CM_TREE_LOG2_PAGE_SIZE 12 // NOLINT(cppcoreguidelines-macro-usage, modernize-macro-to-enum) -#define CM_TREE_LOG2_ROOT_SIZE 64 // NOLINT(cppcoreguidelines-macro-usage, modernize-macro-to-enum) -#define CM_FLASH_DRIVE_CONFIGS_MAX_SIZE 8 // NOLINT(cppcoreguidelines-macro-usage, modernize-macro-to-enum) -#define CM_VIRTIO_CONFIGS_MAX_SIZE 16 // NOLINT(cppcoreguidelines-macro-usage, modernize-macro-to-enum) -#define CM_VIRTIO_HOSTFWD_CONFIGS_MAX_SIZE 16 // NOLINT(cppcoreguidelines-macro-usage, modernize-macro-to-enum) - -#include "machine-c-version.h" - -#endif // MACHINE_EMULATOR_SDK_MACHINE_C_DEFINES_H