Program.hpp 6.69 KB
Newer Older
1
/***********************************************************************************
2
 * Copyright (c) 2017, UT-Battelle
3
4
5
6
7
8
9
10
11
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
12
 *   * Neither the name of the xacc nor the
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Contributors:
 *   Initial API and implementation - Alex McCaskey
 *
 **********************************************************************************/
#ifndef XACC_PROGRAM_HPP_
#define XACC_PROGRAM_HPP_

#include <string>
#include <vector>
36
#include <fstream>
37
38
#include <memory>
#include <queue>
39
#include <boost/algorithm/string.hpp>
40
#include <algorithm>
41
42

#include "Utils.hpp"
43
44
#include "Compiler.hpp"
#include "Accelerator.hpp"
45
#include "RuntimeOptions.hpp"
46
#include "Preprocessor.hpp"
47
#include "ServiceRegistry.hpp"
48
#include "Kernel.hpp"
49
50
51

namespace xacc {

52
53
54
55
56
/**
 * Placeholder, soon we will have Acc Independent transformations...
 * @param accType
 * @return
 */
57
58
59
60
61
62
std::vector<IRTransformation> getAcceleratorIndependentTransformations(
		AcceleratorType& accType) {
	std::vector<IRTransformation> transformations;
	return transformations;
}

63
64
std::vector<std::shared_ptr<Preprocessor>> getDefaultPreprocessors(
		AcceleratorType accType) {
65
	std::vector<std::shared_ptr<Preprocessor>> preprocessors;
66
67
	auto preprocessor = ServiceRegistry::instance()->getService<Preprocessor>(
			"kernel-replacement");
68
	if (accType == AcceleratorType::qpu_gate) {
69
		preprocessors.push_back(preprocessor);
70
71
72
73
74
	}

	return preprocessors;
}

75
/**
76
 * The Program is the main entrypoint for the XACC
77
78
79
80
81
 * API. Users with accelerator kernels must construct a
 * valid Program to be compiled and executed on the
 * attached accelerator. Programs must be given the
 * Accelerator reference to be used and kernel source
 * code at construction time.
82
83
84
85
86
 */
class Program {

protected:

87
88
89
90
	/**
	 * Reference to the source accelerator
	 * kernel code to be compiled and executed
	 */
91
92
	std::string src;

93
94
95
96
	/**
	 * Reference to the attached Accelerator to
	 * use in this compilation and execution
	 */
97
	std::shared_ptr<Accelerator> accelerator;
98

99
	/**
100
101
	 * Reference to the XACC IR instance that is
	 * created by the Compiler
102
	 */
103
104
	std::shared_ptr<IR> xaccIR;

105
106
107
	/**
	 * Reference to the compiler
	 */
108
	std::shared_ptr<Compiler> compiler;
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
public:

	/**
	 * The Constructor, takes the Accelerator
	 * to execute on, and the source to compile and execute
	 *
	 * @param acc Attached Accelerator to execute
	 * @param sourceFile The kernel source code
	 */
	Program(std::shared_ptr<Accelerator> acc, const std::string& sourceFile) :
			src(sourceFile), accelerator(std::move(acc)) {
	}

	/**
	 * The Constructor, takes the Accelerator to execute on,
	 * and the source kernel string as a stream.
	 * @param acc Attached Accelerator to execute
	 * @param stream The file stream containing kernel source code
	 */
	Program(std::shared_ptr<Accelerator> acc, std::istream& stream) :
			accelerator(std::move(acc)), src(
					std::istreambuf_iterator<char>(stream), { }) {
	}

134
135
136
137
138
	/**
	 * Execute the compilation mechanism on the provided program
	 * source kernel code to produce XACC IR that can be executed
	 * on the attached Accelerator.
	 */
139
	void build() {
140

141
		// Get reference to the runtime options
142
		auto runtimeOptions = RuntimeOptions::instance();
143

144
145
		// Get the compiler that has been requested.
		auto compilerToRun = (*runtimeOptions)["compiler"];
146
147

		// Create the appropriate compiler
148
149
		compiler = xacc::ServiceRegistry::instance()->getService<Compiler>(
				compilerToRun);
150

151
152
		// Make sure we got a valid
		if (!compiler) {
153
			XACCError("Invalid Compiler.\n");
154
155
		}

156
157
158
159
160
		// Before compiling, run preprocessors
		auto defaultPPs = getDefaultPreprocessors(accelerator->getType());
		for (auto preprocessor : defaultPPs) {
			src = preprocessor->process(src, compiler, accelerator);
		}
161

162
163
		XACCInfo("Executing "+ compiler->getName() + " compiler.");

164
		// Execute the compilation
165
		xaccIR = compiler->compile(src, accelerator);
166
167

		// Validate the compilation
168
		if (!xaccIR) {
169
			XACCError("Bad source string or something.\n");
170
171
		}

172
173
174
175
176
177
		// Execute hardware dependent IR Transformations
		auto accTransforms = accelerator->getIRTransformations();
		for (auto t : accTransforms) {
			xaccIR = t->transform(xaccIR);
		}

178
		// Write the IR to file if the user requests it
179
180
		if (runtimeOptions->exists("persist-ir")) {
			auto fileStr = (*runtimeOptions)["persist-ir"];
181
182
183
184
			std::ofstream ostr(fileStr);
			xaccIR->persist(ostr);
		}

185
		return;
186
187
	}

188
	/**
189
	 * Return an executable version of the kernel
190
	 * referenced by the kernelName string.
191
	 *
192
193
	 * @param name The name of the kernel
	 * @return kernel The Kernel represented by kernelName
194
	 */
195
	template<typename ... RuntimeArgs>
196
197
	auto getKernel(
			const std::string& kernelName) -> Kernel<RuntimeArgs...> {
198
199

		// Build the kernel with the appropriate compiler
200
201
202
		if (!xaccIR) {
			build();
		}
203

204
205
		return Kernel<RuntimeArgs...>(accelerator, xaccIR->getKernel(kernelName));
	}
206

207
208
209
210
211
212
213
214
215
216
217
	/**
	 * Return all Kernels that have sizeof...(RuntimeArgs)
	 * InstructionParameters.
	 * @return kernels Kernels with sizeof...(RuntimeArgs) Parameters.
	 */
	template<typename ... RuntimeArgs>
	auto getKernels() -> std::vector<Kernel<RuntimeArgs...>> {
		std::vector<Kernel<RuntimeArgs...>> kernels;
		if (!xaccIR) {
			build();
		}
218

219
220
221
		for (auto k : xaccIR->getKernels()) {
			if (k->nParameters() == (sizeof...(RuntimeArgs))) {
				kernels.push_back(Kernel<RuntimeArgs...>(accelerator, k));
222
			}
223
		}
224

225
		return kernels;
226
	}
227
228
229
230
};

}
#endif