Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning], with the exception that minor rel
### Added

- ✨ Add initial infrastructure for new QC and QCO MLIR dialects ([#1264], [#1402], [#1428], [#1430], [#1436], [#1443], [#1446], [#1464], [#1465]) ([**@burgholzer**], [**@denialhaag**], [**@taminob**], [**@DRovara**], [**@li-mingbao**])
- ✨ Add OpenQASM support to mqt-cc CLI tool ([#1470]) ([**@taminob**])

### Changed

Expand Down Expand Up @@ -315,6 +316,7 @@ _📚 Refer to the [GitHub Release Notes](https://github.com/munich-quantum-tool

<!-- PR links -->

[#1470]: https://github.com/munich-quantum-toolkit/core/pull/1470
[#1466]: https://github.com/munich-quantum-toolkit/core/pull/1466
[#1465]: https://github.com/munich-quantum-toolkit/core/pull/1465
[#1464]: https://github.com/munich-quantum-toolkit/core/pull/1464
Expand Down
6 changes: 5 additions & 1 deletion mlir/tools/mqt-cc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ target_link_libraries(
# Required for parsing .mlir files
MLIRParser
# Required for file I/O
MLIRSupport)
MLIRSupport
# Required for OpenQASM parsing
MQT::CoreQASM
MQT::CoreIR
MLIRQCTranslation)
llvm_update_compile_flags(mqt-cc)
mlir_check_all_link_libraries(mqt-cc)
export_executable_symbols_for_plugins(mqt-cc)
84 changes: 59 additions & 25 deletions mlir/tools/mqt-cc/mqt-cc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,15 @@
* Licensed under the MIT License
*/

#include "ir/QuantumComputation.hpp"
#include "mlir/Compiler/CompilerPipeline.h"
#include "mlir/Dialect/QC/IR/QCDialect.h"
#include "mlir/Dialect/QC/Translation/TranslateQuantumComputationToQC.h"
#include "mlir/Dialect/QCO/IR/QCODialect.h"
#include "qasm3/Exception.hpp"
#include "qasm3/Importer.hpp"

#include <exception>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/InitLLVM.h>
#include <llvm/Support/SourceMgr.h>
Expand All @@ -32,13 +37,12 @@
#include <utility>

using namespace llvm;
using namespace mlir;

namespace {

// Command-line options
const cl::opt<std::string> INPUT_FILENAME(cl::Positional,
cl::desc("<input .mlir file>"),
cl::desc("<input .mlir/.qasm file>"),
cl::init("-"));

const cl::opt<std::string> OUTPUT_FILENAME("o", cl::desc("Output filename"),
Expand Down Expand Up @@ -69,31 +73,53 @@ const cl::opt<bool>

} // namespace

/**
* @brief Load and parse a .qasm file
*/
static mlir::OwningOpRef<mlir::ModuleOp>
loadQASMFile(StringRef filename, mlir::MLIRContext* context) {
try {
// Parse the input QASM using MQT-Core
const qc::QuantumComputation qc = qasm3::Importer::importf(filename.str());
// Translate to MLIR dialect QC
return mlir::translateQuantumComputationToQC(context, qc);
} catch (const qasm3::CompilerError& exception) {
errs() << "Failed to parse QASM file '" << filename << "': '"
<< exception.what() << "'\n";
} catch (const std::exception& exception) {
errs() << "Failed to load QASM file '" << filename << "': '"
<< exception.what() << "'\n";
}
return nullptr;
}

/**
* @brief Load and parse a .mlir file
*/
static OwningOpRef<ModuleOp> loadMLIRFile(StringRef filename,
MLIRContext* context) {
static mlir::OwningOpRef<mlir::ModuleOp>
loadMLIRFile(StringRef filename, mlir::MLIRContext* context) {
// Set up the input file
std::string errorMessage;
auto file = openInputFile(filename, &errorMessage);
auto file = mlir::openInputFile(filename, &errorMessage);
if (!file) {
errs() << errorMessage << "\n";
errs() << "Failed to load file '" << filename << "': '" << errorMessage
<< "'\n";
return nullptr;
}

// Parse the input MLIR
SourceMgr sourceMgr;
sourceMgr.AddNewSourceBuffer(std::move(file), SMLoc());
return parseSourceFile<ModuleOp>(sourceMgr, context);
return parseSourceFile<mlir::ModuleOp>(sourceMgr, context);
}

/**
* @brief Write the module to the output file
*/
static mlir::LogicalResult writeOutput(ModuleOp module, StringRef filename) {
static mlir::LogicalResult writeOutput(mlir::ModuleOp module,
StringRef filename) {
std::string errorMessage;
const auto output = openOutputFile(filename, &errorMessage);
const auto output = mlir::openOutputFile(filename, &errorMessage);
if (!output) {
errs() << errorMessage << "\n";
return mlir::failure();
Expand All @@ -108,39 +134,47 @@ int main(int argc, char** argv) {
const InitLLVM y(argc, argv);

// Parse command-line options
cl::ParseCommandLineOptions(argc, argv, "MQT Core Compiler Driver\n");
if (!cl::ParseCommandLineOptions(argc, argv, "MQT Core Compiler Driver\n",
&errs())) {
// error message is printed to stderr via errs()
return -1;
}

// Set up MLIR context with all required dialects
DialectRegistry registry;
registry.insert<qc::QCDialect>();
registry.insert<qco::QCODialect>();
registry.insert<arith::ArithDialect>();
registry.insert<cf::ControlFlowDialect>();
registry.insert<func::FuncDialect>();
registry.insert<scf::SCFDialect>();
registry.insert<LLVM::LLVMDialect>();

MLIRContext context(registry);
mlir::DialectRegistry registry;
registry.insert<mlir::qc::QCDialect>();
registry.insert<mlir::qco::QCODialect>();
registry.insert<mlir::arith::ArithDialect>();
registry.insert<mlir::cf::ControlFlowDialect>();
registry.insert<mlir::func::FuncDialect>();
registry.insert<mlir::scf::SCFDialect>();
registry.insert<mlir::LLVM::LLVMDialect>();

mlir::MLIRContext context(registry);
context.loadAllAvailableDialects();

// Load the input .mlir file
const auto module = loadMLIRFile(INPUT_FILENAME, &context);
mlir::OwningOpRef<mlir::ModuleOp> module;
if (INPUT_FILENAME.getValue().ends_with(".qasm")) {
module = loadQASMFile(INPUT_FILENAME, &context);
} else {
module = loadMLIRFile(INPUT_FILENAME, &context);
}
if (!module) {
errs() << "Failed to load input file: " << INPUT_FILENAME << "\n";
return 1;
}

// Configure the compiler pipeline
QuantumCompilerConfig config;
mlir::QuantumCompilerConfig config;
config.convertToQIR = CONVERT_TO_QIR;
config.recordIntermediates = RECORD_INTERMEDIATES;
config.enableTiming = ENABLE_TIMING;
config.enableStatistics = ENABLE_STATISTICS;
config.printIRAfterAllStages = PRINT_IR_AFTER_ALL_STAGES;

// Run the compilation pipeline
CompilationRecord record;
if (const QuantumCompilerPipeline pipeline(config);
mlir::CompilationRecord record;
if (const mlir::QuantumCompilerPipeline pipeline(config);
pipeline
.runPipeline(module.get(), RECORD_INTERMEDIATES ? &record : nullptr)
.failed()) {
Expand Down
Loading