From b6bec5c508f3bdd84ceaa3ebd407cb65f669df75 Mon Sep 17 00:00:00 2001 From: Muhammad Farooqi Date: Mon, 30 Jun 2025 11:08:46 +0200 Subject: [PATCH 1/2] pulse representation specs added --- include/qdmi/client.h | 142 ++++++++++++++++++++++++++++++- include/qdmi/constants.h | 179 ++++++++++++++++++++++++++++++++++++++- include/qdmi/device.h | 125 ++++++++++++++++++++++++++- include/qdmi/types.h | 28 ++++++ 4 files changed, 471 insertions(+), 3 deletions(-) diff --git a/include/qdmi/client.h b/include/qdmi/client.h index 791273ed..8eac7c3c 100644 --- a/include/qdmi/client.h +++ b/include/qdmi/client.h @@ -573,7 +573,147 @@ int QDMI_device_query_operation_property( QDMI_Device device, QDMI_Operation operation, size_t num_sites, const QDMI_Site *sites, size_t num_params, const double *params, QDMI_Operation_Property prop, size_t size, void *value, size_t *size_ret); - +/** + * @brief Query a pulse parameter property. + * @param[in] device The device to query. Must not be @c NULL. + * @param[in] parameter The pulse parameter to query. Must not be @c NULL. + * @param[in] prop The property to query. Must be one of the values specified + * for @ref QDMI_Pulse_Parameter_Property. + * @param[in] size The size of the memory pointed to by @p value in bytes. Must + * be greater or equal to the size of the return type specified for @p prop, + * except when @p value is @c NULL, in which case it is ignored. + * @param[out] value A pointer to the memory location where the value of the + * property will be stored. If this is @c NULL, it is ignored. + * @param[out] size_ret The actual size of the data being queried in bytes. If + * this is @c NULL, it is ignored. + * @return @ref QDMI_SUCCESS if the device supports the specified property and, + * when @p value is not @c NULL, the property was successfully retrieved. + * @return @ref QDMI_ERROR_NOTSUPPORTED if the device does not support the + * property. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if + * - @p device or @p parameter is @c NULL, + * - @p prop is invalid, or + * - @p value is not @c NULL and @p size is less than the size of the data + * being queried. + * @return @ref QDMI_ERROR_FATAL if an unexpected error occurred. + * @note By calling this function with @p value set to @c NULL, the function can + * be used to check if the device supports the specified property without + * retrieving the property and without the need to provide a buffer for it. + * Additionally, the size of the buffer needed to retrieve the property is + * returned in @p size_ret if @p size_ret is not @c NULL. + * @note For example, to query the value of a pulse parameter, the following + * code pattern can be used: + * ``` + * // Query the size of the property. + * size_t size; + * auto ret = QDMI_device_query_pulse_parameter_property( + * device, parameter, QDMI_PULSE_PARAMETER_PROPERTY_NAME, 0, nullptr, &size); + * // Allocate memory for the property. + * auto name = std::vector(size); + * // Query the property. + * ret = QDMI_device_query_pulse_parameter_property( + * device, parameter, QDMI_PULSE_PARAMETER_PROPERTY_NAME, size, + * static_cast(name.data()), nullptr); + * ``` + */ +int QDMI_device_query_pulse_parameter_property( + QDMI_Device device, QDMI_Pulse_Parameter parameter, + QDMI_Pulse_Parameter_Property prop, size_t size, void *value, + size_t *size_ret); +/** * @brief Query a pulse waveform property. + * @param[in] device The device to query. Must not be @c NULL. + * @param[in] waveform The pulse waveform to query. Must not be @c NULL. + * @param[in] prop The property to query. Must be one of the values specified + * for @ref QDMI_Pulse_Waveform_Property. + * @param[in] size The size of the memory pointed to by @p value in bytes. Must + * be greater or equal to the size of the return type specified for @p prop, + * except when @p value is @c NULL, in which case it is ignored. + * @param[out] value A pointer to the memory location where the value of the + * property will be stored. If this is @c NULL, it is ignored. + * @param[out] size_ret The actual size of the data being queried in bytes. If + * this is @c NULL, it is ignored. + * @return @ref QDMI_SUCCESS if the device supports the specified property and, + * when @p value is not @c NULL, the property was successfully retrieved. + * @return @ref QDMI_ERROR_NOTSUPPORTED if the device does not support the + * property. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if + * - @p device or @p waveform is @c NULL, + * - @p prop is invalid, or + * - @p value is not @c NULL and @p size is less than the size of the data + * being queried. + * @return @ref QDMI_ERROR_FATAL if an unexpected error occurred. + * @note By calling this function with @p value set to @c NULL, the function + * can be used to check if the device supports the specified property without + * retrieving the property and without the need to provide a buffer for it. + * Additionally, the size of the buffer needed to retrieve the property is + * returned in @p size_ret if @p size_ret is not @c NULL. + * @note For example, to query the name of a pulse waveform, the following code + * pattern can be used: + * ``` + * // Query the size of the property. + * size_t size; + * auto ret = QDMI_device_query_pulse_waveform_property( + * device, waveform, QDMI_PULSE_WAVEFORM_PROPERTY_NAME, 0, nullptr, &size); + * // Allocate memory for the property. + * auto name = std::vector(size); + * // Query the property. + * ret = QDMI_device_query_pulse_waveform_property( + * device, waveform, QDMI_PULSE_WAVEFORM_PROPERTY_NAME, size, + * static_cast(name.data()), nullptr); + * ``` + */ +int QDMI_device_query_pulse_waveform_property(QDMI_Device device, + QDMI_Pulse_Waveform waveform, + QDMI_Pulse_Waveform_Property prop, + size_t size, void *value, + size_t *size_ret); +/** * @brief Query a pulse implementation property. + * @param[in] device The device to query. Must not be @c NULL. + * @param[in] impl The pulse implementation to query. Must not be @c NULL. + * @param[in] prop The property to query. Must be one of the values specified + * for @ref QDMI_Pulse_Implementation_Property. + * @param[in] size The size of the memory pointed to by @p value in bytes. Must + * be greater or equal to the size of the return type specified for @p prop, + * except when @p value is @c NULL, in which case it is ignored. + * @param[out] value A pointer to the memory location where the value of the + * property will be stored. If this is @c NULL, it is ignored. + * @param[out] size_ret The actual size of the data being queried in bytes. If + * this is @c NULL, it is ignored. + * @return @ref QDMI_SUCCESS if the device supports the specified property and, + * when @p value is not @c NULL, the property was successfully retrieved. + * @return @ref QDMI_ERROR_NOTSUPPORTED if the device does not support the + * property. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if + * - @p device or @p impl is @c NULL, + * - @p prop is invalid, or + * - @p value is not @c NULL and @p size is less than the size of the data + * being queried. + * @return @ref QDMI_ERROR_FATAL if an unexpected error occurred. + * @note By calling this function with @p value set to @c NULL, the function + * can be used to check if the device supports the specified property without + * retrieving the property and without the need to provide a buffer for it. + * Additionally, the size of the buffer needed to retrieve the property is + * returned in @p size_ret if @p size_ret is not @c NULL. + * @note For example, to query the name of a pulse implementation, the following + * code pattern can be used: + * ``` + * // Query the size of the property. + * size_t size; + * auto ret = QDMI_device_query_pulse_implementation_property( + * device, impl, QDMI_PULSE_IMPLEMENTATION_PROPERTY_OPENPULSE, 0, nullptr, + * &size); + * // Allocate memory for the property. + * auto open_pulse_impl = std::vector(size); + * // Query the property. + * ret = QDMI_device_query_pulse_implementation_property( + * device, impl, QDMI_PULSE_IMPLEMENTATION_PROPERTY_NAME, size, + * static_cast(open_pulse_impl.data()), nullptr); + * ``` + */ +int QDMI_device_query_pulse_implementation_property( + QDMI_Device device, QDMI_Pulse_Implementation impl, + QDMI_Pulse_Implementation_Property prop, size_t size, void *value, + size_t *size_ret); /** @} */ // end of client_query_interface /** @defgroup client_job_interface QDMI Client Job Interface diff --git a/include/qdmi/constants.h b/include/qdmi/constants.h index 7afbb73e..2d7dba3b 100644 --- a/include/qdmi/constants.h +++ b/include/qdmi/constants.h @@ -453,6 +453,9 @@ enum QDMI_OPERATION_PROPERTY_T { QDMI_OPERATION_PROPERTY_DURATION = 3, /// `double` The fidelity of an operation. QDMI_OPERATION_PROPERTY_FIDELITY = 4, + /// @ref QDMI_Pulse_Implementation The pulse implementation of the + /// operation. + QDMI_OPERATION_PROPERTY_PULSEIMPLEMENTATION = 5, /** * @brief The maximum value of the enum. * @details It can be used by devices for bounds checking and validation of @@ -461,7 +464,7 @@ enum QDMI_OPERATION_PROPERTY_T { * @attention This value must remain the last regular member of the enum * besides the custom members and must be updated when new members are added. */ - QDMI_OPERATION_PROPERTY_MAX = 5, + QDMI_OPERATION_PROPERTY_MAX = 6, /** * @brief This enum value is reserved for a custom property. * @details The device defines the meaning and the type of this property. @@ -482,6 +485,180 @@ enum QDMI_OPERATION_PROPERTY_T { /// Operation property type. typedef enum QDMI_OPERATION_PROPERTY_T QDMI_Operation_Property; +/** + * @brief Enum of the pulse parameter properties that can be queried via @ref + * QDMI_device_session_query_pulse_parameter_property as part of the @ref + * device_interface "device interface" and via @ref + * QDMI_device_query_pulse_parameter_property as part of the @ref + * client_interface "client interface". + * @details Pulse parameters are used to define the behavior of a pulse, such as + * its amplitude, and duration. The properties of a pulse parameter can + * be queried to understand how it can be used in a pulse program. + */ +enum QDMI_PULSE_PARAMETER_PROPERTY_T { + /** + * @brief `char*` (string) The name of the pulse parameter. + * @details The name is used to identify the pulse parameter in a pulse + * program. + */ + QDMI_PULSE_PARAMETER_PROPERTY_NAME = 0, + /** + * @brief `size_t` The minimum value that the pulse parameter can take. + * @details This property indicates the minimum value that the pulse + * parameter can take. + */ + QDMI_PULSE_PARAMETER_PROPERTY_RANGEMIN = 1, + /** + * @brief `size_t` The maximum value that the pulse parameter can take. + * @details This property indicates the maximum value that the pulse + * parameter can take. + */ + QDMI_PULSE_PARAMETER_PROPERTY_RANGEMAX = 2, + /** + * @brief `bool` Whether the pulse parameter is mutable. + * @details If this property is set to true, the pulse parameter can be + * modified by the user. If it is set to false, the pulse parameter is fixed + * and cannot be changed. + */ + QDMI_PULSE_PARAMETER_PROPERTY_MUTABLE = 3, + /** + * @brief The maximum value of the enum. + * @details It can be used by devices for bounds checking and validation of + * function parameters. + */ + QDMI_PULSE_PARAMETER_PROPERTY_MAX = 4, + /** + * @brief This enum value is reserved for a custom property. + * @details The device defines the meaning and the type of this property. + * @attention The value of this enum member must not be changed to maintain + * binary compatibility. + */ + QDMI_PULSE_PARAMETER_PROPERTY_CUSTOM1 = 999999995, + /// @see QDMI_PULSE_PARAMETER_PROPERTY_CUSTOM1 + QDMI_PULSE_PARAMETER_PROPERTY_CUSTOM2 = 999999996, + /// @see QDMI_PULSE_PARAMETER_PROPERTY_CUSTOM1 + QDMI_PULSE_PARAMETER_PROPERTY_CUSTOM3 = 999999997, + /// @see QDMI_PULSE_PARAMETER_PROPERTY_CUSTOM1 + QDMI_PULSE_PARAMETER_PROPERTY_CUSTOM4 = 999999998, + /// @see QDMI_PULSE_PARAMETER_PROPERTY_CUSTOM1 + QDMI_PULSE_PARAMETER_PROPERTY_CUSTOM5 = 999999999 +}; + +/// Pulse parameter property type. +typedef enum QDMI_PULSE_PARAMETER_PROPERTY_T QDMI_Pulse_Parameter_Property; + +/** + * @brief Enum of the pulse waveform properties that can be queried via @ref + * QDMI_device_session_query_pulse_waveform_property as part of the @ref + * device_interface "device interface" and via @ref + * QDMI_device_query_pulse_waveform_property as part of the @ref + * client_interface "client interface". + * @details Pulse waveforms are used to define the shape of a pulse. The + * properties of a pulse waveform can be queried to understand how it can be + * used in a pulse program. + */ +enum QDMI_PULSE_WAVEFORM_PROPERTY_T { + /** + * @brief `char*` (string) The name is used to identify the pulse waveform. + */ + QDMI_PULSE_WAVEFORM_PROPERTY_NAME = 0, + /** + * @brief `char*` (string) The formula used to generate the pulse waveform. + */ + QDMI_PULSE_WAVEFORM_PROPERTY_FORMULA = 1, + /** + * @brief `QDMI_Pulse_Parameter*` (@ref QDMI_Pulse_Parameter list) The + * parameters of the pulse waveform. + * @details This property returns a list of pulse parameters that can be used + * to define the behavior of the pulse waveform. The list may be empty if the + * pulse waveform does not have any parameters. + */ + QDMI_PULSE_WAVEFORM_PROPERTY_PARAMETERS = 2, + /** + * @brief The maximum value of the enum. + * @details It can be used by devices for bounds checking and validation of + * function parameters. + */ + QDMI_PULSE_WAVEFORM_PROPERTY_MAX = 3, + /** + * @brief This enum value is reserved for a custom property. + * @details The device defines the meaning and the type of this property. + * @attention The value of this enum member must not be changed to maintain + * binary compatibility. + */ + QDMI_PULSE_WAVEFORM_PROPERTY_CUSTOM1 = 999999995, + /// @see QDMI_PULSE_WAVEFORM_PROPERTY_CUSTOM1 + QDMI_PULSE_WAVEFORM_PROPERTY_CUSTOM2 = 999999996, + /// @see QDMI_PULSE_WAVEFORM_PROPERTY_CUSTOM1 + QDMI_PULSE_WAVEFORM_PROPERTY_CUSTOM3 = 999999997, + /// @see QDMI_PULSE_WAVEFORM_PROPERTY_CUSTOM1 + QDMI_PULSE_WAVEFORM_PROPERTY_CUSTOM4 = 999999998, + /// @see QDMI_PULSE_WAVEFORM_PROPERTY_CUSTOM1 + QDMI_PULSE_WAVEFORM_PROPERTY_CUSTOM5 = 999999999 +}; + +/// Pulse waveform property type. +typedef enum QDMI_PULSE_WAVEFORM_PROPERTY_T QDMI_Pulse_Waveform_Property; + +/** + * @brief Enum of the pulse implementation properties that can be queried via + * @ref QDMI_device_session_query_pulse_implementation_property as part of the + * @ref device_interface "device interface" and via @ref + * QDMI_device_query_pulse_implementation_property as part of the @ref + * client_interface "client interface". + * @details Pulse implementations are used to define how a pulse is + * implemented on the device. The properties of a pulse implementation can be + * queried to query the pulse program in the desired or in the available format. + */ +enum QDMI_PULSE_IMPLEMENTATION_PROPERTY_T { + /** + * @brief `char*` (string) The pulse implementation in the Open Pulse format. + */ + QDMI_PULSE_IMPLEMENTATION_PROPERTY_OPENPULSE = 0, + /** + * @brief `QDMI_Pulse_Waveform` (@ref QDMI_Pulse_Waveform) The pulse + * implementation as pulse waveform. + * @details This property returns a pulse waveform that alongside pulse + * parameters define the pulse implementation. The corresponding pulse + * parameter values can be queried via @ref + * QDMI_PULSE_IMPLEMENTATION_PROPERTY_PULSEPARAMETERS. + */ + QDMI_PULSE_IMPLEMENTATION_PROPERTY_PULSEWAVEFORM = 1, + /** + * @brief `QDMI_Pulse_Parameter*` (@ref QDMI_Pulse_Parameter list) The + * pulse parameter values of the pulse implementation. + * @details This property returns a list of pulse parameters that are used + * to define the pulse implementation. The list may be empty if the pulse + * implementation does not have any parameters. @see + * QDMI_PULSE_IMPLEMENTATION_PROPERTY_PULSEWAVEFORM + */ + QDMI_PULSE_IMPLEMENTATION_PROPERTY_PULSEPARAMETERS = 2, + /** + * @brief The maximum value of the enum. + * @details It can be used by devices for bounds checking and validation of + * function parameters. + */ + QDMI_PULSE_IMPLEMENTATION_PROPERTY_MAX = 3, + /** + * @brief This enum value is reserved for a custom property. + * @details The device defines the meaning and the type of this property. + * @attention The value of this enum member must not be changed to maintain + * binary compatibility. + */ + QDMI_PULSE_IMPLEMENTATION_PROPERTY_CUSTOM1 = 999999995, + /// @see QDMI_PULSE_IMPLEMENTATION_PROPERTY_CUSTOM1 + QDMI_PULSE_IMPLEMENTATION_PROPERTY_CUSTOM2 = 999999996, + /// @see QDMI_PULSE_IMPLEMENTATION_PROPERTY_CUSTOM1 + QDMI_PULSE_IMPLEMENTATION_PROPERTY_CUSTOM3 = 999999997, + /// @see QDMI_PULSE_IMPLEMENTATION_PROPERTY_CUSTOM1 + QDMI_PULSE_IMPLEMENTATION_PROPERTY_CUSTOM4 = 999999998, + /// @see QDMI_PULSE_IMPLEMENTATION_PROPERTY_CUSTOM1 + QDMI_PULSE_IMPLEMENTATION_PROPERTY_CUSTOM5 = 999999999 +}; +/// Pulse implementation property type. +typedef enum QDMI_PULSE_IMPLEMENTATION_PROPERTY_T + QDMI_Pulse_Implementation_Property; + /** * @brief Enum of the status a job can have. * @details See also @ref client_job_interface for a description of the job's diff --git a/include/qdmi/device.h b/include/qdmi/device.h index ed9a4b84..ed82cc1d 100644 --- a/include/qdmi/device.h +++ b/include/qdmi/device.h @@ -351,7 +351,130 @@ int QDMI_device_session_query_operation_property( QDMI_Device_Session session, QDMI_Operation operation, size_t num_sites, const QDMI_Site *sites, size_t num_params, const double *params, QDMI_Operation_Property prop, size_t size, void *value, size_t *size_ret); - +/** + * @brief Query a pulse parameter property. + * @param[in] session The session used for the query. Must not be @c NULL. + * @param[in] parameter The pulse parameter to query. Must not be @c NULL. + * @param[in] prop The property to query. Must be one of the values specified + * for @ref QDMI_Pulse_Parameter_Property. + * @param[in] size The size of the memory pointed to by @p value in bytes. Must + * be greater or equal to the size of the return type specified for @p prop, + * except when @p value is @c NULL, in which case it is ignored. + * @param[out] value A pointer to the memory location where the value of the + * property will be stored. If this is @c NULL, it is ignored. + * @param[out] size_ret The actual size of the data being queried in bytes. If + * this is @c NULL, it is ignored. + * @return @ref QDMI_SUCCESS if the device supports the specified property and, + * when @p value is not @c NULL, the property was successfully retrieved. + * @return @ref QDMI_ERROR_NOTSUPPORTED if the device does not support the + * property. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if + * - @p session or @p parameter is @c NULL, + * - @p prop is invalid, or + * - @p value is not @c NULL and @p size is less than the size of the data + * being queried. + * @return @ref QDMI_ERROR_BADSTATE if the property cannot be queried in the + * current state of the session, for example, because the session is not + * initialized. + * @return @ref QDMI_ERROR_FATAL if an unexpected error occurred. + * @remark Calling this function with @p value set to @c NULL is expected to + * allow checking if the device supports the specified property without + * retrieving the property and without the need to provide a buffer for it. + * Additionally, the size of the buffer needed to retrieve the property is + * returned in @p size_ret if @p size_ret is not @c NULL. + * See the @ref QDMI_device_query_pulse_parameter_property documentation for an + * example. + * @attention May only be called after the session has been initialized with + * @ref QDMI_device_session_init. + */ +int QDMI_device_session_query_pulse_parameter_property( + QDMI_Device_Session session, QDMI_Pulse_Parameter parameter, + QDMI_Pulse_Parameter_Property prop, size_t size, void *value, + size_t *size_ret); +/** + * @brief Query a pulse waveform property. + * @param[in] session The session used for the query. Must not be @c NULL. + * @param[in] waveform The pulse waveform to query. Must not be @c NULL. + * @param[in] prop The property to query. Must be one of the values specified + * for @ref QDMI_Pulse_Waveform_Property. + * @param[in] size The size of the memory pointed to by @p value in bytes. Must + * be greater or equal to the size of the return type specified for @p prop, + * except when @p value is @c NULL, in which case it is ignored. + * @param[out] value A pointer to the memory location where the value of the + * property will be stored. If this is @c NULL, it is ignored. + * @param[out] size_ret The actual size of the data being queried in bytes. If + * this is @c NULL, it is ignored. + * @return @ref QDMI_SUCCESS if the device supports the specified property and, + * when @p value is not @c NULL, the property was successfully retrieved. + * @return @ref QDMI_ERROR_NOTSUPPORTED if the device does not support the + * property. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if + * - @p session or @p waveform is @c NULL, + * - @p prop is invalid, or + * - @p value is not @c NULL and @p size is less than the size of the data + * being queried. + * @return @ref QDMI_ERROR_BADSTATE if the property cannot be queried in the + * current state of the session, for example, because the session is not + * initialized. + * @return @ref QDMI_ERROR_FATAL if an unexpected error occurred. + * + * @remark Calling this function with @p value set to @c NULL is expected to + * allow checking if the device supports the specified property without + * retrieving the property and without the need to provide a buffer for it. + * Additionally, the size of the buffer needed to retrieve the property is + * returned in @p size_ret if @p size_ret is not @c NULL. + * + * See the QDMI_device_query_pulse_waveform_property documentation for an + * example. + * + * May only be called after the session has been initialized with + * @ref QDMI_device_session_init. + */ +int QDMI_device_session_query_pulse_waveform_property( + QDMI_Device_Session session, QDMI_Pulse_Waveform waveform, + QDMI_Pulse_Waveform_Property prop, size_t size, void *value, + size_t *size_ret); +/** + * @brief Query a pulse implementation property. + * @param[in] session The session used for the query. Must not be @c NULL. + * @param[in] implementation The pulse implementation to query. Must not be @c + * NULL. + * @param[in] prop The property to query. Must be one of the values specified + * for @ref QDMI_Pulse_Implementation_Property. + * @param[in] size The size of the memory pointed to by @p value in bytes. Must + * be greater or equal to the size of the return type specified for @p prop, + * except when @p value is @c NULL, in which case it is ignored. + * @param[out] value A pointer to the memory location where the value of the + * property will be stored. If this is @c NULL, it is ignored. + * @param[out] size_ret The actual size of the data being queried in bytes. If + * this is @c NULL, it is ignored. + * @return @ref QDMI_SUCCESS if the device supports the specified property and, + * when @p value is not @c NULL, the property was successfully retrieved. + * @return @ref QDMI_ERROR_NOTSUPPORTED if the device does not support the + * property. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if + * - @p session or @p implementation is @c NULL, + * - @p prop is invalid, or + * - @p value is not @c NULL and @p size is less than the size of the data + * being queried. + * @return @ref QDMI_ERROR_BADSTATE if the property cannot be queried in the + * current state of the session, for example, because the session is not + * initialized. + * @return @ref QDMI_ERROR_FATAL if an unexpected error occurred. + * @remark Calling this function with @p value set to @c NULL is expected to + * allow checking if the device supports the specified property without + * retrieving the property and without the need to provide a buffer for it. + * Additionally, the size of the buffer needed to retrieve the property is + * returned in @p size_ret if @p size_ret is not @c NULL. + * See the @ref QDMI_device_query_pulse_implementation_property + * documentation for an example. + * @attention May only be called after the session has been initialized with + * @ref QDMI_device_session_init. + */ +int QDMI_device_session_query_pulse_implementation_property( + QDMI_Device_Session session, QDMI_Pulse_Implementation implementation, + QDMI_Pulse_Implementation_Property prop, size_t size, void *value, + size_t *size_ret); /** @} */ // end of device_query_interface /** @defgroup device_job_interface QDMI Device Job Interface diff --git a/include/qdmi/types.h b/include/qdmi/types.h index 5bdd1c9b..aa888a63 100644 --- a/include/qdmi/types.h +++ b/include/qdmi/types.h @@ -71,6 +71,34 @@ typedef struct QDMI_Site_impl_d *QDMI_Site; */ typedef struct QDMI_Operation_impl_d *QDMI_Operation; +/** + * @brief A handle for a pulse parameter. + * @details An opaque pointer to an implementation of the QDMI pulse parameter + * concept. A pulse parameter is a variable that can be adjusted to modify the + * behavior of a pulse. This includes parameters such as amplitude, and + * duration. Each implementation of the @ref device_interface "QDMI Device + * Interface" defines the actual implementation of the concept. + */ +typedef struct QDMI_Pulse_Parameter_impl_d *QDMI_Pulse_Parameter; + +/** + * @brief A handle for a pulse waveform. + * @details An opaque pointer to a QDMI pulse waveform concept. + * A pulse waveform is a representation of the shape of a pulse in + * time. Each implementation of the @ref device_interface "QDMI Device + * Interface" defines the actual implementation of the concept. + */ +typedef struct QDMI_Pulse_Waveform_impl_d *QDMI_Pulse_Waveform; + +/** + * @brief A handle for a pulse implementation. + * @details An opaque pointer to a pulse implementation of a QDMI operation. + * A pulse implementation is a specific way of implementing a pulse on a device, + * which may include details such as the waveform used, the parameters of the + * pulse. Each implementation of the @ref device_interface "QDMI Device + * Interface" defines the actual implementation of the concept. + */ +typedef struct QDMI_Pulse_Implementation_impl_d *QDMI_Pulse_Implementation; // NOLINTEND(modernize-use-using) #ifdef __cplusplus From ddd6169a091b554f2ab4b273825ef52ea3dcd354 Mon Sep 17 00:00:00 2001 From: Muhammad Farooqi Date: Fri, 4 Jul 2025 00:34:14 +0200 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9C=A8added=20example=20implementation?= =?UTF-8?q?=20and=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmake/prefix_defs.txt | 9 ++ examples/device/c/device.c | 30 ++++- examples/device/cxx/device.cpp | 160 ++++++++++++++++++++++- examples/driver/qdmi_example_driver.cpp | 52 +++++++- examples/fomac/example_fomac.cpp | 139 ++++++++++++++++++++ examples/fomac/example_fomac.hpp | 31 +++++ include/qdmi/constants.h | 8 +- templates/device/src/my_device.cpp | 38 ++++++ templates/device/test/test_my_device.cpp | 22 ++++ test/test_qdmi.cpp | 49 ++++++- test/utils/test_defs.cpp.in | 6 + test/utils/test_impl.cpp | 1 + test/utils/test_impl.hpp | 1 + 13 files changed, 537 insertions(+), 9 deletions(-) diff --git a/cmake/prefix_defs.txt b/cmake/prefix_defs.txt index 1908e738..f657dc5a 100644 --- a/cmake/prefix_defs.txt +++ b/cmake/prefix_defs.txt @@ -16,6 +16,9 @@ QDMI_device_job_get_results QDMI_device_session_query_device_property QDMI_device_session_query_site_property QDMI_device_session_query_operation_property +QDMI_device_session_query_pulse_parameter_property +QDMI_device_session_query_pulse_waveform_property +QDMI_device_session_query_pulse_implementation_property QDMI_Device_Session QDMI_Device_Session_impl_d QDMI_Device_Job @@ -24,3 +27,9 @@ QDMI_Site QDMI_Site_impl_d QDMI_Operation QDMI_Operation_impl_d +QDMI_Pulse_Parameter +QDMI_Pulse_Parameter_impl_d +QDMI_Pulse_Waveform +QDMI_Pulse_Waveform_impl_d +QDMI_Pulse_Implementation +QDMI_Pulse_Implementation_impl_d diff --git a/examples/device/c/device.c b/examples/device/c/device.c index e0f3f4f1..c336d480 100644 --- a/examples/device/c/device.c +++ b/examples/device/c/device.c @@ -23,6 +23,8 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "c_qdmi/device.h" +#include "c_qdmi/types.h" + #include #include #include @@ -727,7 +729,7 @@ int C_QDMI_device_session_query_device_property(C_QDMI_Device_Session session, ADD_SINGLE_VALUE_PROPERTY( QDMI_DEVICE_PROPERTY_PULSESUPPORT, QDMI_Device_Pulse_Support_Level, - QDMI_DEVICE_PULSE_SUPPORT_LEVEL_NONE, prop, size, value, size_ret) + QDMI_DEVICE_PULSE_SUPPORT_LEVEL_SITE, prop, size, value, size_ret) return QDMI_ERROR_NOTSUPPORTED; } /// [DOXYGEN FUNCTION END] @@ -846,3 +848,29 @@ int C_QDMI_device_session_query_operation_property( } return QDMI_ERROR_NOTSUPPORTED; } /// [DOXYGEN FUNCTION END] + +struct C_QDMI_Pulse_Implementation_impl_d {}; +struct C_QDMI_Pulse_Waveform_impl_t {}; +struct C_QDMI_Pulse_Implementation_impl_t {}; + +int C_QDMI_device_session_query_pulse_parameter_property( + C_QDMI_Device_Session session, C_QDMI_Pulse_Parameter param, + const QDMI_Pulse_Parameter_Property prop, const size_t size, void *value, + size_t *size_ret) { + + return QDMI_ERROR_NOTSUPPORTED; +} /// [DOXYGEN FUNCTION END] + +int C_QDMI_device_session_query_pulse_waveform_property( + C_QDMI_Device_Session session, C_QDMI_Pulse_Waveform waveform, + const QDMI_Pulse_Waveform_Property prop, const size_t size, void *value, + size_t *size_ret) { + return QDMI_ERROR_NOTSUPPORTED; +} /// [DOXYGEN FUNCTION END] + +int C_QDMI_device_session_query_pulse_implementation_property( + C_QDMI_Device_Session session, C_QDMI_Pulse_Implementation impl, + const QDMI_Pulse_Implementation_Property prop, const size_t size, + void *value, size_t *size_ret) { + return QDMI_ERROR_NOTSUPPORTED; +} /// [DOXYGEN FUNCTION END] diff --git a/examples/device/cxx/device.cpp b/examples/device/cxx/device.cpp index be7a53f4..b996f01b 100644 --- a/examples/device/cxx/device.cpp +++ b/examples/device/cxx/device.cpp @@ -24,6 +24,9 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "cxx_qdmi/device.h" +#include "cxx_qdmi/types.h" +#include "qdmi/constants.h" + #include #include #include @@ -36,6 +39,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include #include #include +#include #include #include #include @@ -78,6 +82,17 @@ struct CXX_QDMI_Operation_impl_d { std::string name; }; +struct CXX_QDMI_Pulse_Parameter_impl_d { + std::string name; +}; + +struct CXX_QDMI_Pulse_Waveform_impl_d { + std::string name; +}; + +struct CXX_QDMI_Pulse_Implementation_impl_d { + std::string operation_name; +}; namespace { /** * @brief Static function to maintain the device state. @@ -212,7 +227,57 @@ const std::unordered_map< {{CXX_DEVICE_SITES[0], CXX_DEVICE_SITES[4]}, 0.95}}}, // No need to specify single-qubit fidelities here }; -} // namespace + +const CXX_QDMI_Pulse_Parameter_impl_d AMPLITUDE{"A"}; +const CXX_QDMI_Pulse_Parameter_impl_d TIME{"t"}; +const CXX_QDMI_Pulse_Parameter_impl_d SIGMA{"sigma"}; + +const CXX_QDMI_Pulse_Waveform_impl_d GAUSSIAN{"gaussian"}; + +std::array + GAUSSIAN_PULSE_PARAMETERS = {&LITUDE, &TIME, &SIGMA}; + +const std::unordered_map> + GAUSSIAN_PULSE_PARAMETERS_PROPERTIES = { + {&LITUDE, {0.3, 0.7, true}}, + {&TIME, + {-std::numeric_limits::infinity(), + std::numeric_limits::infinity(), true}}, + {&SIGMA, {10.0, 20.0, true}}, +}; +const std::unordered_map< + const CXX_QDMI_Pulse_Waveform_impl_d *, + std::pair>> + PULSE_WAVEFORMS = { + {&GAUSSIAN, {"A * e^(-(t / sigma)^2)", GAUSSIAN_PULSE_PARAMETERS}}}; + +const CXX_QDMI_Pulse_Implementation_impl_d RX_PULSE_IMPLEMENTATION = {"rx"}; +const CXX_QDMI_Pulse_Implementation_impl_d RY_PULSE_IMPLEMENTATION = {"ry"}; +const CXX_QDMI_Pulse_Implementation_impl_d RZ_PULSE_IMPLEMENTATION = {"rz"}; +const CXX_QDMI_Pulse_Implementation_impl_d CX_PULSE_IMPLEMENTATION = {"cx"}; + +const std::unordered_map + OPERATION_PULSE_IMPLEMENTATIONS = { + {CXX_DEVICE_OPERATIONS[0], &RX_PULSE_IMPLEMENTATION}, + {CXX_DEVICE_OPERATIONS[1], &RY_PULSE_IMPLEMENTATION}, + {CXX_DEVICE_OPERATIONS[2], &RZ_PULSE_IMPLEMENTATION}, + {CXX_DEVICE_OPERATIONS[3], &CX_PULSE_IMPLEMENTATION}}; + +const std::unordered_map< + const CXX_QDMI_Pulse_Implementation_impl_d *, + std::pair>> + OPERATION_PULSE_IMPLEMENTATIONS_PROPERTIES = { + {&RX_PULSE_IMPLEMENTATION, {&GAUSSIAN, GAUSSIAN_PULSE_PARAMETERS}}, + {&RY_PULSE_IMPLEMENTATION, {&GAUSSIAN, GAUSSIAN_PULSE_PARAMETERS}}, + {&RZ_PULSE_IMPLEMENTATION, {&GAUSSIAN, GAUSSIAN_PULSE_PARAMETERS}}, + {&CX_PULSE_IMPLEMENTATION, {&GAUSSIAN, GAUSSIAN_PULSE_PARAMETERS}}, +}; + +}; // namespace // NOLINTBEGIN(bugprone-macro-parentheses) #define ADD_SINGLE_VALUE_PROPERTY(prop_name, prop_type, prop_value, prop, \ @@ -776,7 +841,7 @@ int CXX_QDMI_device_session_query_device_property( ADD_SINGLE_VALUE_PROPERTY( QDMI_DEVICE_PROPERTY_PULSESUPPORT, QDMI_Device_Pulse_Support_Level, - QDMI_DEVICE_PULSE_SUPPORT_LEVEL_NONE, prop, size, value, size_ret) + QDMI_DEVICE_PULSE_SUPPORT_LEVEL_SITE, prop, size, value, size_ret) return QDMI_ERROR_NOTSUPPORTED; } /// [DOXYGEN FUNCTION END] @@ -821,10 +886,17 @@ int CXX_QDMI_device_session_query_operation_property( prop != QDMI_OPERATION_PROPERTY_CUSTOM5)) { return QDMI_ERROR_INVALIDARGUMENT; } + // General properties ADD_STRING_PROPERTY(QDMI_OPERATION_PROPERTY_NAME, OPERATION_PROPERTIES.at(operation).first.c_str(), prop, size, value, size_ret) + ADD_SINGLE_VALUE_PROPERTY(QDMI_OPERATION_PROPERTY_PULSEIMPLEMENTATION, + CXX_QDMI_Pulse_Implementation, + const_cast( + OPERATION_PULSE_IMPLEMENTATIONS.at(operation)), + prop, size, value, size_ret) + if (operation == CXX_DEVICE_OPERATIONS[3]) { if (sites != nullptr && num_sites != 2) { return QDMI_ERROR_INVALIDARGUMENT; @@ -873,3 +945,87 @@ int CXX_QDMI_device_session_query_operation_property( } return QDMI_ERROR_NOTSUPPORTED; } /// [DOXYGEN FUNCTION END] + +int CXX_QDMI_device_session_query_pulse_parameter_property( + CXX_QDMI_Device_Session session, CXX_QDMI_Pulse_Parameter param, + const QDMI_Pulse_Parameter_Property prop, const size_t size, void *value, + size_t *size_ret) { + if (session == nullptr || (value != nullptr && size == 0) || + (prop >= QDMI_PULSE_PARAMETER_PROPERTY_MAX && + prop != QDMI_PULSE_PARAMETER_PROPERTY_CUSTOM1 && + prop != QDMI_PULSE_PARAMETER_PROPERTY_CUSTOM2 && + prop != QDMI_PULSE_PARAMETER_PROPERTY_CUSTOM3 && + prop != QDMI_PULSE_PARAMETER_PROPERTY_CUSTOM4 && + prop != QDMI_PULSE_PARAMETER_PROPERTY_CUSTOM5)) { + return QDMI_ERROR_INVALIDARGUMENT; + } + + auto [range_min, range_max, is_mutable] = + GAUSSIAN_PULSE_PARAMETERS_PROPERTIES.at(param); + + ADD_STRING_PROPERTY(QDMI_PULSE_PARAMETER_PROPERTY_NAME, param->name.c_str(), + prop, size, value, size_ret) + ADD_SINGLE_VALUE_PROPERTY(QDMI_PULSE_PARAMETER_PROPERTY_RANGEMIN, double, + range_min, prop, size, value, size_ret) + ADD_SINGLE_VALUE_PROPERTY(QDMI_PULSE_PARAMETER_PROPERTY_RANGEMAX, double, + range_max, prop, size, value, size_ret) + ADD_SINGLE_VALUE_PROPERTY(QDMI_PULSE_PARAMETER_PROPERTY_MUTABLE, bool, + is_mutable, prop, size, value, size_ret) + + return QDMI_ERROR_NOTSUPPORTED; +} /// [DOXYGEN FUNCTION END] + +int CXX_QDMI_device_session_query_pulse_waveform_property( + CXX_QDMI_Device_Session session, CXX_QDMI_Pulse_Waveform waveform, + const QDMI_Pulse_Waveform_Property prop, const size_t size, void *value, + size_t *size_ret) { + if (session == nullptr || waveform == nullptr || + (value != nullptr && size == 0) || + (prop >= QDMI_PULSE_WAVEFORM_PROPERTY_MAX && + prop != QDMI_PULSE_WAVEFORM_PROPERTY_CUSTOM1 && + prop != QDMI_PULSE_WAVEFORM_PROPERTY_CUSTOM2 && + prop != QDMI_PULSE_WAVEFORM_PROPERTY_CUSTOM3 && + prop != QDMI_PULSE_WAVEFORM_PROPERTY_CUSTOM4 && + prop != QDMI_PULSE_WAVEFORM_PROPERTY_CUSTOM5)) { + return QDMI_ERROR_INVALIDARGUMENT; + } + + ADD_STRING_PROPERTY(QDMI_PULSE_WAVEFORM_PROPERTY_NAME, waveform->name.c_str(), + prop, size, value, size_ret) + ADD_STRING_PROPERTY(QDMI_PULSE_WAVEFORM_PROPERTY_FORMULA, + PULSE_WAVEFORMS.at(waveform).first.c_str(), prop, size, + value, size_ret) + ADD_LIST_PROPERTY( + QDMI_PULSE_WAVEFORM_PROPERTY_PARAMETERS, CXX_QDMI_Pulse_Parameter, + PULSE_WAVEFORMS.at(waveform).second, prop, size, value, size_ret) + + return QDMI_ERROR_NOTSUPPORTED; +} /// [DOXYGEN FUNCTION END] + +int CXX_QDMI_device_session_query_pulse_implementation_property( + CXX_QDMI_Device_Session session, CXX_QDMI_Pulse_Implementation impl, + const QDMI_Pulse_Implementation_Property prop, const size_t size, + void *value, size_t *size_ret) { + if (session == nullptr || impl == nullptr || + (value != nullptr && size == 0) || + (prop >= QDMI_PULSE_IMPLEMENTATION_PROPERTY_MAX && + prop != QDMI_PULSE_IMPLEMENTATION_PROPERTY_CUSTOM1 && + prop != QDMI_PULSE_IMPLEMENTATION_PROPERTY_CUSTOM2 && + prop != QDMI_PULSE_IMPLEMENTATION_PROPERTY_CUSTOM3 && + prop != QDMI_PULSE_IMPLEMENTATION_PROPERTY_CUSTOM4 && + prop != QDMI_PULSE_IMPLEMENTATION_PROPERTY_CUSTOM5)) { + return QDMI_ERROR_INVALIDARGUMENT; + } + ADD_SINGLE_VALUE_PROPERTY( + QDMI_PULSE_IMPLEMENTATION_PROPERTY_PULSEWAVEFORM, CXX_QDMI_Pulse_Waveform, + const_cast( + OPERATION_PULSE_IMPLEMENTATIONS_PROPERTIES.at(impl).first), + prop, size, value, size_ret) + + ADD_LIST_PROPERTY(QDMI_PULSE_IMPLEMENTATION_PROPERTY_PULSEPARAMETERS, + CXX_QDMI_Pulse_Parameter, + OPERATION_PULSE_IMPLEMENTATIONS_PROPERTIES.at(impl).second, + prop, size, value, size_ret) + + return QDMI_ERROR_NOTSUPPORTED; +} /// [DOXYGEN FUNCTION END] diff --git a/examples/driver/qdmi_example_driver.cpp b/examples/driver/qdmi_example_driver.cpp index 0073f7b1..338fc6a5 100644 --- a/examples/driver/qdmi_example_driver.cpp +++ b/examples/driver/qdmi_example_driver.cpp @@ -24,6 +24,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "qdmi/client.h" #include "qdmi/device.h" +#include "qdmi/types.h" #include #include @@ -102,7 +103,18 @@ struct QDMI_Library { /// Function pointer to @ref QDMI_device_session_query_operation_property. decltype(QDMI_device_session_query_operation_property) *device_session_query_operation_property{}; - + /// Function pointer to @ref + /// QDMI_device_session_query_pulse_parameter_property. + decltype(QDMI_device_session_query_pulse_parameter_property) + *device_session_query_pulse_parameter_property{}; + /// Function pointer to @ref + /// QDMI_device_session_query_pulse_waveform_property. + decltype(QDMI_device_session_query_pulse_waveform_property) + *device_session_query_pulse_waveform_property{}; + /// Function pointer to @ref + /// QDMI_device_session_query_pulse_implementation_property. + decltype(QDMI_device_session_query_pulse_implementation_property) + *device_session_query_pulse_implementation_property{}; // default constructor QDMI_Library() = default; @@ -219,6 +231,10 @@ void QDMI_library_load(const std::string &lib_name, const std::string &prefix) { LOAD_SYMBOL(library, prefix, device_session_query_device_property) LOAD_SYMBOL(library, prefix, device_session_query_site_property) LOAD_SYMBOL(library, prefix, device_session_query_operation_property) + LOAD_SYMBOL(library, prefix, device_session_query_pulse_parameter_property) + LOAD_SYMBOL(library, prefix, device_session_query_pulse_waveform_property) + LOAD_SYMBOL(library, prefix, + device_session_query_pulse_implementation_property) // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast) } catch (const std::exception &) { @@ -528,3 +544,37 @@ int QDMI_device_query_operation_property( device->device_session, operation, num_sites, sites, num_params, params, prop, size, value, size_ret); } + +int QDMI_device_query_pulse_parameter_property( + QDMI_Device device, QDMI_Pulse_Parameter parameter, + QDMI_Pulse_Parameter_Property prop, const size_t size, void *value, + size_t *size_ret) { + if (device == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + return device->library->device_session_query_pulse_parameter_property( + device->device_session, parameter, prop, size, value, size_ret); +} + +int QDMI_device_query_pulse_waveform_property(QDMI_Device device, + QDMI_Pulse_Waveform waveform, + QDMI_Pulse_Waveform_Property prop, + const size_t size, void *value, + size_t *size_ret) { + if (device == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + return device->library->device_session_query_pulse_waveform_property( + device->device_session, waveform, prop, size, value, size_ret); +} + +int QDMI_device_query_pulse_implementation_property( + QDMI_Device device, QDMI_Pulse_Implementation implementation, + QDMI_Pulse_Implementation_Property prop, const size_t size, void *value, + size_t *size_ret) { + if (device == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + return device->library->device_session_query_pulse_implementation_property( + device->device_session, implementation, prop, size, value, size_ret); +} diff --git a/examples/fomac/example_fomac.cpp b/examples/fomac/example_fomac.cpp index 440fdb77..12e85154 100644 --- a/examples/fomac/example_fomac.cpp +++ b/examples/fomac/example_fomac.cpp @@ -199,3 +199,142 @@ auto FoMaC::get_parameters_num(const QDMI_Operation &op) const -> size_t { throw_if_error(ret, "Failed to query the parameter number"); return parameters_num; } + +auto FoMaC::get_operation_pulse_implementation(const QDMI_Operation &op) const + -> QDMI_Pulse_Implementation { + size_t size = 0; + int ret = QDMI_device_query_operation_property( + device, op, 0, nullptr, 0, nullptr, + QDMI_OPERATION_PROPERTY_PULSEIMPLEMENTATION, 0, nullptr, &size); + throw_if_error(ret, + "Failed to query the operation pulse implementation size"); + QDMI_Pulse_Implementation impl = static_cast( + malloc(sizeof(QDMI_Pulse_Implementation))); + ret = QDMI_device_query_operation_property( + device, op, 0, nullptr, 0, nullptr, + QDMI_OPERATION_PROPERTY_PULSEIMPLEMENTATION, sizeof(impl), &impl, + nullptr); + throw_if_error(ret, "Failed to query the operation pulse implementation"); + return impl; +} + +auto FoMaC::get_pulse_waveform(const QDMI_Pulse_Implementation &impl) const + -> QDMI_Pulse_Waveform { + size_t size = 0; + int ret = QDMI_device_query_pulse_implementation_property( + device, impl, QDMI_PULSE_IMPLEMENTATION_PROPERTY_PULSEWAVEFORM, 0, + nullptr, &size); + throw_if_error(ret, "Failed to query the pulse waveform size."); + QDMI_Pulse_Waveform waveform = + static_cast(malloc(sizeof(QDMI_Pulse_Waveform))); + ret = QDMI_device_query_pulse_implementation_property( + device, impl, QDMI_PULSE_IMPLEMENTATION_PROPERTY_PULSEWAVEFORM, size, + &waveform, nullptr); + throw_if_error(ret, "Failed to query the pulse waveform."); + return waveform; +} + +auto FoMaC::get_pulse_parameters(const QDMI_Pulse_Implementation &impl) const + -> std::vector { + size_t size = 0; + int ret = QDMI_device_query_pulse_implementation_property( + device, impl, QDMI_PULSE_IMPLEMENTATION_PROPERTY_PULSEPARAMETERS, 0, + nullptr, &size); + throw_if_error(ret, "Failed to query the pulse parameters size."); + std::vector params(size / sizeof(QDMI_Pulse_Parameter)); + ret = QDMI_device_query_pulse_implementation_property( + device, impl, QDMI_PULSE_IMPLEMENTATION_PROPERTY_PULSEPARAMETERS, size, + static_cast(params.data()), nullptr); + throw_if_error(ret, "Failed to query the pulse parameters."); + return params; +} + +auto FoMaC::get_pulse_parameter_name(const QDMI_Pulse_Parameter ¶m) const + -> std::string { + size_t name_length = 0; + int ret = QDMI_device_query_pulse_parameter_property( + device, param, QDMI_PULSE_PARAMETER_PROPERTY_NAME, 0, nullptr, + &name_length); + throw_if_error(ret, "Failed to query the pulse parameter name length."); + std::string name(name_length - 1, '\0'); + ret = QDMI_device_query_pulse_parameter_property( + device, param, QDMI_PULSE_PARAMETER_PROPERTY_NAME, name_length, + name.data(), nullptr); + throw_if_error(ret, "Failed to query the pulse parameter name."); + return name; +} + +auto FoMaC::get_pulse_parameter_rangemin( + const QDMI_Pulse_Parameter ¶m) const -> double { + double range_min = 0; + int ret = QDMI_device_query_pulse_parameter_property( + device, param, QDMI_PULSE_PARAMETER_PROPERTY_RANGEMIN, sizeof(double), + &range_min, nullptr); + throw_if_error(ret, "Failed to query the pulse parameter range minimum."); + return range_min; +} + +auto FoMaC::get_pulse_parameter_rangemax( + const QDMI_Pulse_Parameter ¶m) const -> double { + double range_max = 0; + int ret = QDMI_device_query_pulse_parameter_property( + device, param, QDMI_PULSE_PARAMETER_PROPERTY_RANGEMAX, sizeof(double), + &range_max, nullptr); + throw_if_error(ret, "Failed to query the pulse parameter range maximum."); + return range_max; +} + +auto FoMaC::get_pulse_parameter_ismutable( + const QDMI_Pulse_Parameter ¶m) const -> bool { + bool is_mutable = false; + int ret = QDMI_device_query_pulse_parameter_property( + device, param, QDMI_PULSE_PARAMETER_PROPERTY_MUTABLE, sizeof(bool), + &is_mutable, nullptr); + throw_if_error(ret, "Failed to query the pulse parameter mutability."); + return is_mutable; +} + +auto FoMaC::get_pulse_waveform_name(const QDMI_Pulse_Waveform &waveform) const + -> std::string { + size_t name_length = 0; + int ret = QDMI_device_query_pulse_waveform_property( + device, waveform, QDMI_PULSE_WAVEFORM_PROPERTY_NAME, 0, nullptr, + &name_length); + throw_if_error(ret, "Failed to query the pulse waveform name length."); + std::string name(name_length - 1, '\0'); + ret = QDMI_device_query_pulse_waveform_property( + device, waveform, QDMI_PULSE_WAVEFORM_PROPERTY_NAME, name_length, + name.data(), nullptr); + throw_if_error(ret, "Failed to query the pulse waveform name."); + return name; +} + +auto FoMaC::get_pulse_waveform_formula( + const QDMI_Pulse_Waveform &waveform) const -> std::string { + size_t formula_length = 0; + int ret = QDMI_device_query_pulse_waveform_property( + device, waveform, QDMI_PULSE_WAVEFORM_PROPERTY_FORMULA, 0, nullptr, + &formula_length); + throw_if_error(ret, "Failed to query the pulse waveform formula length."); + std::string formula(formula_length - 1, '\0'); + ret = QDMI_device_query_pulse_waveform_property( + device, waveform, QDMI_PULSE_WAVEFORM_PROPERTY_FORMULA, formula_length, + formula.data(), nullptr); + throw_if_error(ret, "Failed to query the pulse waveform formula."); + return formula; +} + +auto FoMaC::get_pulse_waveform_parameters(const QDMI_Pulse_Waveform &waveform) + const -> std::vector { + size_t size = 0; + int ret = QDMI_device_query_pulse_waveform_property( + device, waveform, QDMI_PULSE_WAVEFORM_PROPERTY_PARAMETERS, 0, nullptr, + &size); + throw_if_error(ret, "Failed to query the pulse waveform parameters size."); + std::vector params(size / sizeof(QDMI_Pulse_Parameter)); + ret = QDMI_device_query_pulse_waveform_property( + device, waveform, QDMI_PULSE_WAVEFORM_PROPERTY_PARAMETERS, size, + static_cast(params.data()), nullptr); + throw_if_error(ret, "Failed to query the pulse waveform parameters."); + return params; +} diff --git a/examples/fomac/example_fomac.hpp b/examples/fomac/example_fomac.hpp index c97885b6..57fbfbaa 100644 --- a/examples/fomac/example_fomac.hpp +++ b/examples/fomac/example_fomac.hpp @@ -63,4 +63,35 @@ class FoMaC { [[nodiscard]] auto get_parameters_num(const QDMI_Operation &op) const -> size_t; + [[nodiscard]] auto + get_operation_pulse_implementation(const QDMI_Operation &op) const + -> QDMI_Pulse_Implementation; + [[nodiscard]] auto + get_pulse_waveform(const QDMI_Pulse_Implementation &impl) const + -> QDMI_Pulse_Waveform; + [[nodiscard]] auto + get_pulse_parameters(const QDMI_Pulse_Implementation &impl) const + -> std::vector; + + [[nodiscard]] auto + get_pulse_parameter_name(const QDMI_Pulse_Parameter ¶m) const + -> std::string; + [[nodiscard]] auto + get_pulse_parameter_rangemin(const QDMI_Pulse_Parameter ¶m) const + -> double; + [[nodiscard]] auto + get_pulse_parameter_rangemax(const QDMI_Pulse_Parameter ¶m) const + -> double; + [[nodiscard]] auto + get_pulse_parameter_ismutable(const QDMI_Pulse_Parameter ¶m) const + -> bool; + [[nodiscard]] auto + get_pulse_waveform_name(const QDMI_Pulse_Waveform &waveform) const + -> std::string; + [[nodiscard]] auto + get_pulse_waveform_formula(const QDMI_Pulse_Waveform &waveform) const + -> std::string; + [[nodiscard]] auto + get_pulse_waveform_parameters(const QDMI_Pulse_Waveform &waveform) const + -> std::vector; }; diff --git a/include/qdmi/constants.h b/include/qdmi/constants.h index 2d7dba3b..8086b93d 100644 --- a/include/qdmi/constants.h +++ b/include/qdmi/constants.h @@ -498,18 +498,18 @@ typedef enum QDMI_OPERATION_PROPERTY_T QDMI_Operation_Property; enum QDMI_PULSE_PARAMETER_PROPERTY_T { /** * @brief `char*` (string) The name of the pulse parameter. - * @details The name is used to identify the pulse parameter in a pulse - * program. + * @details The name is used to identify the parameter in a pulse + * waveform formula @see QDMI_PULSE_WAVEFORM_PROPERTY_FORMULA. */ QDMI_PULSE_PARAMETER_PROPERTY_NAME = 0, /** - * @brief `size_t` The minimum value that the pulse parameter can take. + * @brief `double` The minimum value that the pulse parameter can take. * @details This property indicates the minimum value that the pulse * parameter can take. */ QDMI_PULSE_PARAMETER_PROPERTY_RANGEMIN = 1, /** - * @brief `size_t` The maximum value that the pulse parameter can take. + * @brief `double` The maximum value that the pulse parameter can take. * @details This property indicates the maximum value that the pulse * parameter can take. */ diff --git a/templates/device/src/my_device.cpp b/templates/device/src/my_device.cpp index 062f312f..08f4574b 100644 --- a/templates/device/src/my_device.cpp +++ b/templates/device/src/my_device.cpp @@ -65,6 +65,25 @@ struct MY_QDMI_Device_Site_impl_d {}; */ struct MY_QDMI_Device_Operation_impl_d {}; +/** + * @brief Implementation of the MY_QDMI_Device_Pulse_Parameter structure. + * @details This structure can, e.g., be used to store the pulse parameter id. + */ +struct MY_QDMI_Device_Pulse_Parameter_impl_d {}; + +/** + * @brief Implementation of the MY_QDMI_Device_Pulse_Waveform structure. + * @details This structure can, e.g., be used to store the pulse waveform id. + */ +struct MY_QDMI_Device_Pulse_Waveform_impl_d {}; + +/** + * @brief Implementation of the MY_QDMI_Device_Pulse_Implementation structure. + * @details This structure can, e.g., be used to store the pulse implementation + * id. + */ +struct MY_QDMI_Device_Pulse_Implementation_impl_d {}; + int MY_QDMI_device_initialize() { return QDMI_ERROR_NOTIMPLEMENTED; } int MY_QDMI_device_finalize() { return QDMI_ERROR_NOTIMPLEMENTED; } @@ -149,6 +168,25 @@ int MY_QDMI_device_session_query_operation_property( return QDMI_ERROR_NOTIMPLEMENTED; } +int MY_QDMI_device_session_query_pulse_parameter_property( + MY_QDMI_Device_Session session, MY_QDMI_Pulse_Parameter param, + const QDMI_Pulse_Parameter_Property prop, const size_t size, void *value, + size_t *size_ret) { + return QDMI_ERROR_NOTIMPLEMENTED; +} + +int MY_QDMI_device_session_query_pulse_waveform_property( + MY_QDMI_Device_Session session, MY_QDMI_Pulse_Waveform waveform, + const QDMI_Pulse_Waveform_Property prop, const size_t size, void *value, + size_t *size_ret) { + return QDMI_ERROR_NOTIMPLEMENTED; +} +int MY_QDMI_device_session_query_pulse_implementation_property( + MY_QDMI_Device_Session session, MY_QDMI_Pulse_Implementation impl, + const QDMI_Pulse_Implementation_Property prop, const size_t size, + void *value, size_t *size_ret) { + return QDMI_ERROR_NOTIMPLEMENTED; +} // The following line ignores the unused parameters in the functions. // Please remove the following code block after populating the functions. // NOLINTEND(misc-unused-parameters,clang-diagnostic-unused-parameter) diff --git a/templates/device/test/test_my_device.cpp b/templates/device/test/test_my_device.cpp index 894e98a5..b1d005db 100644 --- a/templates/device/test/test_my_device.cpp +++ b/templates/device/test/test_my_device.cpp @@ -17,6 +17,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception ------------------------------------------------------------------------------*/ #include "my_qdmi/device.h" +#include "qdmi/constants.h" #include #include @@ -226,3 +227,24 @@ TEST_F(QDMIImplementationTest, QueryDeviceQubitNum) { &num_qubits, nullptr), QDMI_SUCCESS); } + +TEST_F(QDMIImplementationTest, QueryPulseParameterImplemented) { + ASSERT_EQ(MY_QDMI_device_session_query_pulse_parameter_property( + nullptr, nullptr, QDMI_PULSE_PARAMETER_PROPERTY_MAX, 0, nullptr, + nullptr), + QDMI_ERROR_INVALIDARGUMENT); +} + +TEST_F(QDMIImplementationTest, QueryPulseWaveformPropertyImplemented) { + ASSERT_EQ(MY_QDMI_device_session_query_pulse_waveform_property( + nullptr, nullptr, QDMI_PULSE_WAVEFORM_PROPERTY_MAX, 0, nullptr, + nullptr), + QDMI_ERROR_INVALIDARGUMENT); +} + +TEST_F(QDMIImplementationTest, QueryPulseImplementationPropertyImplemented) { + ASSERT_EQ(MY_QDMI_device_session_query_pulse_implementation_property( + nullptr, nullptr, QDMI_PULSE_IMPLEMENTATION_PROPERTY_MAX, 0, + nullptr, nullptr), + QDMI_ERROR_INVALIDARGUMENT); +} diff --git a/test/test_qdmi.cpp b/test/test_qdmi.cpp index ee7aaa80..0b8da301 100644 --- a/test/test_qdmi.cpp +++ b/test/test_qdmi.cpp @@ -19,6 +19,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include "example_fomac.hpp" #include "example_tool.hpp" #include "qdmi/client.h" +#include "qdmi/constants.h" #include "utils/test_impl.hpp" #include @@ -972,5 +973,51 @@ TEST_P(QDMIImplementationTest, QueryPulseSupportLevel) { device, QDMI_DEVICE_PROPERTY_PULSESUPPORT, sizeof(QDMI_Device_Pulse_Support_Level), &pulse_support_level, nullptr); EXPECT_EQ(ret, QDMI_SUCCESS); - EXPECT_EQ(pulse_support_level, QDMI_DEVICE_PULSE_SUPPORT_LEVEL_NONE); + EXPECT_EQ(pulse_support_level, QDMI_DEVICE_PULSE_SUPPORT_LEVEL_SITE); +} + +TEST_P(QDMIImplementationTest, QueryPulseImplementation) { + + if (lib_prefix != "CXX") { + GTEST_SKIP() << "Skipping test for non-C++ implementations"; + } + + const auto fomac = FoMaC(device); + const auto ops = fomac.get_operation_map(); + for (const auto &[name, op] : ops) { + const auto pulse_impl = fomac.get_operation_pulse_implementation(op); + EXPECT_NE(pulse_impl, nullptr); + + const auto waveform = fomac.get_pulse_waveform(pulse_impl); + EXPECT_NE(waveform, nullptr); + EXPECT_GT(fomac.get_pulse_waveform_name(waveform).size(), 0); + EXPECT_GT(fomac.get_pulse_waveform_formula(waveform).size(), 0); + const auto waveform_params = fomac.get_pulse_waveform_parameters(waveform); + EXPECT_GE(waveform_params.size(), 0); + for (const auto ¶m : waveform_params) { + auto param_name = fomac.get_pulse_parameter_name(param); + EXPECT_GT(param_name.size(), 0); + EXPECT_GE(fomac.get_pulse_parameter_rangemin(param), + -std::numeric_limits::infinity()); + EXPECT_LE(fomac.get_pulse_parameter_rangemax(param), + std::numeric_limits::infinity()); + if (fomac.get_pulse_parameter_ismutable(param)) { + ASSERT_TRUE(fomac.get_pulse_parameter_ismutable(param)); + } + } + + const auto pulse_params = fomac.get_pulse_parameters(pulse_impl); + EXPECT_GT(pulse_params.size(), 0); + for (const auto ¶m : pulse_params) { + auto param_name = fomac.get_pulse_parameter_name(param); + EXPECT_GT(param_name.size(), 0); + EXPECT_GE(fomac.get_pulse_parameter_rangemin(param), + -std::numeric_limits::infinity()); + EXPECT_LE(fomac.get_pulse_parameter_rangemax(param), + std::numeric_limits::infinity()); + if (fomac.get_pulse_parameter_ismutable(param)) { + ASSERT_TRUE(fomac.get_pulse_parameter_ismutable(param)); + } + } + } } diff --git a/test/utils/test_defs.cpp.in b/test/utils/test_defs.cpp.in index 22a82fbb..39b0a311 100644 --- a/test/utils/test_defs.cpp.in +++ b/test/utils/test_defs.cpp.in @@ -32,6 +32,9 @@ int main() { @QDMI_PREFIX@_QDMI_Device_Job job = nullptr; @QDMI_PREFIX@_QDMI_Site site = nullptr; @QDMI_PREFIX@_QDMI_Operation operation = nullptr; + @QDMI_PREFIX@_QDMI_Pulse_Parameter pulse_param = nullptr; + @QDMI_PREFIX@_QDMI_Pulse_Waveform waveform = nullptr; + @QDMI_PREFIX@_QDMI_Pulse_Implementation pulse_impl = nullptr; @QDMI_PREFIX@_QDMI_device_initialize(); @QDMI_PREFIX@_QDMI_device_finalize(); @QDMI_PREFIX@_QDMI_device_session_alloc(&session); @@ -50,4 +53,7 @@ int main() { @QDMI_PREFIX@_QDMI_device_session_query_device_property(session, QDMI_DEVICE_PROPERTY_MAX, 0, nullptr, nullptr); @QDMI_PREFIX@_QDMI_device_session_query_site_property(session, site, QDMI_SITE_PROPERTY_MAX, 0, nullptr, nullptr); @QDMI_PREFIX@_QDMI_device_session_query_operation_property(session, operation, 0, nullptr, 0, nullptr, QDMI_OPERATION_PROPERTY_MAX, 0, nullptr, nullptr); + @QDMI_PREFIX@_QDMI_device_session_query_pulse_parameter_property(session, pulse_param, QDMI_PULSE_PARAMETER_PROPERTY_MAX, 0, nullptr, nullptr); + @QDMI_PREFIX@_QDMI_device_session_query_pulse_waveform_property(session, waveform, QDMI_PULSE_WAVEFORM_PROPERTY_MAX, 0, nullptr, nullptr); + @QDMI_PREFIX@_QDMI_device_session_query_pulse_implementation_property(session, pulse_impl, QDMI_PULSE_IMPLEMENTATION_PROPERTY_MAX, 0, nullptr, nullptr); } diff --git a/test/utils/test_impl.cpp b/test/utils/test_impl.cpp index 5415bf24..bdd37509 100644 --- a/test/utils/test_impl.cpp +++ b/test/utils/test_impl.cpp @@ -36,6 +36,7 @@ void QDMIImplementationTest::SetUp() { const std::string &library_name = std::get<0>(params); const std::string &prefix = std::get<1>(params); mode = std::get<2>(params); + lib_prefix = std::get<1>(params); // Get the current test info const ::testing::TestInfo *test_info = diff --git a/test/utils/test_impl.hpp b/test/utils/test_impl.hpp index 37eb6a17..6ddccd89 100644 --- a/test/utils/test_impl.hpp +++ b/test/utils/test_impl.hpp @@ -54,6 +54,7 @@ class QDMIImplementationTest QDMI_Device device = nullptr; TEST_SESSION_MODE mode = TEST_SESSION_MODE::READONLY; std::string config_file_name; + std::string lib_prefix; void SetUp() override;