-
-
Notifications
You must be signed in to change notification settings - Fork 73
✨ Build target environments from QDMI payloads #2227
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: codex/qdmi-capability-integration
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| # QDMI-to-compiler program-capability adapter | ||
|
|
||
| Status: locally validated, design-gated prototype. | ||
|
|
||
| ## Scope and decisions | ||
|
|
||
| Core PR `#2227` snapshots an open QDMI device and an exact accepted program | ||
| format into an owning compiler target environment. The runtime descriptors and | ||
| feature query belong to Core PR `#2226`; the detached compiler model belongs to | ||
| Core PR `#2219`. Neither foundation depends on this adapter or the other | ||
| foundation. A temporary integration base combines them only for testing. | ||
|
|
||
| The adapter preserves format identity and encoding, grouped optional features, | ||
| and the prototype's standard-format baseline. Unknown optional feature metadata | ||
| remains distinct from an empty complete list. Unknown topology or operation | ||
| support still fails during target inference; existing simulator control families | ||
| and zero-arity global phase are unchanged. | ||
|
|
||
| Bindings reuse one session-opening helper with configuration validation at the | ||
| Python boundary. The resulting environment remains valid after the device | ||
| session closes. Tests use explicit known topology in their fake provider. | ||
|
|
||
| ## Design and release boundary | ||
|
|
||
| QDMI issue `#523` and Core issue `#2365` must settle program-capability | ||
| semantics before this prototype is merge-ready. It is a non-blocking Core 4.1 | ||
| candidate, never a Core 4.0 dependency. Native multi-program jobs, driver | ||
| replacement, metadata removal, and compiler control-flow passes remain | ||
| independent. Retarget the adapter to the normal development branch after both | ||
| foundations land. Release artifacts require released dependencies. | ||
|
|
||
| ## Validation | ||
|
|
||
| Run the release CTest suite, Python compiler/QDMI/SDK tests, generated stubs, | ||
| repository lint and C++ lint. Cover exact-format rejection, malformed grouped | ||
| features, optional metadata, QIR baselines, snapshot lifetime and error | ||
| translation. Exercise the documented DDSIM compilation/submission path. | ||
|
|
||
| Local validation passed 3,891 native tests with one existing skip and 454 Python | ||
| compiler/QDMI/SDK tests, including DDSIM bitcode submission. Generated stubs, | ||
| repository lint and C++ lint passed. Hosted CI and contract review remain | ||
| separate gates. | ||
|
|
||
| The source is in `mlir/Compiler/QDMIAdapter`, its unit tests and | ||
| `bindings/mlir/register_mlir.cpp`; canonical usage is documented in | ||
| `docs/mlir/target_compilation.md`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,34 +15,27 @@ Open a configured QDMI device and snapshot it as a compiler target: | |
|
|
||
| ```python | ||
| from mqt.core.mlir import ( | ||
| CompilerTarget, | ||
| PayloadFormat, | ||
| PayloadEncoding, | ||
| PayloadSpecification, | ||
| TargetEnvironment, | ||
| compile_program, | ||
| ) | ||
| from mqt.core.qdmi import ProgramFormat | ||
|
|
||
| target = CompilerTarget.from_device_id("mqt.sc.iqm.garnet") | ||
| payload = PayloadSpecification(PayloadFormat("qir", "2.1.0", "base", PayloadEncoding.BINARY)) | ||
| environment = TargetEnvironment(target, payload) | ||
| environment = TargetEnvironment.from_device_id( | ||
| "mqt.ddsim.default", | ||
| ProgramFormat.QIR21_BASE_BINARY, | ||
|
Contributor
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 SC provider does not advertise any program formats right?
Member
Author
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 does not. But maybe it should. |
||
| ) | ||
| compiled = compile_program( | ||
| "bell.qasm", | ||
| target_environment=environment, | ||
| ) | ||
| ``` | ||
|
|
||
| The payload specification identifies the exact representation selected for the | ||
| device. MQT Core derives the compiler output from that specification and uses | ||
| The QDMI adapter checks that the device accepts the exact program format. It | ||
| groups program-feature records by ID and value, adds the selected format's | ||
| normative baseline, and preserves whether the optional feature list is known. | ||
| MQT Core derives the compiler output from this payload specification and uses | ||
| the canonical QCO pipeline. The targeted overload therefore accepts one | ||
| `TargetEnvironment` and no independent output or custom pipeline. MQT Core's | ||
| QDMI adapter does not yet translate QDMI program-format and feature metadata, so | ||
| callers must construct the payload specification from the device documentation. | ||
|
|
||
| The example has no reported execution capabilities. A producer must add every | ||
| effective capability, including the selected format's baseline. Set | ||
| `optional_capabilities_known=True` only when the producer also knows that the | ||
| list contains every optional device capability. | ||
| `TargetEnvironment` and no independent output or custom pipeline. | ||
|
|
||
| The target can also be constructed directly. Connectivity and native-operation | ||
| support are required: | ||
|
|
@@ -136,35 +129,24 @@ device ID and the compiler-owned target: | |
| ```cpp | ||
| #include "mlir/Compiler/QDMIAdapter.h" | ||
| #include "mlir/Compiler/Programs.h" | ||
| #include "mlir/Compiler/TargetEnvironment.h" | ||
| #include "qdmi/ProgramFormat.hpp" | ||
| #include <llvm/Support/Error.h> | ||
| #include <llvm/Support/raw_ostream.h> | ||
|
|
||
| auto target = mlir::compilerTargetFromDeviceId("mqt.sc.iqm.garnet"); | ||
| if (!target) { | ||
| llvm::errs() << "Failed to create compiler target: " | ||
| << llvm::toString(target.takeError()) << '\n'; | ||
| return 1; | ||
| } | ||
|
|
||
| auto payload = mlir::PayloadSpecification::create({ | ||
| .id = "qir", | ||
| .version = "2.1.0", | ||
| .profile = "base", | ||
| .encoding = mlir::PayloadEncoding::Binary, | ||
| }); | ||
| if (!payload) { | ||
| llvm::errs() << llvm::toString(payload.takeError()) << '\n'; | ||
| auto environment = mlir::targetEnvironmentFromDeviceId( | ||
| "mqt.ddsim.default", qdmi::QIR21_BASE_BINARY); | ||
| if (!environment) { | ||
| llvm::errs() << "Failed to create target environment: " | ||
| << llvm::toString(environment.takeError()) << '\n'; | ||
| return 1; | ||
| } | ||
| mlir::TargetEnvironment environment(*target, *payload); | ||
|
|
||
| auto qc = mlir::QCProgram::fromQASMFile("input.qasm"); | ||
| if (!qc) { | ||
| return 1; | ||
| } | ||
| auto qco = std::move(*qc).intoQCO(); | ||
| if (!qco || !qco->compileForTarget(environment)) { | ||
| if (!qco || !qco->compileForTarget(*environment)) { | ||
| return 1; | ||
| } | ||
| ``` | ||
|
|
||
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.
We still need to streamline our includes when we have fewer PRs open, but this would comply with the current style:
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.
Yeah. You are right. Still have this wired wrongly in my brain. We did device at some point to only treat stdlib includes with angle brackets, right?
Because this is still an external header pulled in as a dependency.
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.
Yeah, but then we changed our minds again, following the discussion in FullStaQD/qcc#37. I still have it on my list to apply this across the MQT. Maybe just before the v4 release is a good time, since we hopefully won't have too many open PRs at that point. 🤔
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.
Yeah. Before the release makes sense.
We may even want to consider that as a point where we may use an "mqt" namespace for our code to differentiate it a tad bit more from plain mlir. Similar to how this is done in FullStaQD with
qcc. I was initially opposed to that but I am starting to see the potential benefits.