Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
3833e0d
Add transpilation step and TODOs
MatthiasReumann May 6, 2026
fdb9060
🎨 pre-commit fixes
pre-commit-ci[bot] May 6, 2026
b0ff8a2
Merge branch 'main' into feat/arch-option-and-qdmi
MatthiasReumann Jun 15, 2026
00db463
Merge branch 'feat/arch-option-and-qdmi' of https://github.com/munich…
MatthiasReumann Jun 15, 2026
f9c2c6b
🎨 pre-commit fixes
pre-commit-ci[bot] Jun 15, 2026
287e1d2
Merge branch 'main' into feat/arch-option-and-qdmi
MatthiasReumann Jul 1, 2026
7b885fa
🎨 pre-commit fixes
pre-commit-ci[bot] Jul 1, 2026
db347db
Implement initial QDMI integration
MatthiasReumann Jul 2, 2026
436382f
Merge branch 'feat/arch-option-and-qdmi' of https://github.com/munich…
MatthiasReumann Jul 2, 2026
51636d3
🎨 pre-commit fixes
pre-commit-ci[bot] Jul 2, 2026
793f50f
Restructure main
MatthiasReumann Jul 2, 2026
9b65ba7
Merge branch 'feat/arch-option-and-qdmi' of https://github.com/munich…
MatthiasReumann Jul 2, 2026
70a188a
Merge branch 'main' into feat/arch-option-and-qdmi
MatthiasReumann Jul 9, 2026
6d7db6b
Add SuperconductingDevice class
MatthiasReumann Jul 9, 2026
042a093
Integrate into Compiler
MatthiasReumann Jul 9, 2026
8e43cf8
🎨 pre-commit fixes
pre-commit-ci[bot] Jul 9, 2026
e8d31b5
Merge branch 'main' into feat/arch-option-and-qdmi
MatthiasReumann Jul 9, 2026
d95ae33
Don't link unncessary libraries
MatthiasReumann Jul 9, 2026
672162b
Apply bunny suggestions
MatthiasReumann Jul 9, 2026
3691dcd
Merge branch 'main' into feat/arch-option-and-qdmi
MatthiasReumann Jul 9, 2026
7f1791a
Final touches
MatthiasReumann Jul 9, 2026
569b51f
Merge branch 'main' into feat/arch-option-and-qdmi
MatthiasReumann Jul 9, 2026
5fc2635
Implement JSON config
MatthiasReumann Jul 9, 2026
340a52b
🎨 pre-commit fixes
pre-commit-ci[bot] Jul 9, 2026
65cbaf8
Fix lint
MatthiasReumann Jul 9, 2026
1af70f7
Merge branch 'feat/arch-option-and-qdmi' of https://github.com/munich…
MatthiasReumann Jul 9, 2026
efd3817
Merge branch 'main' into feat/arch-option-and-qdmi
MatthiasReumann Jul 10, 2026
9b766a7
Merge branch 'main' into feat/arch-option-and-qdmi
MatthiasReumann Jul 14, 2026
8b62b27
🎨 pre-commit fixes
pre-commit-ci[bot] Jul 14, 2026
879825d
Remove discovery file
MatthiasReumann Jul 14, 2026
d6e3ee2
Update CHANGELOG.md
MatthiasReumann Jul 14, 2026
6e89142
Merge branch 'feat/arch-option-and-qdmi' of https://github.com/munich…
MatthiasReumann Jul 14, 2026
18423a5
🎨 pre-commit fixes
pre-commit-ci[bot] Jul 14, 2026
b94f9b4
Add missing include
MatthiasReumann Jul 14, 2026
8f7d137
Add 'CONFIGURE_DEPENDS'
MatthiasReumann Jul 14, 2026
f7d7c41
Add "is_object" check
MatthiasReumann Jul 14, 2026
0983e04
Merge branch 'feat/arch-option-and-qdmi' of https://github.com/munich…
MatthiasReumann Jul 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ releases may include breaking changes.

### Added

