Accelerator.hpp 7.24 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 "IRTransformation.hpp"
36
#include "XACCFactory.hpp"
37
38
#include <array>
#include <bitset>
39
40
41

namespace xacc {

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/**
 * 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 };

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

class RuntimeType {
public:

};

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

70
71
72
73
/**
 *
 * @author Alex McCaskey
 */
74
class AcceleratorBuffer {
75
public:
76
77
	AcceleratorBuffer(const std::string& str) :
			bufferId(str) {
78
	}
79
80
81
82
83
84
85
86
87
88
89
90
91
	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;
92
	}
93

94
protected:
95

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

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

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

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

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

	virtual int getBufferSize() = 0;

133
134
135
136
137
138
139
140
141
142
143
144
145
146
	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;
	}

147
148
149
protected:

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

151
152
	std::map<std::string, std::shared_ptr<RuntimeType>> runtimeParameters;

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
};

/**
 * 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.
 */
168
template<typename BitsType>
169
170
class Accelerator : public IAccelerator {

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

	using BitsTypePtr = std::shared_ptr<BitsType>;
176
177
178

public:

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

184
185
186
187
188
189
	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 {
190
			XACCError("Invalid buffer variable name.");
191
		}
192
	}
193

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

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

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

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

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

241

242
243
244
	/**
	 * Destructor
	 */
245
	virtual ~Accelerator() {}
246
247
248

protected:

249
	std::map<std::string, BitsTypePtr> allocatedBuffers;
250

251
	BitsTypePtr totalSystemBuffer;
252

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

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

262
};
263

264
265
}
#endif