SIde-Channel Analysis toolKit (SICAK)
Software toolkit for side-channel analysis
oclengine.hpp
Go to the documentation of this file.
1 /*
2 * SICAK - SIde-Channel Analysis toolKit
3 * Copyright (C) 2018 Petr Socha, FIT, CTU in Prague
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18 
29 #ifndef OCLENGINE_HPP
30 #define OCLENGINE_HPP
31 
32 
33 #include <string>
34 
35 #define CL_USE_DEPRECATED_OPENCL_1_1_APIS
36 #ifdef __APPLE__
37 #include <OpenCL/opencl.h>
38 #else
39 #include <CL/cl.h>
40 #endif
41 
42 #include "exceptions.hpp"
43 
50 template<class T>
51 class OclEngine {
52 
53 protected:
54 
55  unsigned int m_platform;
56  unsigned int m_device;
57  cl_context m_context;
58  cl_command_queue m_command_queue;
59  cl_platform_id * m_platforms;
60  cl_device_id * m_devices;
61 
62 public:
63 
65  OclEngine(unsigned int platform, unsigned int device);
66 
67  virtual ~OclEngine();
68 
70  static std::string queryDevices();
71 
73  std::string getTypeName(float dummy) { dummy=dummy; return std::string("float"); }
75  std::string getTypeName(double dummy) { dummy=dummy; return std::string("double"); }
76 
78  std::string getTypeName(int8_t dummy) { dummy=dummy; return std::string("char"); }
80  std::string getTypeName(uint8_t dummy) { dummy=dummy; return std::string("unsigned char"); }
81 
83  std::string getTypeName(int16_t dummy) { dummy=dummy; return std::string("short"); }
85  std::string getTypeName(uint16_t dummy) { dummy=dummy; return std::string("unsigned short"); }
86 
88  std::string getTypeName(int32_t dummy) { dummy=dummy; return std::string("int"); }
90  std::string getTypeName(uint32_t dummy) { dummy=dummy; return std::string("unsigned int"); }
91 
93  std::string getTypeName(int64_t dummy) { dummy=dummy; return std::string("long"); }
95  std::string getTypeName(uint64_t dummy) { dummy=dummy; return std::string("unsigned long"); }
96 
98  static void trimWS(std::string & str);
99 };
100 
101 
102 
103 template<class T>
104 OclEngine<T>::OclEngine(unsigned int platform, unsigned int device): m_platform(platform), m_device(device), m_platforms(NULL), m_devices(NULL) {
105 
106  // Get number of OpenCL platforms available
107  cl_uint ret_num_platforms;
108  cl_int ret = clGetPlatformIDs(0, NULL, &ret_num_platforms);
109  if (ret) throw RuntimeException("Couldn't get number of platforms available", ret);
110  if (ret_num_platforms == 0) throw RuntimeException("No OpenCL platforms found");
111 
112  if (platform >= ret_num_platforms) throw RuntimeException("No such OpenCL platform found");
113 
114  // Alloc memory for the platforms
115  m_platforms = (cl_platform_id*)malloc(ret_num_platforms * sizeof(cl_platform_id));
116  if (m_platforms == NULL) throw RuntimeException("Couldn't alloc memory");
117 
118  // Get the platforms
119  ret = clGetPlatformIDs(ret_num_platforms, m_platforms, NULL);
120  if (ret) {
121  free(m_platforms);
122  throw RuntimeException("Couldn't get platform IDs", ret);
123  }
124 
125  // Get number of OpenCL devices available
126  cl_uint ret_num_devices;
127  ret = clGetDeviceIDs(m_platforms[platform], CL_DEVICE_TYPE_ALL, 0, NULL, &ret_num_devices);
128  if (ret) {
129  free(m_platforms);
130  throw RuntimeException("Couldn't get number of devices available", ret);
131  }
132 
133  if (device >= ret_num_devices) {
134  free(m_platforms);
135  throw RuntimeException("No such OpenCL device found on this platform");
136  }
137 
138  // Alloc memory for the devices
139  m_devices = (cl_device_id*)malloc(ret_num_devices * sizeof(cl_device_id));
140  if (m_devices == NULL) {
141  free(m_platforms);
142  throw RuntimeException("Couldn't alloc memory");
143  }
144 
145  // Get the devices
146  ret = clGetDeviceIDs(m_platforms[platform], CL_DEVICE_TYPE_ALL, ret_num_devices, m_devices, &ret_num_devices);
147  if (ret) {
148  free(m_devices);
149  free(m_platforms);
150  throw RuntimeException("Couldn't get device IDs", ret);
151  }
152 
153  // Create an OpenCL context for the selected device
154  m_context = clCreateContext(NULL, 1, &(m_devices[device]), NULL, NULL, &ret);
155  if (ret) {
156  free(m_devices);
157  free(m_platforms);
158  throw RuntimeException("Couldn't create the OpenCL context", ret);
159  }
160 
161  // Create a command queue
162  m_command_queue = clCreateCommandQueue(m_context, m_devices[device], 0, &ret);
163  if (ret) {
164  ret = clReleaseContext(m_context);
165  free(m_devices);
166  free(m_platforms);
167  throw RuntimeException("Couldn't create a command queue", ret);
168  }
169 
170  // from now on, the destructor becomes responsible for the release
171 }
172 
173 template<class T>
175 
176  cl_int ret;
177  // Release the command queue, context and devices/platforms lists
178  ret = clReleaseCommandQueue(m_command_queue);
179  ret = clReleaseContext(m_context);
180  free(m_devices);
181  free(m_platforms);
182  // ...ignore errors while releasing members (cannot throw out of a destructor; and since the object is being destructed, it doesn't matter much anyway)
183  ret = ret;
184 }
185 
186 template<class T>
187 void OclEngine<T>::trimWS(std::string & str) {
188 
189  const std::string whitespaces = "\t\n\v\f\r ";
190  str.erase(0, str.find_first_not_of(whitespaces));
191  str.erase(str.find_last_not_of(whitespaces) + 1);
192 
193 }
194 
195 template<class T>
197 
198  std::string devicesRet;
199  char textBuffer[1024];
200  std::string textBufferStr;
201 
202  // Get number of OpenCL platforms available
203  cl_uint ret_num_platforms;
204  cl_int ret = clGetPlatformIDs(0, NULL, &ret_num_platforms);
205  if (ret) throw RuntimeException("Couldn't get number of platforms available", ret);
206 
207  if (ret_num_platforms == 0) {
208  return std::string(" No OpenCL platforms found!\n");
209  }
210 
211  // Alloc memory for the platforms
212  cl_platform_id *platforms = NULL;
213  platforms = (cl_platform_id*)malloc(ret_num_platforms * sizeof(cl_platform_id));
214  if (platforms == NULL) throw RuntimeException("Couldn't alloc memory");
215 
216  // Get the platforms
217  ret = clGetPlatformIDs(ret_num_platforms, platforms, NULL);
218  if (ret) {
219  free(platforms);
220  throw RuntimeException("Couldn't get platform IDs", ret);
221  }
222 
223  // Loop through the platforms
224  for (unsigned int i = 0; i < ret_num_platforms; i++) {
225 
226  // Get the platform name
227  ret = clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, sizeof(textBuffer), textBuffer, NULL);
228  if (ret) {
229  free(platforms);
230  throw RuntimeException("Couldn't get platform name", ret);
231  }
232 
233  textBufferStr = textBuffer;
234  trimWS(textBufferStr);
235  devicesRet.append(" * Platform ID: '").append(std::to_string(i)).append("', name: '").append(textBufferStr).append("'");
236 
237  // Get the platform version
238  ret = clGetPlatformInfo(platforms[i], CL_PLATFORM_VERSION, sizeof(textBuffer), textBuffer, NULL);
239  if (ret) {
240  free(platforms);
241  throw RuntimeException("Couldn't get platform version", ret);
242  }
243 
244  devicesRet.append(" (").append(textBuffer).append(")\n");
245 
246  // Get number of OpenCL devices available
247  cl_uint ret_num_devices;
248  ret = clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, 0, NULL, &ret_num_devices);
249  if (ret) {
250  free(platforms);
251  throw RuntimeException("Couldn't get number of devices available", ret);
252  }
253 
254  if (ret_num_devices == 0) {
255  devicesRet.append("No OpenCL devices found\n\n");
256  continue;
257  }
258 
259  // Alloc memory for the devices
260  cl_device_id *devices = NULL;
261  devices = (cl_device_id*)malloc(ret_num_devices * sizeof(cl_device_id));
262  if (devices == NULL) {
263  free(platforms);
264  throw RuntimeException("Couldn't alloc memory");
265  }
266 
267  // Get the devices
268  ret = clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, ret_num_devices, devices, &ret_num_devices);
269  if (ret) {
270  free(devices);
271  free(platforms);
272  throw RuntimeException("Couldn't get device IDs", ret);
273  }
274 
275  // Loop through the devices
276  for (unsigned int k = 0; k < ret_num_devices; k++) {
277 
278  // Get device name
279  ret = clGetDeviceInfo(devices[k], CL_DEVICE_NAME, sizeof(textBuffer), &textBuffer, NULL);
280  if (ret) {
281  free(devices);
282  free(platforms);
283  throw RuntimeException("Couldn't get device name", ret);
284  }
285 
286  textBufferStr = textBuffer;
287  trimWS(textBufferStr); // Intel for some reasons indents this value -> trim whitespace
288  devicesRet.append(" * Device ID: '").append(std::to_string(k)).append("', name: '").append(textBufferStr).append("'\n");
289 
290  }
291 
292  devicesRet.append("\n");
293 
294  free(devices);
295  }
296 
297  free(platforms);
298 
299  return devicesRet;
300 
301 }
302 
303 
304 #endif /* OCLENGINE_HPP */
std::string getTypeName(uint8_t dummy)
Returns the data type name.
Definition: oclengine.hpp:80
std::string getTypeName(uint32_t dummy)
Returns the data type name.
Definition: oclengine.hpp:90
std::string getTypeName(int16_t dummy)
Returns the data type name.
Definition: oclengine.hpp:83
std::string getTypeName(double dummy)
Returns the data type name.
Definition: oclengine.hpp:75
This header file contains exceptions.
std::string getTypeName(int64_t dummy)
Returns the data type name.
Definition: oclengine.hpp:93
std::string getTypeName(uint16_t dummy)
Returns the data type name.
Definition: oclengine.hpp:85
std::string getTypeName(float dummy)
Returns the data type name.
Definition: oclengine.hpp:73
std::string getTypeName(uint64_t dummy)
Returns the data type name.
Definition: oclengine.hpp:95
OpenCL base class template used in other SICAK plugins.
Definition: oclengine.hpp:51
static void trimWS(std::string &str)
Trims white space from string.
Definition: oclengine.hpp:187
std::string getTypeName(int8_t dummy)
Returns the data type name.
Definition: oclengine.hpp:78
OclEngine(unsigned int platform, unsigned int device)
Initializes the specified OpenCL device and creates an OpenCL command queue.
Definition: oclengine.hpp:104
std::string getTypeName(int32_t dummy)
Returns the data type name.
Definition: oclengine.hpp:88
An exception which cannot be directly influenced by the user, or predicted beforehand.
Definition: exceptions.hpp:76
static std::string queryDevices()
Query available platforms and devices.
Definition: oclengine.hpp:196