✨ Integrate QDMI Devices - #1687
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
arch optionarch Option
arch Option|
@burgholzer (cc: @ystade) This pull request now implements a very basic QDMI V1 integration into our compiler collection. Before continuing, I want to discuss the following issues. Optionally enable QDMIAs of now, the current implementation tightly couples the Extract Nested ClassesIn order to augment the FoMaC device classes, I think it would be nice to extract them outside the Trailing Return Types (Nitpick, sorry!)I am really not that sure if the FoMaC classes benefit from the benefits of trailing return types. The // fomac/FoMaC.cpp
auto getParametersNum(const std::vector<Site>& sites = {},
const std::vector<double>& params = {}) const -> size_t;
// qdmi/sc/Device.hpp
auto sessionFree(MQT_SC_QDMI_Device_Session session) -> void;I've taken the liberty to implement some of the above FoMaC changes this morning (+ some improvements using modern C++ concepts) in Any comments appreciated! Many thanks 🙏 |
Hm. I'd argue that if we view QDMI as the primary way to add architecture information to
We have an open tracking issue going in that direction #1358. See also #1363 (comment)
Feel free to get rid of them. I am personally not the biggest fan of these either way.
Thanks, I'll take a look! 👍🏼
|
I was kind of thinking about IBM Benchpress. Not sure if we could still use QDMI here that easily.
Oh. Great! I'll have a look at these and try to incorporate them in the refactoring.
I've also opened #1849 to ease the comparison to the old implementation. |
I was hoping that we could take the input from benchpress and wrap it in QDMI at runtime.
Take those with a grain of salt though. It's been a while that they have been written and some circumstances might have changed since then. Still good to have a look though. |
|
A little late, but since I was tagged, I also wanted to comment: Trailing return typesI guess I am responsible for them. I love them because when you read FoMaC ConceptI guess everything has already been said here. I can just repeat here that in the future we want to directly build on QDMI and want to get rid of FoMaC or rather replace that by a C++ abstraction of QDMI. |
|
@coderabbitai full review |
✅ Action performedFull review finished. |
📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds QDMI and device-aware support, changes mapping to use shared superconducting devices, inserts optional transpilation into the compiler pipeline, and adds ChangesDevice-Driven Transpilation
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant mqt_cc
participant QDMI
participant QuantumCompilerPipeline
participant MappingPass
User->>mqt_cc: Select QDMI device
mqt_cc->>QDMI: Prepare session and resolve device
mqt_cc->>QuantumCompilerPipeline: Set config.device
QuantumCompilerPipeline->>MappingPass: Run device-based transpilation
MappingPass-->>QuantumCompilerPipeline: Return transformed IR
QuantumCompilerPipeline-->>mqt_cc: Return compilation record
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@mlir/include/mlir/Support/Qdmi.h`:
- Around line 20-26: Add Doxygen-style documentation comments on the header
declarations for mlir::qdmi::listAvailableDevices and mlir::qdmi::getDevice.
Describe each function’s purpose, its session parameter, the output stream
behavior for listAvailableDevices, and what getDevice returns when given a
device name; place the comments directly above the declarations in Qdmi.h to
match project convention.
In `@mlir/lib/Compiler/CompilerPipeline.cpp`:
- Around line 176-210: Remove the unused local SuperconductingDevice in the
CompilerPipeline transpilation block and update the stage counting logic so
totalStages includes the two device-dependent stages when config_.device is set.
In the pipeline around runStage, keep the mapping pass using
qco::createMappingPass and eliminate the dead scDevice construction, then adjust
the totalStages calculation near the pipeline setup so prettyPrintStage reports
the correct progress for both optional transpilation and QCO cleanup stages.
In `@mlir/lib/Dialect/QCO/Transforms/Mapping/Mapping.cpp`:
- Around line 206-209: The constructor doc comment for MappingPass is stale and
still refers to a coupling set instead of the current device-based API. Update
the comment above MappingPassPassPass? constructor in MappingPass to describe
constructing the pass from a SuperconductingDevice, matching the
std::shared_ptr<SuperconductingDevice> parameter and keeping the wording aligned
with the current interface.
In `@mlir/lib/Support/SuperconductingDevice.cpp`:
- Around line 57-58: The coupling map handling in SuperconductingDevice
currently leaves the QDMI edge-direction semantics unresolved, which can make
adjacency checks inconsistent. Update the logic around the QDMI site-to-graph
construction so the relevant Graph/coupling set representation matches QDMI’s
actual edge semantics, and ensure areAdjacent(u, v) succeeds for both directions
if the source data is undirected. Use the SuperconductingDevice construction
path and the areAdjacent adjacency behavior as the main points to verify the
fix.
- Around line 29-36: In SuperconductingDevice::distanceBetween, replace the
UINT64_MAX sentinel check with std::numeric_limits<size_t>::max() so it matches
Graph::getDistMatrix()’s initialization and stays portable. Update the
comparison in distanceBetween to use the size_t max value, and ensure the needed
numeric_limits include is available through the existing includes rather than
relying on UINT64_MAX.
- Around line 50-72: The current getCouplingGraph implementation uses raw
site.getIndex() values from fomac::Device when constructing Graph, but those IDs
may be non-contiguous or offset, so remap all site IDs to a dense 0-based index
space before filling the qubit vector and coupling pairs. Update the logic in
SuperconductingDevice::getCouplingGraph to build a stable old-to-new index
mapping from device->getSites() and apply it to both the qubit list and the
coupling set so Graph receives valid contiguous indices.
In `@mlir/tools/mqt-cc/mqt-cc.cpp`:
- Around line 194-218: In mqt-cc.cpp, handle the requested-device failure in the
main compile flow by returning a nonzero exit code immediately after `getDevice`
fails and `listAvailableDevices(session, llvm::errs())` is printed, so the
pipeline does not continue with a null `config.device`. Also update the
intermediate-dump path in the compilation output to print the transpilation
records captured by `recordIntermediates`, specifically adding the
`afterTranspilation` and `afterTranspilationCanon` outputs in the section around
the existing “After Final QCO Canonicalization” and “After QCO-to-QC Conversion”
messages.
- Line 16: The include in mqt-cc.cpp uses the wrong header casing, which can
fail on case-sensitive filesystems. Update the include in the same spot to match
the actual header name, using the Qdmi.h casing so it aligns with
mlir/Support/Qdmi.h and the rest of the build references.
In `@mlir/unittests/Dialect/QCO/Transforms/Mapping/test_mapping.cpp`:
- Around line 134-145: The helper getNineQubitSquareGrid is mislabeled in its
comment: it constructs a 3×3 grid of 9 qubits, not a 9×9 topology. Update the
documentation comment above getNineQubitSquareGrid in test_mapping.cpp to
describe the actual 3×3 square-grid coupling set so the topology name matches
the connectivity.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 21adacff-e169-4b63-8e06-220ffd4384ed
📒 Files selected for processing (14)
mlir/include/mlir/Compiler/CompilerPipeline.hmlir/include/mlir/Dialect/QCO/Transforms/Mapping/Mapping.hmlir/include/mlir/Support/Graph.hmlir/include/mlir/Support/Qdmi.hmlir/include/mlir/Support/SuperconductingDevice.hmlir/lib/Compiler/CompilerPipeline.cppmlir/lib/Dialect/QCO/Transforms/CMakeLists.txtmlir/lib/Dialect/QCO/Transforms/Mapping/Mapping.cppmlir/lib/Dialect/QCO/Utils/Graph.cppmlir/lib/Support/CMakeLists.txtmlir/lib/Support/Qdmi.cppmlir/lib/Support/SuperconductingDevice.cppmlir/tools/mqt-cc/mqt-cc.cppmlir/unittests/Dialect/QCO/Transforms/Mapping/test_mapping.cpp
|
@coderabbitai full review |
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@mlir/include/mlir/Support/SuperconductingDevice.h`:
- Around line 45-46: Document the edge-case contract for
SuperconductingDevice::distanceBetween so callers know what it returns when u ==
v and when no path exists between qubits. Update the Doxygen comment on
distanceBetween to explicitly state the expected behavior for reachable versus
unreachable nodes, and make sure the wording prevents misuse by callers like the
heuristic in Mapping.cpp that subtracts 1 from the returned value.
In `@mlir/lib/Compiler/CompilerPipeline.cpp`:
- Line 214: The stage labels in CompilerPipeline comments are duplicated after
the earlier renumbering, so update the QIR stage comments in the pipeline to use
the correct sequential numbers. In CompilerPipeline, adjust the comments around
the QIR-related stages so they no longer say Stage 9/Stage 10 and instead match
the actual device-configured ordering (QIR stages 11 and 12), keeping the labels
consistent with the surrounding stage comments.
In `@mlir/lib/Support/Qdmi.cpp`:
- Around line 23-24: The loop in Qdmi.cpp is copying each device unnecessarily
because `session.getDevices()` yields `fomac::Device` objects and only
`getName()` is used. Update the range-based loop in the QDMI output code to
iterate with `const auto&` instead of `auto`, so the devices are read by
reference without extra copies.
- Around line 32-37: Replace the manual iterator search in the device lookup
with `std::find_if` for a more idiomatic and concise implementation. Update the
loop in the device-search logic to use `std::find_if` over `devices`, keeping
the same name-matching predicate on `getName()` and preserving the existing
behavior of returning the matching iterator or `devices.end()` when not found.
In `@mlir/lib/Support/SuperconductingDevice.cpp`:
- Around line 51-56: The getCouplingGraph logic currently relies on an assert
after calling device->getCouplingMap(), which can be compiled out and leave
siteCoupling dereferenced in release builds. Replace that assert with an
explicit runtime failure in getCouplingGraph before any use of
siteCoupling->size() or *siteCoupling, and keep the same guard covering all
subsequent coupling-map access so a missing map is handled safely.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: fcf330bd-3fe1-49ea-bc63-80915d3ca0cc
📒 Files selected for processing (14)
mlir/include/mlir/Compiler/CompilerPipeline.hmlir/include/mlir/Dialect/QCO/Transforms/Mapping/Mapping.hmlir/include/mlir/Support/Graph.hmlir/include/mlir/Support/Qdmi.hmlir/include/mlir/Support/SuperconductingDevice.hmlir/lib/Compiler/CompilerPipeline.cppmlir/lib/Dialect/QCO/Transforms/CMakeLists.txtmlir/lib/Dialect/QCO/Transforms/Mapping/Mapping.cppmlir/lib/Dialect/QCO/Utils/Graph.cppmlir/lib/Support/CMakeLists.txtmlir/lib/Support/Qdmi.cppmlir/lib/Support/SuperconductingDevice.cppmlir/tools/mqt-cc/mqt-cc.cppmlir/unittests/Dialect/QCO/Transforms/Mapping/test_mapping.cpp
|
I think this one is ready to discuss.
--qdmi-list-devices // List all available QDMI devices.
--qdmi-device=iqm-radiance // Specify the device used for hardware-specific passes.
--qdmi-config=./qdmi.json // Specify session config, additional devices and their respective configs.
CLI Examplematthias:~$ cat ~/Downloads/qdmi.json
{
"devices": [
{
"libName": "/Users/matthias/Documents/projects/core/build/src/qdmi/devices/sc/libmqt-core-qdmi-sc-device.dylib",
"prefix": "MQT_SC",
"deviceConfig": {
"baseUrl": "...",
"token": "...",
"authFile": "...",
"authUrl": "...",
"username": "...",
"password": "...",
"custom1": "...",
"custom2": "...",
"custom3": "...",
"custom4": "...",
"custom5": "..."
}
}
]
}
matthias:~$ mqt-cc --qdmi-list-devices --qdmi-config ~/Downloads/qdmi.json
[2026-07-09 14:03:58.473] [info] [Driver.cpp:193] Device session parameter BASE URL not supported by device (skipped)
[2026-07-09 14:03:58.474] [info] [Driver.cpp:193] Device session parameter TOKEN not supported by device (skipped)
[2026-07-09 14:03:58.474] [info] [Driver.cpp:193] Device session parameter AUTH FILE not supported by device (skipped)
[2026-07-09 14:03:58.474] [info] [Driver.cpp:193] Device session parameter AUTH URL not supported by device (skipped)
[2026-07-09 14:03:58.474] [info] [Driver.cpp:193] Device session parameter USERNAME not supported by device (skipped)
[2026-07-09 14:03:58.474] [info] [Driver.cpp:193] Device session parameter PASSWORD not supported by device (skipped)
[2026-07-09 14:03:58.474] [info] [Driver.cpp:193] Device session parameter CUSTOM1 not supported by device (skipped)
[2026-07-09 14:03:58.474] [info] [Driver.cpp:193] Device session parameter CUSTOM2 not supported by device (skipped)
[2026-07-09 14:03:58.474] [info] [Driver.cpp:193] Device session parameter CUSTOM3 not supported by device (skipped)
[2026-07-09 14:03:58.474] [info] [Driver.cpp:193] Device session parameter CUSTOM4 not supported by device (skipped)
[2026-07-09 14:03:58.474] [info] [Driver.cpp:193] Device session parameter CUSTOM5 not supported by device (skipped)
Available QDMI devices:
MQT NA Default QDMI Device // Statically loaded.
MQT SC Default QDMI Device // Statically loaded.
MQT Core DDSIM QDMI Device // Statically loaded.
MQT SC Default QDMI Device // Dynamically loaded.Footnotes
|
|
I have not yet had the chance to look through everything in detail here yet, but I have one general high-level observation already: A lot of the QDMI-related functionality is built "outside" of QDMI here (building on top of FoMaC; relying on @MatthiasReumann does that make sense? Can you work with that? |
I'll try to summarize my thoughts on this. Let me know, if the following is valid.
Generally understood.
I wonder: Is there any valid reason to link devices statically in the Because isn't the purpose of the
Understood. Currently, what really confuses me - and I just realized - is that the Footnotes
|
Assisted-by: GPT-5.6 via Codex
Assisted-by: GPT-5.6 via Codex
Assisted-by: GPT-5.6 via Codex
Integrate qubit reuse with target compilation by supporting scalar QCO allocations during mapping and verifying reuse runs before placement. Assisted-by: GPT-5.6 via Codex
|
@MatthiasReumann I skimmed through the conversation here, and to me, everything makes a lot of sense. I do not have additional comments that go beyond Lukas' ones right now. Let me know whether you would like to have feedback on any particular point. |
burgholzer
left a comment
There was a problem hiding this comment.
Alright. Iterated on this quite a bit with the help of gpt-5.6-sol.
The comments in this review are not intended for @MatthiasReumann, but for iteration work on the PR that I am planning.
Let's see how quickly the iteration converges.
But I think this is starting to look really clean.
dd9619b to
11ec581
Compare
Add a detached FoMaC adapter, Python target bindings, and the minimal mqt-cc device workflow on top of the compiler-owned target pipeline. Preserve calibration metadata, reject unsupported site models, and keep conformance as the final target check. Assisted-by: GPT-5.6 via Codex
Assisted-by: GPT-5.6 via Codex
Assisted-by: GPT-5.6 via Codex
Assisted-by: GPT-5.6 via Codex
Require the bundled providers for full test builds so provider-backed tests can be registered unconditionally. Exercise the real Garnet target in Python while keeping a small direct sparse target for isolated API coverage. Assisted-by: GPT-5.6 via Codex
8f43272 to
ea98c0b
Compare
Assisted-by: GPT-5.6 via Codex
burgholzer
left a comment
There was a problem hiding this comment.
Alright. This feels like it is ready 🚀
Feels great to have QDMI integrated into the Compiler Collection 🥳
🤖 AI text below 🤖
Summary
This is the final integration slice of the compiler-target series. It:
mlir::CompilerTarget, including names, topology, coherence data, operationcapabilities, and available calibration;
source-build
mqt-cc;mqt-ccdevice listing, explicit registry configuration, and stable-IDdevice selection without introducing another driver or target abstraction;
conformance verification.
The bridge validates that QDMI operation support fits the compiler's homogeneous
bidirectional target model. Directional operations must report both ordered
orientations on every supported pair, while operand-symmetric operations such as
CZ may report each undirected edge once. Devices without topology and operation
site restrictions retain the all-to-all convention used by DDSIM. Neutral-atom
zone models are rejected with a focused diagnostic.
Design
CompilerTargetremains owned by the MLIR compiler and independent of FoMaC,QDMI, and the legacy CoreIR target. The optional adapter is the only library
linking FoMaC to the compiler target. It snapshots all data eagerly, so
compilation does not retain a device or session handle.
Python exposes
CompilerTarget.from_device,QCOProgram.compile_for_target,and
compile_program(..., target=...). The C++ adapter andmqt-ccworkflow aresource-build interfaces; this PR does not create a partial installed MLIR SDK
boundary or change wheel shipment for
mqt-cc.Validation
mqt-ccCTestsgit diff --checkCloses #1082