Accelerator.hpp 7.26 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
/***********************************************************************************
 * Copyright (c) 2016, UT-Battelle
 * 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
 *     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_ACCELERATOR_HPP_
#define XACC_ACCELERATOR_HPP_

#include <string>
35
#include <vector>
36
37
#include <array>
#include <bitset>
38
39
#include "IRTransformation.hpp"
#include "XACCError.hpp"
40
41
42

namespace xacc {

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/**
 * Utility structs to help determine if
 * we have been given valid Vertices.
 */
template<typename T, typename = void>
struct is_valid_bitstype: std::false_type {
};
template<typename T>
struct is_valid_bitstype<T, decltype(std::declval<T>().N, void())> : std::true_type {
};

/**
 * The types of Accelerators that XACC interacts with
 */
enum AcceleratorType { qpu_gate, qpu_aqc, npu };

59
60
61
62
63
64
65
66
67
68
69
70

class RuntimeType {
public:

};

template<typename T>
class ConcreteRuntimeType :  public RuntimeType {
public:
	T value;
};

71
72
73
74
/**
 *
 * @author Alex McCaskey
 */
75
class AcceleratorBuffer {
76
public:
77
78
	AcceleratorBuffer(const std::string& str) :
			bufferId(str) {
79
	}
80
81
82
83
84
85
86
87
88
89
90
91
92
	AcceleratorBuffer(const std::string& str, const int N) :
			bufferId(str), bufferSize(N) {
	}
	template<typename ... Indices>
	AcceleratorBuffer(const std::string& str, int firstIndex,
			Indices ... indices) :
			bufferId(str), bufferSize(1 + sizeof...(indices)) {
	}
	int size() {
		return bufferSize;
	}
	std::string name() {
		return bufferId;
93
	}
94

95
protected:
96

97
98
	int bufferSize = 0;
	std::string bufferId;
99
100
};

101
class IAccelerator {
102
public:
103
104
105
106
107
	/**
	 * Return the type of this Accelerator.
	 *
	 * @return type The Accelerator type - Gate or AQC QPU, or NPU
	 */
108
109
	virtual AcceleratorType getType() = 0;

110
111
112
113
114
	/**
	 * Return any IR Transformations that must be applied to ensure
	 * the compiled IR is amenable to execution on this Accelerator.
	 * @return
	 */
115
	virtual std::vector<IRTransformation> getIRTransformations() = 0;
116

117
118
119
120
121
	/**
	 * Execute the provided XACC IR on this attached Accelerator.
	 *
	 * @param ir
	 */
122
	virtual void execute(const std::string& bufferId, const std::shared_ptr<IR> ir) = 0;
123

124
125
126
127
128
129
	/**
	 * Return the number of bits that the user most recently
	 * requested.
	 *
	 * @return nBits The number of requested bits
	 */
130
131
132
133
	virtual int getBufferSize(const std::string& id) = 0;

	virtual int getBufferSize() = 0;

134
135
136
137
138
139
140
141
142
143
144
145
146
147
	template<typename T>
	void setRuntimeParameter(const std::string& name, T param) {
		auto type = std::make_shared<ConcreteRuntimeType<T>>();
		type->value = param;
		runtimeParameters.insert(std::make_pair(name, type));
	}

	template<typename T>
	T getRuntimeParameter(const std::string& name) {
		auto rp = runtimeParameters[name];
		auto cp = std::static_pointer_cast<ConcreteRuntimeType<T>>(rp);
		return cp->value;
	}

148
	virtual ~IAccelerator() {}
149
150
151
protected:

	virtual bool isValidBufferSize(const int NBits) {return true;}
152

153
154
	std::map<std::string, std::shared_ptr<RuntimeType>> runtimeParameters;

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
};

/**
 * The Accelerator class provides a high-level abstraction
 * for XACC's interaction with attached post-exascale
 * accelerators (quantum and neuromorphic processing units).
 *
 * Derived Accelerators must provide a valid execute implementation
 * that takes XACC IR and executes it on the attached hardware or
 * simulator.
 *
 * Derived Accelerators must provide a list of IRTransformation
 * instances that transform XACC IR to be amenable to execution
 * on the hardware.
 */
170
template<typename BitsType>
171
172
class Accelerator : public IAccelerator {

173
174
175
	static_assert(std::is_base_of<AcceleratorBuffer, BitsType>::value, "Accelerators "
			"can only be instantiated with a valid AcceleratorBuffer type as "
			"the template parameter.");
176
177

	using BitsTypePtr = std::shared_ptr<BitsType>;
178
179
180

public:

181
182
183
	Accelerator() {
		totalSystemBuffer = std::make_shared<BitsType>("default");
		allocatedBuffers.insert(std::make_pair("default", totalSystemBuffer));
184
185
	}

186
187
188
189
190
191
	BitsTypePtr createBuffer(const std::string& varId) {
		if (isValidBufferVarId(varId)) {
			auto buffer = std::make_shared<BitsType>(varId);
			allocatedBuffers.insert(std::make_pair(varId, buffer));
			return buffer;
		} else {
192
			XACCError("Invalid buffer variable name.");
193
		}
194
	}
195

196
197
	BitsTypePtr createBuffer(const std::string& varId, const int size) {
		if (!isValidBufferVarId(varId)) {
198
			XACCError("Invalid buffer variable name.");
199
200
		}
		if (!isValidBufferSize(size)) {
201
			XACCError("Invalid buffer size.");
202
203
204
205
206
		}
		auto buffer = std::make_shared<BitsType>(varId, size);
		allocatedBuffers.insert(std::make_pair(varId, buffer));
		return buffer;
	}
207

208
209
210
211
	template<typename... Indices>
	BitsTypePtr createBuffer(const std::string& varId, int firstIndex,
			Indices ... indices) {
		if (!isValidBufferVarId(varId)) {
212
			XACCError("Invalid buffer variable name.");
213
214
		}
		if (!isValidBufferSize(sizeof...(indices) + 1)) {
215
			XACCError("Invalid buffer size.");
216
217
		}
		if (!validIndices(indices...)) {
218
			XACCError("Invalid buffer indices.");
219
220
221
222
		}
		auto buffer = std::make_shared<BitsType>(varId, firstIndex, indices...);
		allocatedBuffers.insert(std::make_pair(varId, buffer));
		return buffer;
223
224
	}

225
226
227
228
229
230
	/**
	 * Return the number of bits that the user most recently
	 * requested.
	 *
	 * @return nBits The number of requested bits
	 */
231
232
	virtual int getBufferSize(const std::string& id) {
		return allocatedBuffers[id]->size();
233
	}
234

235
236
237
238
239
240
	virtual int getBufferSize() {
		return allocatedBuffers["default"]->size();
	}

	BitsTypePtr getExistingBuffer(const std::string& varId) {
		return allocatedBuffers[varId];
241
242
	}

243

244
245
246
	/**
	 * Destructor
	 */
247
	virtual ~Accelerator() {}
248
249
250

protected:

251
	std::map<std::string, BitsTypePtr> allocatedBuffers;
252

253
	BitsTypePtr totalSystemBuffer;
254

255
256
257
	bool isValidBufferVarId(const std::string& str) {
		return allocatedBuffers.find(str) == std::end(allocatedBuffers);
	}
258

259
260
261
262
	template<typename... Indices>
	bool validIndices(int firstIndex, Indices... indices) {
		return false;
	}
263

264
};
265

266
267
}
#endif