Skip to content
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ This project adheres to [Semantic Versioning], with the exception that minor rel

### Changed

- ♻️ Extract singleton pattern into reusable template base class for QDMI devices and driver ([#1444]) ([**@ystade**], [**@burgholzer**])
- 🚚 Reorganize QDMI code structure by moving devices into dedicated subdirectories and separating driver and common utilities ([#1444]) ([**@ystade**])
- 📦 Build MLIR by default for C++ library builds ([#1356]) ([**@burgholzer**], [**@denialhaag**])

### Removed
Expand Down Expand Up @@ -308,6 +310,7 @@ _📚 Refer to the [GitHub Release Notes](https://github.com/munich-quantum-tool
<!-- PR links -->

[#1446]: https://github.com/munich-quantum-toolkit/core/pull/1446
[#1444]: https://github.com/munich-quantum-toolkit/core/pull/1444
[#1443]: https://github.com/munich-quantum-toolkit/core/pull/1443
[#1437]: https://github.com/munich-quantum-toolkit/core/pull/1437
[#1436]: https://github.com/munich-quantum-toolkit/core/pull/1436
Expand Down
2 changes: 1 addition & 1 deletion bindings/fomac/fomac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#include "fomac/FoMaC.hpp"

#include "qdmi/Driver.hpp"
#include "qdmi/driver/Driver.hpp"

#include <nanobind/nanobind.h>
#include <nanobind/operators.h>
Expand Down
2 changes: 1 addition & 1 deletion bindings/na/register_fomac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#include "fomac/FoMaC.hpp"
#include "na/fomac/Device.hpp"
#include "qdmi/na/Generator.hpp"
#include "qdmi/devices/na/Generator.hpp"

#include <nanobind/nanobind.h>
#include <nanobind/operators.h>
Expand Down
2 changes: 1 addition & 1 deletion include/mqt-core/fomac/FoMaC.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#pragma once

#include "qdmi/Common.hpp"
#include "qdmi/common/Common.hpp"

#include <algorithm>
#include <complex>
Expand Down
2 changes: 1 addition & 1 deletion include/mqt-core/na/fomac/Device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#pragma once

#include "fomac/FoMaC.hpp"
#include "qdmi/na/Generator.hpp"
#include "qdmi/devices/na/Generator.hpp"

// NOLINTNEXTLINE(misc-include-cleaner)
#include <nlohmann/json.hpp>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,40 @@
#include <string>

namespace qdmi {
template <class Concrete> class Singleton {
protected:
/// @brief Protected constructor to enforce the singleton pattern.
Singleton() = default;

public:
// Delete move constructor and move assignment operator because of the
// following reason:
//
// - Users access the singleton via get() which returns a reference
// - Moving would invalidate the singleton's state
// - Users never own the singleton instance
Singleton(Singleton&&) = delete;
Singleton& operator=(Singleton&&) = delete;
// Delete copy constructor and assignment operator to enforce singleton.
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;

/// @brief Virtual destructor for the Singleton base class.
virtual ~Singleton() = default;

/// @returns the singleton instance of the derived class.
[[nodiscard]] static auto get() -> Concrete& {
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
static auto* instance = new Concrete();
// The instance is intentionally leaked to avoid static deinitialization
// issues (cf. static (de)initialization order fiasco)
return *instance;
}
};

/**
* @brief Function used to mark unreachable code
* @details Uses compiler specific extensions if possible. Even if no extension
* @details Uses compiler-specific extensions if possible. Even if no extension
* is used, undefined behavior is still raised by an empty function body and the
* noreturn attribute.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "dd/DDDefinitions.hpp"
#include "dd/Package.hpp"
#include "mqt_ddsim_qdmi/device.h"
#include "qdmi/common/Common.hpp"

#include <atomic>
#include <cstddef>
Expand All @@ -31,7 +32,9 @@
#include <unordered_map>

namespace qdmi::dd {
class Device final {
class Device final : public Singleton<Device> {
friend class Singleton;

/// Provides access to the device name.
std::string name_;

Expand Down Expand Up @@ -64,19 +67,6 @@ class Device final {
Device();

public:
// Default move constructor and move assignment operator.
Device(Device&&) = delete;
Device& operator=(Device&&) = delete;
// Delete copy constructor and assignment operator to enforce singleton.
Device(const Device&) = delete;
Device& operator=(const Device&) = delete;

/// @brief Destructor for the Device class.
~Device() = default;

/// @returns the singleton instance of the Device class.
[[nodiscard]] static auto get() -> Device&;

/**
* @brief Allocates a new device session.
* @see MQT_DDSIM_QDMI_device_session_alloc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include "mqt_na_qdmi/device.h"
#include "qdmi/common/Common.hpp"

#include <cstddef>
#include <cstdint>
Expand All @@ -27,7 +28,9 @@
#include <vector>

namespace qdmi::na {
class Device final {
class Device final : public Singleton<Device> {
friend class Singleton;

/// @brief Provides access to the device name.
std::string name_;

Expand Down Expand Up @@ -69,19 +72,6 @@ class Device final {
Device();

public:
// Default move constructor and move assignment operator.
Device(Device&&) = default;
Device& operator=(Device&&) = default;
// Delete copy constructor and assignment operator to enforce singleton.
Device(const Device&) = delete;
Device& operator=(const Device&) = delete;

/// @brief Destructor for the Device class.
~Device() = default;

/// @returns the singleton instance of the Device class.
[[nodiscard]] static auto get() -> Device&;

/**
* @brief Allocates a new device session.
* @see MQT_NA_QDMI_device_session_alloc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include "mqt_sc_qdmi/device.h"
#include "qdmi/common/Common.hpp"

#include <cstddef>
#include <cstdint>
Expand All @@ -26,7 +27,9 @@
#include <vector>

namespace qdmi::sc {
class Device final {
class Device final : public Singleton<Device> {
friend class Singleton;

/// @brief Provides access to the device name.
std::string name_;

Expand All @@ -51,19 +54,6 @@ class Device final {
Device();

public:
// Delete move constructor and move assignment operator.
Device(Device&&) = delete;
Device& operator=(Device&&) = delete;
// Delete copy constructor and assignment operator to enforce singleton.
Device(const Device&) = delete;
Device& operator=(const Device&) = delete;

/// @brief Destructor for the Device class.
~Device();

/// @returns the singleton instance of the Device class.
[[nodiscard]] static auto get() -> Device&;

/**
* @brief Allocates a new device session.
* @see MQT_SC_QDMI_device_session_alloc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

#pragma once

#include "qdmi/common/Common.hpp"

#include <cstddef>
#include <cstdint>
#include <memory>
Expand All @@ -18,7 +20,6 @@
#include <qdmi/device.h>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace qdmi {
Expand Down Expand Up @@ -393,7 +394,9 @@ namespace qdmi {
* sessions. It is responsible for loading the libraries, allocating sessions,
* and providing access to the devices.
*/
class Driver final {
class Driver final : public Singleton<Driver> {
friend class Singleton;

/// @brief Private constructor to enforce the singleton pattern.
Driver();

Expand All @@ -410,21 +413,6 @@ class Driver final {
sessions_;

public:
// Delete copy constructors and assignment operators to prevent copying the
// singleton instance.
Driver(const Driver&) = delete;
Driver& operator=(const Driver&) = delete;
Driver(Driver&&) = default;
Driver& operator=(Driver&&) = default;

/// @brief Returns the singleton instance.
static auto get() -> Driver& {
static Driver instance;
return instance;
}

/// @brief Destructor for the Driver class.
~Driver();
/**
* @brief Loads a dynamic device library and adds it to the driver.
*
Expand Down
2 changes: 1 addition & 1 deletion src/fomac/FoMaC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

#include "fomac/FoMaC.hpp"

#include "qdmi/Common.hpp"
#include "qdmi/common/Common.hpp"

#include <algorithm>
#include <complex>
Expand Down
2 changes: 1 addition & 1 deletion src/na/fomac/Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

#include "fomac/FoMaC.hpp"
#include "ir/Definitions.hpp"
#include "qdmi/na/Generator.hpp"
#include "qdmi/devices/na/Generator.hpp"

#include <algorithm>
#include <array>
Expand Down
53 changes: 3 additions & 50 deletions src/qdmi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,56 +6,9 @@
#
# Licensed under the MIT License

set(TARGET_NAME ${MQT_CORE_TARGET_NAME}-qdmi-common)

if(NOT TARGET ${TARGET_NAME})
# Add common library
add_mqt_core_library(${TARGET_NAME} ALIAS_NAME QDMICommon)

# Add sources to target
target_sources(${TARGET_NAME} PRIVATE Common.cpp)

# Add headers using file sets
target_sources(${TARGET_NAME} PUBLIC FILE_SET HEADERS BASE_DIRS ${MQT_CORE_INCLUDE_BUILD_DIR}
FILES ${MQT_CORE_INCLUDE_BUILD_DIR}/qdmi/Common.hpp)

# Add link libraries
target_link_libraries(
${TARGET_NAME}
PUBLIC qdmi::qdmi
PRIVATE qdmi::qdmi_project_warnings)

# add to list of MQT core targets
list(APPEND MQT_CORE_TARGETS ${TARGET_NAME})
endif()

add_subdirectory(dd)
add_subdirectory(sc)
add_subdirectory(na)

set(TARGET_NAME ${MQT_CORE_TARGET_NAME}-qdmi-driver)

if(NOT TARGET ${TARGET_NAME})
# Add driver library
add_mqt_core_library(${TARGET_NAME} ALIAS_NAME QDMIDriver)

# Add sources to target
target_sources(${TARGET_NAME} PRIVATE Driver.cpp)

# Add headers using file sets
target_sources(${TARGET_NAME} PUBLIC FILE_SET HEADERS BASE_DIRS ${MQT_CORE_INCLUDE_BUILD_DIR}
FILES ${MQT_CORE_INCLUDE_BUILD_DIR}/qdmi/Driver.hpp)

# Add link libraries
target_link_libraries(
${TARGET_NAME}
PUBLIC qdmi::qdmi MQT::CoreQDMICommon
PRIVATE MQT::CoreQDMINaDevice MQT::CoreQDMIScDevice MQT::CoreQDMI_DDSIM_Device
qdmi::qdmi_project_warnings spdlog::spdlog ${CMAKE_DL_LIBS})

# add to list of MQT core targets
list(APPEND MQT_CORE_TARGETS ${TARGET_NAME})
endif()
add_subdirectory(common)
add_subdirectory(devices)
add_subdirectory(driver)

set(MQT_CORE_TARGETS
${MQT_CORE_TARGETS}
Expand Down
34 changes: 34 additions & 0 deletions src/qdmi/common/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright (c) 2023 - 2026 Chair for Design Automation, TUM
# Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH
# All rights reserved.
#
# SPDX-License-Identifier: MIT
#
# Licensed under the MIT License

set(TARGET_NAME ${MQT_CORE_TARGET_NAME}-qdmi-common)

if(NOT TARGET ${TARGET_NAME})
# Add common library
add_mqt_core_library(${TARGET_NAME} ALIAS_NAME QDMICommon)

# Add sources to target
target_sources(${TARGET_NAME} PRIVATE Common.cpp)

# Add headers using file sets
target_sources(${TARGET_NAME} PUBLIC FILE_SET HEADERS BASE_DIRS ${MQT_CORE_INCLUDE_BUILD_DIR}
FILES ${MQT_CORE_INCLUDE_BUILD_DIR}/qdmi/common/Common.hpp)

# Add link libraries
target_link_libraries(
${TARGET_NAME}
PUBLIC qdmi::qdmi
PRIVATE qdmi::qdmi_project_warnings)

# add to list of MQT core targets
list(APPEND MQT_CORE_TARGETS ${TARGET_NAME})
endif()

set(MQT_CORE_TARGETS
${MQT_CORE_TARGETS}
PARENT_SCOPE)
2 changes: 1 addition & 1 deletion src/qdmi/Common.cpp → src/qdmi/common/Common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
/// @brief Common definitions and utilities for working with QDMI in C++.
/// @note This file will be upstreamed to the QDMI core library in the future.

#include "qdmi/Common.hpp"
#include "qdmi/common/Common.hpp"

#include <iostream>
#include <qdmi/constants.h>
Expand Down
15 changes: 15 additions & 0 deletions src/qdmi/devices/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (c) 2023 - 2026 Chair for Design Automation, TUM
# Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH
# All rights reserved.
#
# SPDX-License-Identifier: MIT
#
# Licensed under the MIT License

add_subdirectory(dd)
add_subdirectory(sc)
add_subdirectory(na)

set(MQT_CORE_TARGETS
${MQT_CORE_TARGETS}
PARENT_SCOPE)
Loading
Loading