Skip to content
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This project adheres to [Semantic Versioning], with the exception that minor rel

- ✨ Add Sampler and Estimator Primitives to the QDMI-Qiskit Interface ([#1507]) ([**@marcelwa**])
- ✨ Add conversions between Jeff and QCO ([#1479], [#1548], [#1565]) ([**@denialhaag**])
- ✨ Add a `place-and-route` pass for mapping circuits to architectures with restricted topologies ([#1537], [#1547], [#1568], [#1581]) ([**@MatthiasReumann**])
- ✨ Add a `place-and-route` pass for mapping circuits to architectures with restricted topologies ([#1537], [#1547], [#1568], [#1581], [#1583]) ([**@MatthiasReumann**])
- ✨ Add initial infrastructure for new QC and QCO MLIR dialects
([#1264], [#1330], [#1402], [#1428], [#1430], [#1436], [#1443], [#1446], [#1464], [#1465], [#1470], [#1471], [#1472], [#1474], [#1475], [#1506], [#1510], [#1513], [#1521], [#1542], [#1548], [#1550], [#1554], [#1570], [#1572], [#1573])
([**@burgholzer**], [**@denialhaag**], [**@taminob**], [**@DRovara**], [**@li-mingbao**], [**@Ectras**], [**@MatthiasReumann**], [**@simon1hofmann**])
Expand Down Expand Up @@ -333,6 +333,7 @@ _📚 Refer to the [GitHub Release Notes](https://github.com/munich-quantum-tool

<!-- PR links -->

[#1583]: https://github.com/munich-quantum-toolkit/core/pull/1583
[#1581]: https://github.com/munich-quantum-toolkit/core/pull/1581
[#1573]: https://github.com/munich-quantum-toolkit/core/pull/1573
[#1572]: https://github.com/munich-quantum-toolkit/core/pull/1572
Expand Down
111 changes: 111 additions & 0 deletions mlir/include/mlir/Dialect/QCO/Utils/Drivers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* 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/Dialect/QCO/IR/QCODialect.h"
#include "mlir/Dialect/QCO/IR/QCOOps.h"

#include <llvm/ADT/TypeSwitch.h>
#include <mlir/IR/Region.h>
#include <mlir/IR/Value.h>
#include <mlir/Support/LLVM.h>

#include <cstddef>
#include <utility>

namespace mlir::qco {
class Qubits {
/**
* @brief Specifies the qubit "location" (hardware or program).
*/
enum class QubitLocation : std::uint8_t { Hardware, Program };

public:
/**
* @brief Add qubit with automatically assigned dynamic index.
*/
[[maybe_unused]] void add(TypedValue<QubitType> q);

/**
* @brief Add qubit with static index.
*/
void add(TypedValue<QubitType> q, std::size_t hw);

/**
* @brief Remap the qubit value from prev to next.
*/
void remap(TypedValue<QubitType> prev, TypedValue<QubitType> next);

/**
* @brief Remove the qubit value.
*/
void remove(TypedValue<QubitType> q);

/**
* @returns the qubit value assigned to a program index.
*/
[[maybe_unused]] TypedValue<QubitType> getProgramQubit(std::size_t index);

/**
* @returns the qubit value assigned to a hardware index.
*/
TypedValue<QubitType> getHardwareQubit(std::size_t index);

private:
DenseMap<std::size_t, TypedValue<QubitType>> programToValue_;
DenseMap<std::size_t, TypedValue<QubitType>> hardwareToValue_;
DenseMap<TypedValue<QubitType>, std::pair<QubitLocation, std::size_t>>
valueToIndex_;
};

/**
* @brief Perform top-down non-recursive walk of all operations within a
* region and apply callback function.
* @details The signature of the callback function is:
*
* (Operation*, Qubits& q) -> WalkResult
*
* where the Qubits object tracks the front of qubit SSA values.
* @param region The targeted region.
* @param fn The callback function.
*/
template <typename Fn> void walkUnit(Region& region, Fn&& fn) {
const auto ffn = std::forward<Fn>(fn);

Qubits qubits;
for (Operation& curr : region.getOps()) {
if (ffn(&curr, qubits).wasInterrupted()) {
break;
};

TypeSwitch<Operation*>(&curr)
.template Case<StaticOp>(
[&](StaticOp op) { qubits.add(op.getQubit(), op.getIndex()); })
.template Case<AllocOp>([&](AllocOp op) { qubits.add(op.getResult()); })
.template Case<UnitaryOpInterface>([&](UnitaryOpInterface op) {
for (const auto& [prevV, nextV] :
llvm::zip(op.getInputQubits(), op.getOutputQubits())) {
const auto prevQ = cast<TypedValue<QubitType>>(prevV);
const auto nextQ = cast<TypedValue<QubitType>>(nextV);
qubits.remap(prevQ, nextQ);
}
})
.template Case<ResetOp>([&](ResetOp op) {
qubits.remap(op.getQubitIn(), op.getQubitOut());
})
.template Case<MeasureOp>([&](MeasureOp op) {
qubits.remap(op.getQubitIn(), op.getQubitOut());
})
.template Case<DeallocOp>(
[&](DeallocOp op) { qubits.remove(op.getQubit()); });
}
}
} // namespace mlir::qco
Loading
Loading