Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
324 changes: 324 additions & 0 deletions .agent/plans/1687-iqm-01-models.md

Large diffs are not rendered by default.

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

- ✨ Bundle reusable IQM Garnet and Emerald superconducting device models with
stable QDMI registry IDs ([#1992]) ([**@burgholzer**])
- ✨ Add compiler-wide scoped global-phase normalization with exact modifier
semantics and synthesis integration ([#1986]) ([**@burgholzer**])
- ✨ Expose compressed vector and matrix DD serialization through bytes-based
Expand Down Expand Up @@ -705,6 +707,7 @@ for previous changelogs._

<!-- PR links -->

[#1992]: https://github.com/munich-quantum-toolkit/core/pull/1992
[#1986]: https://github.com/munich-quantum-toolkit/core/pull/1986
[#1984]: https://github.com/munich-quantum-toolkit/core/pull/1984
[#1983]: https://github.com/munich-quantum-toolkit/core/pull/1983
Expand Down
67 changes: 55 additions & 12 deletions cmake/AddMQTQDMIDevice.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ endfunction()
# Configure and register a relocatable built-in QDMI device. The generated fragment is emitted
# beside the runtime library in both build and install trees.
function(mqt_configure_qdmi_device target)
cmake_parse_arguments(ARG "" "ID;PREFIX" "RUNTIME_FILES" ${ARGN})
cmake_parse_arguments(ARG "" "ID;PREFIX" "RUNTIME_FILES;CONFIGURATIONS" ${ARGN})
if(NOT TARGET ${target})
message(FATAL_ERROR "Unknown QDMI device target: ${target}")
endif()
Expand All @@ -38,29 +38,72 @@ function(mqt_configure_qdmi_device target)
_mqt_qdmi_json_escape(device_id "${ARG_ID}")
_mqt_qdmi_json_escape(device_prefix "${ARG_PREFIX}")

set(runtime_file_names)
foreach(runtime_file IN LISTS ARG_RUNTIME_FILES)
get_filename_component(runtime_file_name "${runtime_file}" NAME)
list(APPEND runtime_file_names "${runtime_file_name}")
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${runtime_file}"
"$<TARGET_FILE_DIR:${target}>/${runtime_file_name}")
endforeach()

set(device_entries
" {\n \"id\": \"${device_id}\",\n \"library\": \"$<TARGET_FILE_NAME:${target}>\",\n \"prefix\": \"${device_prefix}\",\n \"enabled\": true\n }"
)
set(configuration_ids "${ARG_ID}")
foreach(configuration IN LISTS ARG_CONFIGURATIONS)
string(REPLACE "|" ";" configuration_parts "${configuration}")
list(LENGTH configuration_parts configuration_length)
if(NOT configuration_length EQUAL 2)
message(
FATAL_ERROR
"QDMI configuration '${configuration}' must use the form '<device-id>|<runtime-file-name>'"
)
endif()
list(GET configuration_parts 0 configuration_id)
list(GET configuration_parts 1 configuration_file)
if(configuration_id STREQUAL "" OR configuration_file STREQUAL "")
message(
FATAL_ERROR
"QDMI configuration '${configuration}' must use a non-empty device ID and runtime file name"
)
endif()
list(FIND configuration_ids "${configuration_id}" configuration_id_index)
if(NOT configuration_id_index EQUAL -1)
message(FATAL_ERROR "Duplicate QDMI device ID '${configuration_id}'")
endif()
list(APPEND configuration_ids "${configuration_id}")
list(FIND runtime_file_names "${configuration_file}" runtime_file_index)
if(runtime_file_index EQUAL -1)
message(
FATAL_ERROR
"QDMI configuration '${configuration_id}' refers to unknown runtime file '${configuration_file}'"
)
endif()
_mqt_qdmi_json_escape(configuration_id "${configuration_id}")
_mqt_qdmi_json_escape(configuration_file "${configuration_file}")
string(
APPEND
device_entries
",\n {\n \"id\": \"${configuration_id}\",\n \"library\": \"$<TARGET_FILE_NAME:${target}>\",\n \"prefix\": \"${device_prefix}\",\n \"enabled\": true,\n \"session\": {\n \"device-config\": {\n \"file\": \"${configuration_file}\"\n }\n }\n }"
)
endforeach()

set(fragment "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/${target}.qdmi.json")
file(
GENERATE
OUTPUT "${fragment}"
CONTENT
"{\n \"schema-version\": 1,\n \"qdmi\": {\n \"devices\": [\n {\n \"id\": \"${device_id}\",\n \"library\": \"$<TARGET_FILE_NAME:${target}>\",\n \"prefix\": \"${device_prefix}\",\n \"enabled\": true\n }\n ]\n }\n}\n"
"{\n \"schema-version\": 1,\n \"qdmi\": {\n \"devices\": [\n${device_entries}\n ]\n }\n}\n"
)

add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${fragment}"
"$<TARGET_FILE_DIR:${target}>/${target}.qdmi.json")
set(runtime_file_names)
foreach(runtime_file IN LISTS ARG_RUNTIME_FILES)
get_filename_component(runtime_file_name "${runtime_file}" NAME)
list(APPEND runtime_file_names "${runtime_file_name}")
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${runtime_file}"
"$<TARGET_FILE_DIR:${target}>/${runtime_file_name}")
endforeach()
set_target_properties(
${target}
PROPERTIES QDMI_DEVICE_ID "${ARG_ID}"
Expand Down
31 changes: 26 additions & 5 deletions docs/qdmi/sc_device.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ and fidelity, and optional tuple-specific overrides.
"durationUnit": {"unit": "ns", "scaleFactor": 1.0},
"qubitProperties": {
"defaults": {"t1": 100000, "t2": 150000},
"overrides": [{"qubit": 1, "t1": 95000}]
"overrides": [{"qubit": 1, "name": "QB2", "t1": 95000}]
},
"couplings": [[0, 1]],
"operations": [
Expand Down Expand Up @@ -66,11 +66,32 @@ exact ordered edge in the coupling map. Every site override must select one of
the operation's supported tuples and supply a duration, fidelity, or both.

When operation duration or fidelity is queried, a matching tuple override wins
over the operation default. Missing data returns `QDMI_ERROR_NOTSUPPORTED`.
Qubit T1 and T2 use a per-qubit override first and the qubit default second. The
order of a configured site tuple is significant. Handles from another session
are rejected.
over the operation default. Missing data returns `QDMI_ERROR_NOTSUPPORTED`. Each
qubit override may also provide a non-empty site name. Qubit T1 and T2 use a
per-qubit override first and the qubit default second. The order of a configured
site tuple is significant. Handles from another session are rejected.

The calibration values bundled in `json/sc/mqt-core-qdmi-sc-device.json` are
synthetic examples for testing and documentation; they are not measurements of
physical hardware.

## Bundled IQM models

The SC provider also installs `json/sc/iqm-garnet.json` and
`json/sc/iqm-emerald.json`. They model the 20-qubit, 30-edge Garnet and
54-qubit, 90-edge Emerald architectures and expose the portable IQM operation
set `r`, `cz`, and `measure`. Their stable registry IDs are `mqt.sc.iqm.garnet`
and `mqt.sc.iqm.emerald`.

The snapshots were derived from authenticated IQM architecture and calibration
data retrieved on 2 August 2026 through
[QDMI-on-IQM](https://github.com/iqm-finland/QDMI-on-IQM). Site names and
topology came from each static architecture, operation loci from its default
dynamic architecture, and available T1, T2, and per-locus fidelities from its
default calibration-set quality metrics. Coherence times were rounded to the
nearest nanosecond and stored as integral values using unit `us` and scale
factor `0.001`. They are historical compiler-facing snapshots, not claims about
current hardware calibration.

The IQM interface did not report operation durations, so the files intentionally
omit them.
1 change: 1 addition & 0 deletions include/mqt-core/qdmi/devices/sc/Configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct Device {

struct QubitOverride : QubitCalibration {
uint64_t qubit = 0;
std::optional<std::string> name;
};

struct QubitProperties {
Expand Down
1 change: 1 addition & 0 deletions include/mqt-core/qdmi/devices/sc/Device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct MQT_SC_QDMI_Device_Session_impl_d;
struct MQT_SC_QDMI_Site_impl_d {
MQT_SC_QDMI_Device_Session_impl_d* owner = nullptr;
uint64_t id = 0;
std::optional<std::string> name;
std::optional<uint64_t> t1;
std::optional<uint64_t> t2;

Expand Down
Loading
Loading