forked from NVIDIA/cuda-quantum
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPyFermioniqRESTQPU.cpp
More file actions
114 lines (93 loc) · 4.05 KB
/
PyFermioniqRESTQPU.cpp
File metadata and controls
114 lines (93 loc) · 4.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*******************************************************************************
* Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates. *
* All rights reserved. *
* *
* This source code and the accompanying materials are made available under *
* the terms of the Apache License 2.0 which accompanies this distribution. *
******************************************************************************/
#include "common/ArgumentWrapper.h"
#include "cudaq/Optimizer/InitAllDialects.h"
#include "cudaq/platform/fermioniq/FermioniqBaseQPU.h"
#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
using namespace mlir;
extern "C" void __cudaq_deviceCodeHolderAdd(const char *, const char *);
namespace cudaq {
void registerToQIRTranslation();
void registerToOpenQASMTranslation();
void registerToIQMJsonTranslation();
void registerLLVMDialectTranslation(MLIRContext *context);
} // namespace cudaq
namespace cudaq {
class PyFermioniqRESTQPU : public cudaq::FermioniqBaseQPU {
private:
/// Creates new context without mlir initialization.
MLIRContext *createContext() {
DialectRegistry registry;
cudaq::opt::registerCodeGenDialect(registry);
cudaq::registerAllDialects(registry);
auto context = new MLIRContext(registry);
context->loadAllAvailableDialects();
registerLLVMDialectTranslation(*context);
return context;
}
protected:
std::tuple<ModuleOp, MLIRContext *, void *>
extractQuakeCodeAndContext(const std::string &kernelName,
void *data) override {
auto [mod, ctx] = extractQuakeCodeAndContextImpl(kernelName);
void *updatedArgs = nullptr;
if (data) {
auto *wrapper = reinterpret_cast<cudaq::ArgWrapper *>(data);
updatedArgs = wrapper->rawArgs;
}
return {mod, ctx, updatedArgs};
}
std::tuple<ModuleOp, MLIRContext *>
extractQuakeCodeAndContextImpl(const std::string &kernelName) {
cudaq::info("extract quake code\n");
MLIRContext *context = createContext();
static bool initOnce = [&] {
registerToQIRTranslation();
registerToOpenQASMTranslation();
registerToIQMJsonTranslation();
return true;
}();
(void)initOnce;
// Get the quake representation of the kernel
auto quakeCode = cudaq::get_quake_by_name(kernelName);
auto m_module = parseSourceString<ModuleOp>(quakeCode, context);
if (!m_module)
throw std::runtime_error("module cannot be parsed");
// Here we have an opportunity to run any passes that are
// specific to python before the rest of the RemoteRESTQPU workflow
auto cloned = m_module->clone();
PassManager pm(cloned.getContext());
pm.addPass(cudaq::opt::createLambdaLiftingPass());
cudaq::opt::addAggressiveEarlyInlining(pm);
pm.addNestedPass<func::FuncOp>(cudaq::opt::createClassicalMemToReg());
pm.addNestedPass<func::FuncOp>(createCanonicalizerPass());
pm.addNestedPass<mlir::func::FuncOp>(
cudaq::opt::createUnwindLoweringPass());
pm.addNestedPass<func::FuncOp>(createCanonicalizerPass());
pm.addPass(cudaq::opt::createApplyOpSpecializationPass());
pm.addPass(createInlinerPass());
pm.addPass(cudaq::opt::createExpandMeasurementsPass());
pm.addNestedPass<func::FuncOp>(createCanonicalizerPass());
pm.addNestedPass<func::FuncOp>(createCSEPass());
if (failed(pm.run(cloned)))
throw std::runtime_error(
"Failure to synthesize callable block arguments in PyRemoteRESTQPU ");
std::string moduleStr;
{
llvm::raw_string_ostream os(moduleStr);
cloned.print(os);
}
// The remote rest qpu workflow will need the module string in
// the internal registry.
__cudaq_deviceCodeHolderAdd(kernelName.c_str(), moduleStr.c_str());
return std::make_tuple(cloned, context);
}
void cleanupContext(MLIRContext *context) override { delete context; }
};
} // namespace cudaq
CUDAQ_REGISTER_TYPE(cudaq::QPU, cudaq::PyFermioniqRESTQPU, fermioniq)