- ✨ Integrate QDMI into the MLIR Compiler Collection ([#1687])
([**@MatthiasReumann**])
- ✨ Add support for QDMI child devices to the driver and FoMaC libraries
([#1897]) ([**@burgholzer**])
- ✨ Add typed custom property and result queries to the C++ and Python FoMaC
Expand Down Expand Up @@ -692,6 +694,7 @@ changelogs._
[#1702]: https://github.com/munich-quantum-toolkit/core/pull/1702
[#1700]: https://github.com/munich-quantum-toolkit/core/pull/1700
[#1694]: https://github.com/munich-quantum-toolkit/core/pull/1694
[#1687]: https://github.com/munich-quantum-toolkit/core/pull/1687
[#1676]: https://github.com/munich-quantum-toolkit/core/pull/1676
[#1675]: https://github.com/munich-quantum-toolkit/core/pull/1675
[#1674]: https://github.com/munich-quantum-toolkit/core/pull/1674
Expand Down
18 changes: 14 additions & 4 deletions mlir/include/mlir/Compiler/CompilerPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@

#pragma once

#include "fomac/FoMaC.hpp"

#include <mlir/Pass/PassManager.h>
#include <mlir/Support/LogicalResult.h>

#include <memory>
#include <string>

namespace mlir {
Expand Down Expand Up @@ -49,6 +52,9 @@ struct QuantumCompilerConfig {

/// Enable Hadamard lifting
bool enableHadamardLifting = false;

/// Pointer to QDMI Device to compile to.
std::shared_ptr<fomac::Device> device;
};

/**
Expand All @@ -66,6 +72,8 @@ struct CompilationRecord {
std::string afterQCOCanon;
std::string afterOptimization;
std::string afterOptimizationCanon;
std::string afterTranspilation;
std::string afterTranspilationCanon;
std::string afterQCConversion;
std::string afterQCCanon;
std::string afterQIRConversion;
Expand All @@ -86,10 +94,12 @@ struct CompilationRecord {
* 4. QCO cleanup pipeline
* 5. Quantum optimization passes
* 6. QCO cleanup pipeline
* 7. QC dialect - converted back for backend lowering
* 8. QC cleanup pipeline
* 9. QIR (Quantum Intermediate Representation) - optional final lowering
* 10. QIR cleanup pipeline
* 7. Quantum transpilation passes - optional fit to hardware constraints
* 8. QCO cleanup pipeline
* 9. QC dialect - converted back for backend lowering
* 10. QC cleanup pipeline
* 11. QIR (Quantum Intermediate Representation) - optional final lowering
* 12. QIR cleanup pipeline
*
* Following MLIR best practices, simplification and dead-value cleanup are
* run after each major transformation stage.
Expand Down
11 changes: 4 additions & 7 deletions mlir/include/mlir/Dialect/QCO/Transforms/Mapping/Mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#pragma once

#include "mlir/Dialect/QCO/Transforms/Passes.h"
#include "mlir/Support/SuperconductingDevice.h"

#include <llvm/Support/LogicalResult.h>
#include <mlir/IR/Region.h>
Expand All @@ -20,12 +21,8 @@

namespace mlir::qco {

/**
* @brief Create a mapping pass instance with the given target architecture.
* @returns a pass object.
*/
std::unique_ptr<Pass>
createMappingPass(const llvm::DenseSet<std::pair<size_t, size_t>>&,
MappingPassOptions);
/// Create a superconducting mapping pass instance.
std::unique_ptr<Pass> createMappingPass(std::shared_ptr<SuperconductingDevice>,
MappingPassOptions);

} // namespace mlir::qco
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include <optional>
#include <utility>

namespace mlir::qco {
namespace mlir {

/// A directed graph.
class Graph {
Expand Down Expand Up @@ -61,6 +61,13 @@ class Graph {
for_each(edges, [this](const auto& e) { addEdge(e.first, e.second); });
}

/// Construct graph from node identifiers and edge set.
explicit Graph(ArrayRef<size_t> nodes,
const llvm::DenseSet<std::pair<size_t, size_t>>& edges) {
for_each(nodes, [this](const auto u) { std::ignore = adj_[u]; });
for_each(edges, [this](const auto& e) { addEdge(e.first, e.second); });
}

/// Add a directed edge to the internal representation of the graph.
/// Implicitly adds nodes.
void addEdge(size_t u, size_t v);
Expand Down Expand Up @@ -105,4 +112,4 @@ class Graph {
private:
llvm::DenseMap<size_t, SmallVector<size_t>> adj_;
};
} // namespace mlir::qco
} // namespace mlir
93 changes: 93 additions & 0 deletions mlir/include/mlir/Support/Qdmi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* 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
*/

#pragma once

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

#include <llvm/Support/raw_ostream.h>
#include <mlir/Support/LLVM.h>

#include <memory>

namespace mlir::qdmi {
namespace impl {

struct DeviceConfig {
/// Library name/path
std::string libName;
/// Prefix for function names
std::string prefix;
/// Device session configuration
::qdmi::DeviceSessionConfig deviceConfig;
};

struct Config {
/// Read and parse the given QDMI JSON config file.
/// The function expects the following JSON structure, where some attributes
/// may be omitted depending on the use-case.
/// {
/// "session": {
/// "token": "...",
/// "authFile": "...",
/// "authUrl": "...",
/// "username": "...",
/// "password": "...",
/// "projectId": "...",
/// "custom1": "...",
/// "custom2": "...",
/// "custom3": "...",
/// "custom4": "...",
/// "custom5": "..."
/// },
/// "devices": [
/// {
/// "libName": "...",
/// "prefix": "...",
/// "deviceConfig": {
/// "baseUrl": "...",
/// "token": "...",
/// "authFile": "...",
/// "authUrl": "...",
/// "username": "...",
/// "password": "...",
/// "custom1": "...",
/// "custom2": "...",
/// "custom3": "...",
/// "custom4": "...",
/// "custom5": "..."
/// }
/// }
/// ]
/// }
static Config read(StringRef path);

fomac::SessionConfig session;
SmallVector<DeviceConfig, 0> devices;
};
} // namespace impl

/// Return parameterized session.
/// Applies the provided session config and loads the specified QDMI devices.
fomac::Session prepareSession(StringRef configPath);

/// Return unparameterized session.
/// Applies default session config and does not load any dynamic QDMI devices.
fomac::Session prepareSession();

/// Output a list of all available QDMI devices to @p os.
void listAvailableDevices(fomac::Session& session,
llvm::raw_ostream& os = llvm::outs());

/// Find a QDMI device with the given name and return its FoMaC class.
std::shared_ptr<fomac::Device> getDevice(fomac::Session& session,
StringRef name);
} // namespace mlir::qdmi
Comment thread
MatthiasReumann marked this conversation as resolved.
65 changes: 65 additions & 0 deletions mlir/include/mlir/Support/SuperconductingDevice.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* 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
*/

#pragma once

#include "fomac/FoMaC.hpp"
#include "mlir/Support/Graph.h"

#include <mlir/Support/LLVM.h>

#include <cstddef>
#include <memory>

namespace mlir {
class SuperconductingDevice {
public:
/// Construct a superconducting device from qubits and a coupling map.
/// A coupling is a directed edge from qubit u → v. Thus, for undirected
/// architectures, for each (u, v) the coupling also contains (v, u).
SuperconductingDevice(ArrayRef<size_t> qubits,
const DenseSet<std::pair<size_t, size_t>>& coupling)
: coupling_(qubits, coupling), dist_(coupling_.getDistMatrix()),
device_(nullptr) {}

/// Construct a superconducting device from a QDMI device.
/// Assumes that the given QDMI device is a superconducting device that has
/// a coupling map.
explicit SuperconductingDevice(std::shared_ptr<fomac::Device> device)
: coupling_(getCouplingGraph(device)), dist_(coupling_.getDistMatrix()),
device_(std::move(device)) {}

/// Return the device's number of qubits.
[[nodiscard]] size_t nqubits() const;

/// Return true if two qubits are adjacent.
[[nodiscard]] bool areAdjacent(size_t u, size_t v) const;

/// Return the length of the shortest path between two qubits.
[[nodiscard]] size_t distanceBetween(size_t u, size_t v) const;
Comment thread
MatthiasReumann marked this conversation as resolved.

/// Return the qubit identifiers.
[[nodiscard]] SmallVector<size_t> qubits() const;

/// Return all neighbours of a qubit.
[[nodiscard]] ArrayRef<size_t> neighboursOf(size_t u) const;

/// Return the max degree (connectivity) of any qubit of the device.
[[nodiscard]] size_t maxDegree() const;

private:
/// Construct graph object from QDMI device.
static Graph getCouplingGraph(const std::shared_ptr<fomac::Device>& device);

Graph coupling_;
Graph::DistanceMatrix dist_;
std::shared_ptr<fomac::Device> device_;
};
} // namespace mlir
47 changes: 42 additions & 5 deletions mlir/lib/Compiler/CompilerPipeline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,18 @@
#include "mlir/Conversion/QCToQCO/QCToQCO.h"
#include "mlir/Conversion/QCToQIR/QIRAdaptive/QCToQIRAdaptive.h"
#include "mlir/Conversion/QCToQIR/QIRBase/QCToQIRBase.h"
#include "mlir/Dialect/QCO/Transforms/Mapping/Mapping.h"
#include "mlir/Dialect/QCO/Transforms/Passes.h"
#include "mlir/Support/Passes.h"
#include "mlir/Support/PrettyPrinting.h"
#include "mlir/Support/SuperconductingDevice.h"

#include <llvm/Support/raw_ostream.h>
#include <mlir/IR/BuiltinOps.h>
#include <mlir/Pass/PassManager.h>
#include <mlir/Support/LLVM.h>

#include <memory>
#include <string>

namespace mlir {
Expand Down Expand Up @@ -100,6 +103,9 @@ QuantumCompilerPipeline::runPipeline(ModuleOp module,
if (convertToQIR) {
totalStages += 2;
}
if (config_.device != nullptr) {
totalStages += 2;
}
auto currentStage = 0;

// Stage 1: QC import
Expand Down Expand Up @@ -171,11 +177,42 @@ QuantumCompilerPipeline::runPipeline(ModuleOp module,
if (record != nullptr && config_.recordIntermediates) {
record->afterOptimizationCanon = captureIR(module);
if (config_.printIRAfterAllStages) {
prettyPrintStage(module, "Final QCO Cleanup", ++currentStage,
prettyPrintStage(module, "Post-Optimization QCO Cleanup", ++currentStage,
totalStages);
}
}
// Stage 7: QCO-to-QC conversion
// Stage 7: Transpilation passes (optional)
// Assume superconducting devices for now.
if (config_.device != nullptr) {
if (failed(runStage([&](PassManager& pm) {
pm.addPass(qco::createMappingPass(
std::make_shared<SuperconductingDevice>(config_.device),
qco::MappingPassOptions{}));
}))) {
return failure();
}
if (record != nullptr && config_.recordIntermediates) {
record->afterTranspilation = captureIR(module);
if (config_.printIRAfterAllStages) {
prettyPrintStage(module, "Transpilation Passes", ++currentStage,
totalStages);
}
}
// Stage 8: QCO cleanup (optional)
if (failed(runStage(
[&](PassManager& pm) { populateQCOCleanupPipeline(pm); }))) {
return failure();
}
if (record != nullptr && config_.recordIntermediates) {
record->afterTranspilationCanon = captureIR(module);
if (config_.printIRAfterAllStages) {
prettyPrintStage(module, "Post-Transpilation QCO Cleanup",
++currentStage, totalStages);
}
}
}
Comment thread
MatthiasReumann marked this conversation as resolved.

// Stage 9: QCO-to-QC conversion
Comment thread
MatthiasReumann marked this conversation as resolved.
if (failed(runStage([&](PassManager& pm) { pm.addPass(createQCOToQC()); }))) {
return failure();
}
Expand All @@ -186,7 +223,7 @@ QuantumCompilerPipeline::runPipeline(ModuleOp module,
totalStages);
}
}
// Stage 8: QC cleanup
// Stage 10: QC cleanup
if (failed(
runStage([&](PassManager& pm) { populateQCCleanupPipeline(pm); }))) {
return failure();
Expand All @@ -197,7 +234,7 @@ QuantumCompilerPipeline::runPipeline(ModuleOp module,
prettyPrintStage(module, "Final QC Cleanup", ++currentStage, totalStages);
}
}
// Stage 9: QC-to-QIR conversion (optional)
// Stage 11: QC-to-QIR conversion (optional)
if (convertToQIR) {
if (failed(runStage([&](PassManager& pm) {
if (config_.convertToQIRAdaptive) {
Expand All @@ -215,7 +252,7 @@ QuantumCompilerPipeline::runPipeline(ModuleOp module,
totalStages);
}
}
// Stage 10: QIR cleanup (optional)
// Stage 12: QIR cleanup (optional)
if (failed(runStage([&](PassManager& pm) {
populateQIRCleanupPipeline(pm, config_.convertToQIRAdaptive);
}))) {
Expand Down
2 changes: 2 additions & 0 deletions mlir/lib/Dialect/QCO/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ add_mlir_library(
MLIRArithDialect
MLIRMathDialect
MLIRSCFUtils
PUBLIC
MLIRSupportMQT
DEPENDS
MLIRQCOTransformsIncGen)

Expand Down
Loading
Loading