-
-
Notifications
You must be signed in to change notification settings - Fork 61
add mlir python bindings poc for qasm-to-qco pipeline #1763
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
51b81ef
b7a05b4
d8f9dfe
5acd3f9
ed720c9
37588a5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice to structure this more like https://github.com/llvm/llvm-project/tree/main/mlir/include/mlir/CAPI. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| /* | ||
| * 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 "mlir-c/IR.h" | ||
| #include "mlir-c/Support.h" | ||
|
|
||
| #ifdef __cplusplus | ||
| extern "C" { | ||
| #endif | ||
|
|
||
| MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(QC, qc); | ||
| MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(QCO, qco); | ||
|
|
||
| /** Registers and loads all MQT MLIR dialects into a context. */ | ||
| MLIR_CAPI_EXPORTED void mqtMlirRegisterAllDialects(MlirContext context); | ||
|
|
||
| /** Registers all MQT MLIR passes into the global registry. */ | ||
| MLIR_CAPI_EXPORTED void mqtMlirRegisterAllPasses(void); | ||
|
|
||
| #ifdef __cplusplus | ||
| } | ||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # 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_mlir_public_c_api_library( | ||
| MQTMLIRCoreDialectsCAPI | ||
| Dialects.cpp | ||
| ADDITIONAL_HEADER_DIRS | ||
| ${MQT_MLIR_SOURCE_INCLUDE_DIR}/mlir/CAPI | ||
| ENABLE_AGGREGATION | ||
| LINK_LIBS | ||
| PUBLIC | ||
| MLIRIR | ||
| MLIRSupport | ||
| MLIRQCDialect | ||
| MLIRQCODialect | ||
| MLIRQTensorDialect | ||
| MLIRArithDialect | ||
| MLIRFuncDialect | ||
| MLIRMemRefDialect | ||
| MLIRSCFDialect | ||
| MLIRQCTransforms | ||
| MLIRQCOTransforms | ||
| MLIRQCToQCO) | ||
|
|
||
| mqt_mlir_target_use_project_options(MQTMLIRCoreDialectsCAPI) |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice to structure this more like https://github.com/llvm/llvm-project/tree/main/mlir/lib/CAPI. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| /* | ||
| * 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 | ||
| */ | ||
|
|
||
| #include "mlir/CAPI/Dialects.h" | ||
|
|
||
| #include "mlir-c/IR.h" | ||
| #include "mlir/CAPI/IR.h" | ||
| #include "mlir/CAPI/Registration.h" | ||
| #include "mlir/Conversion/QCToQCO/QCToQCO.h" | ||
| #include "mlir/Dialect/QC/IR/QCDialect.h" | ||
| #include "mlir/Dialect/QC/Transforms/Passes.h" | ||
| #include "mlir/Dialect/QCO/IR/QCODialect.h" | ||
| #include "mlir/Dialect/QCO/Transforms/Passes.h" // NOLINT(misc-include-cleaner) | ||
| #include "mlir/Dialect/QTensor/IR/QTensorDialect.h" | ||
|
|
||
| #include <mlir/Dialect/Arith/IR/Arith.h> | ||
| #include <mlir/Dialect/Func/IR/FuncOps.h> | ||
| #include <mlir/Dialect/MemRef/IR/MemRef.h> | ||
| #include <mlir/Dialect/SCF/IR/SCF.h> | ||
| #include <mlir/IR/DialectRegistry.h> | ||
|
|
||
| MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(QC, qc, ::mlir::qc::QCDialect) | ||
| MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(QCO, qco, ::mlir::qco::QCODialect) | ||
|
|
||
| void mqtMlirRegisterAllDialects(MlirContext context) { | ||
| mlir::DialectRegistry registry; | ||
| registry.insert<mlir::qc::QCDialect, mlir::qco::QCODialect, | ||
| mlir::qtensor::QTensorDialect, mlir::arith::ArithDialect, | ||
| mlir::func::FuncDialect, mlir::memref::MemRefDialect, | ||
| mlir::scf::SCFDialect>(); | ||
| unwrap(context)->appendDialectRegistry(registry); | ||
| unwrap(context)->loadAllAvailableDialects(); | ||
| } | ||
|
|
||
| void mqtMlirRegisterAllPasses() { | ||
| mlir::qc::registerQCPasses(); | ||
| mlir::qco::registerQCOPasses(); | ||
| mlir::registerQCToQCOPasses(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| # 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 | ||
|
|
||
| # Disable versioned soname — causes duplication in Python wheels. | ||
| set(CMAKE_PLATFORM_NO_VERSIONED_SONAME ON) | ||
|
|
||
| set(MQT_MLIR_PYTHON_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mqt/core/mlir") | ||
| set(MQT_MLIR_PYTHON_PACKAGES_DIR "${CMAKE_CURRENT_BINARY_DIR}/python_packages") | ||
|
|
||
| # ################################################################################################## | ||
| # Sources | ||
| # ################################################################################################## | ||
|
|
||
| declare_mlir_python_sources(MQTCoreMLIRPythonSources ROOT_DIR "${MQT_MLIR_PYTHON_ROOT_DIR}" SOURCES | ||
| __init__.py _pipeline.py) | ||
|
|
||
| declare_mlir_python_sources(MQTCoreMLIRPythonExtensions) | ||
|
|
||
| # ################################################################################################## | ||
| # Extension module | ||
| # ################################################################################################## | ||
|
|
||
| declare_mlir_python_extension( | ||
| MQTCoreMLIRPythonExtensions.Main | ||
| MODULE_NAME | ||
| _mqtCoreMlir | ||
| ADD_TO_PARENT | ||
| MQTCoreMLIRPythonExtensions | ||
| SOURCES | ||
| MQTCoreMLIRModule.cpp | ||
| EMBED_CAPI_LINK_LIBS | ||
| MQTMLIRCoreDialectsCAPI | ||
| MLIRQCTranslation | ||
| MLIRSupportMQT | ||
| PRIVATE_LINK_LIBS | ||
| LLVMSupport | ||
| MQT::CoreIR) | ||
|
|
||
| # ################################################################################################## | ||
| # Aggregate and install | ||
| # ################################################################################################## | ||
|
|
||
| set(_source_components MQTCoreMLIRPythonSources MQTCoreMLIRPythonExtensions) | ||
|
|
||
| add_mlir_python_common_capi_library( | ||
| MQTCoreMLIRAggregateCAPI | ||
| INSTALL_COMPONENT | ||
| MQTCoreMLIRPythonModules | ||
| INSTALL_DESTINATION | ||
| python_packages/mqt/core/mlir/_mlir_libs | ||
| OUTPUT_DIRECTORY | ||
| "${MQT_MLIR_PYTHON_PACKAGES_DIR}/mqt/core/mlir/_mlir_libs" | ||
| RELATIVE_INSTALL_ROOT | ||
| "../../../.." | ||
| DECLARED_SOURCES | ||
| ${_source_components}) | ||
|
|
||
| add_mlir_python_modules( | ||
| MQTCoreMLIRPythonModules | ||
| ROOT_PREFIX | ||
| "${MQT_MLIR_PYTHON_PACKAGES_DIR}/mqt/core/mlir" | ||
| INSTALL_PREFIX | ||
| "python_packages/mqt/core/mlir" | ||
| DECLARED_SOURCES | ||
| ${_source_components} | ||
| COMMON_CAPI_LINK_LIBS | ||
| MQTCoreMLIRAggregateCAPI) |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The bindings should live in https://github.com/munich-quantum-toolkit/core/tree/main/bindings. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| /* | ||
| * 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 | ||
| */ | ||
|
|
||
| #include "mlir-c/IR.h" | ||
| #include "mlir/Bindings/Python/NanobindAdaptors.h" // NOLINT(misc-include-cleaner) | ||
| #include "mlir/CAPI/Dialects.h" | ||
| #include "mlir/Conversion/QCToQCO/QCToQCO.h" // NOLINT(misc-include-cleaner) | ||
| #include "mlir/Dialect/QC/Translation/TranslateQuantumComputationToQC.h" // NOLINT(misc-include-cleaner) | ||
| #include "mlir/Support/Passes.h" // NOLINT(misc-include-cleaner) | ||
| #include "qasm3/Importer.hpp" | ||
|
|
||
| #include <llvm/Support/raw_ostream.h> // NOLINT(misc-include-cleaner) | ||
| #include <mlir/IR/BuiltinOps.h> // NOLINT(misc-include-cleaner) | ||
| #include <mlir/IR/MLIRContext.h> // NOLINT(misc-include-cleaner) | ||
| #include <mlir/Pass/PassManager.h> // NOLINT(misc-include-cleaner) | ||
| #include <mlir/Support/LogicalResult.h> // NOLINT(misc-include-cleaner) | ||
|
|
||
| #include <stdexcept> // NOLINT(misc-include-cleaner) | ||
| #include <string> // NOLINT(misc-include-cleaner) | ||
|
|
||
| namespace nb = nanobind; // NOLINT(misc-unused-alias-decls) | ||
|
|
||
| // NOLINTNEXTLINE(misc-use-internal-linkage,readability-identifier-naming,readability-named-parameter) | ||
| NB_MODULE(_mqtCoreMlir, m) { | ||
| mqtMlirRegisterAllPasses(); | ||
|
|
||
| m.doc() = "MQT Core MLIR Python bindings"; | ||
|
|
||
| auto registerDialects = [](MlirContext context) { | ||
| mqtMlirRegisterAllDialects(context); | ||
| }; | ||
| m.def("register_dialects", registerDialects, nb::arg("context"), | ||
| "Register and load QC, QCO, QTensor, and dependent MLIR dialects."); | ||
|
|
||
| m.def( | ||
| "qasm_to_qco", | ||
| [](const std::string& qasm) -> std::string { | ||
| auto qc = qasm3::Importer::imports(qasm); | ||
|
|
||
| mlir::MLIRContext ctx; | ||
| MlirContext cCtx{&ctx}; | ||
| mqtMlirRegisterAllDialects(cCtx); | ||
|
|
||
| auto module = mlir::translateQuantumComputationToQC(&ctx, qc); | ||
| if (!module) { | ||
| throw std::runtime_error("failed to translate circuit to QC MLIR"); | ||
| } | ||
|
|
||
| mlir::PassManager pm(&ctx); | ||
| populateQCCleanupPipeline(pm); | ||
| pm.addPass(mlir::createQCToQCO()); | ||
| if (mlir::failed(pm.run(*module))) { | ||
| throw std::runtime_error("qc-to-qco conversion failed"); | ||
| } | ||
|
|
||
| std::string out; | ||
| llvm::raw_string_ostream os(out); | ||
| module->print(os); | ||
| return out; | ||
| }, | ||
| nb::arg("qasm"), | ||
| "Run the full (py:qasm) -> (mlir:qc) -> (mlir:qco) pipeline."); | ||
| } |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be nice to extend this. All dialects, passes, and conversions should be accessible. It would also be nice to provide a |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # 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 | ||
|
|
||
| """Python bindings for the MQT MLIR compiler collection.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from ._mlir_libs._mqtCoreMlir import qasm_to_qco, register_dialects | ||
| from ._pipeline import compile_qc_to_qco, make_context | ||
|
|
||
| __all__ = ["compile_qc_to_qco", "make_context", "qasm_to_qco", "register_dialects"] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| # 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 | ||
|
|
||
| """High-level pipeline helpers built on top of the MLIR Python bindings.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| from mlir.ir import Context, Module | ||
| from mlir.passmanager import PassManager | ||
|
|
||
| from ._mlir_libs._mqtCoreMlir import register_dialects | ||
|
|
||
|
|
||
| def make_context() -> Context: | ||
| """Return an MLIRContext with all MQT dialects registered and loaded.""" | ||
| ctx = Context() | ||
| register_dialects(ctx) | ||
| return ctx | ||
|
|
||
|
|
||
| def compile_qc_to_qco(mlir_text: str) -> str: | ||
| """Run the qc-to-qco conversion pass on an MLIR module given as text. | ||
|
|
||
| Args: | ||
| mlir_text: MLIR module in the QC dialect, as a string. | ||
|
|
||
| Returns: | ||
| The resulting QCO dialect MLIR module as a string. | ||
| """ | ||
| with make_context() as ctx: | ||
| module = Module.parse(mlir_text, ctx) | ||
| pm = PassManager.parse("builtin.module(qc-to-qco)", ctx) | ||
| pm.run(module.operation) | ||
| return str(module) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # 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_executable(poc-test-pipeline test_pipeline.cpp) | ||
|
|
||
| target_link_libraries( | ||
| poc-test-pipeline | ||
| PRIVATE MLIRQCDialect | ||
| MLIRQCODialect | ||
| MLIRQTensorDialect | ||
| MLIRArithDialect | ||
| MLIRFuncDialect | ||
| MLIRMemRefDialect | ||
| MLIRSCFDialect | ||
| MLIRQCTranslation | ||
| MLIRQCToQCO | ||
| MLIRSupportMQT | ||
| MLIRPass | ||
| MQT::CoreIR | ||
| MQT::CoreQASM) | ||
|
|
||
| mqt_mlir_target_use_project_options(poc-test-pipeline) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BUILD_MQT_CORE_MLIR_PYTHONshould be enabled automatically ifBUILD_MQT_CORE_MLIRandBUILD_MQT_CORE_BINDINGSare both enabled.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would even argue there may be no need for a separate option. Whenever MLIR is enabled and the bindings are as well, this should be built.