ext: Fix undefined-behavior bug in bitshift
[gem5.git] / ext / nomali / lib / nomali_api.cc
1 /*
2 * Copyright (c) 2014-2016 ARM Limited
3 * All rights reserved
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * Authors: Andreas Sandberg
18 */
19
20 #include "libnomali/nomali.h"
21
22 #include <cstring>
23
24 #include "mali_t6xx.hh"
25 #include "mali_t7xx.hh"
26
27 #define EXPORT __attribute__ ((visibility ("default")))
28
29 static const char *errstrs[] = {
30 "No error",
31 "Unknown error",
32 "Memory allocation failed",
33 "Invalid model handle",
34 "Invalid parameter",
35 };
36
37 static_assert(sizeof(errstrs) / sizeof(*errstrs) == NOMALI_E_NUM_ERRORS,
38 "NoMali API error descriptions out of sync!");
39
40 class NoMaliApi
41 {
42 public:
43 NoMaliApi();
44 ~NoMaliApi();
45
46 void setGpu(NoMali::GPU *gpu) { _gpu = gpu; }
47
48 public:
49 nomali_error_t setCallback(const nomali_callback_t *callback);
50
51 nomali_error_t getInfo(nomali_info_t *info);
52
53 nomali_error_t reset();
54 nomali_error_t regRead(uint32_t *value, nomali_addr_t addr);
55 nomali_error_t regWrite(nomali_addr_t addr, uint32_t value);
56 nomali_error_t regReadRaw(uint32_t *value, nomali_addr_t addr);
57 nomali_error_t regWriteRaw(nomali_addr_t addr, uint32_t value);
58 nomali_error_t intState(int *state, nomali_int_t intno) const;
59
60 public:
61 void callbackInt(nomali_int_t intno, int set);
62 void callbackReset();
63
64 private:
65 nomali_callback_t callbacks[NOMALI_CALLBACK_NUM_CALLBACKS];
66
67 NoMali::GPU *_gpu;
68 };
69
70 template<class BaseGpu>
71 class NoMaliApiGpu
72 : public BaseGpu
73 {
74 public:
75 template<typename... Args>
76 NoMaliApiGpu(NoMaliApi &_api, Args &&... args)
77 : BaseGpu(std::forward<Args>(args)...),
78 api(_api)
79 {
80 reset();
81 }
82
83 void reset() override {
84 BaseGpu::reset();
85 api.callbackReset();
86 }
87
88 public:
89 void intJob(int set) override { api.callbackInt(NOMALI_INT_JOB, set); }
90 void intMMU(int set) override { api.callbackInt(NOMALI_INT_MMU, set); }
91 void intGPU(int set) override { api.callbackInt(NOMALI_INT_GPU, set); }
92
93 private:
94 NoMaliApi &api;
95 };
96
97
98 NoMaliApi::NoMaliApi()
99 : _gpu(nullptr)
100 {
101 memset(callbacks, 0, sizeof(callbacks));
102 }
103
104
105 NoMaliApi::~NoMaliApi()
106 {
107 }
108
109 nomali_error_t
110 NoMaliApi::setCallback(const nomali_callback_t *callback)
111 {
112 if (!callback ||
113 callback->type >= NOMALI_CALLBACK_NUM_CALLBACKS)
114 return NOMALI_E_INVALID;
115
116 callbacks[callback->type] = *callback;
117
118 return NOMALI_E_OK;
119 }
120
121 nomali_error_t
122 NoMaliApi::getInfo(nomali_info_t *info)
123 {
124 if (!info)
125 return NOMALI_E_INVALID;
126
127 info->reg_size = 0x4000;
128
129 return NOMALI_E_OK;
130 }
131
132 nomali_error_t
133 NoMaliApi::reset()
134 {
135 _gpu->reset();
136 return NOMALI_E_OK;
137 }
138
139 nomali_error_t
140 NoMaliApi::regRead(uint32_t *value, nomali_addr_t addr)
141 {
142 if (!value)
143 return NOMALI_E_INVALID;
144
145 *value = _gpu->readReg(NoMali::RegAddr(addr));
146
147 return NOMALI_E_OK;
148 }
149
150 nomali_error_t
151 NoMaliApi::regWrite(nomali_addr_t addr, uint32_t value)
152 {
153 _gpu->writeReg(NoMali::RegAddr(addr), value);
154
155 return NOMALI_E_OK;
156 }
157
158
159 nomali_error_t
160 NoMaliApi::regReadRaw(uint32_t *value, nomali_addr_t addr)
161 {
162 if (!value)
163 return NOMALI_E_INVALID;
164
165 *value = _gpu->readRegRaw(NoMali::RegAddr(addr));
166
167 return NOMALI_E_OK;
168 }
169
170 nomali_error_t
171 NoMaliApi::regWriteRaw(nomali_addr_t addr, uint32_t value)
172 {
173 _gpu->writeRegRaw(NoMali::RegAddr(addr), value);
174
175 return NOMALI_E_OK;
176 }
177
178 nomali_error_t
179 NoMaliApi::intState(int *state, nomali_int_t intno) const
180 {
181 if (!state)
182 return NOMALI_E_INVALID;
183
184 switch (intno) {
185 case NOMALI_INT_GPU:
186 *state = _gpu->intGPUAsserted();
187 break;
188
189 case NOMALI_INT_JOB:
190 *state = _gpu->intJobAsserted();
191 break;
192
193 case NOMALI_INT_MMU:
194 *state = _gpu->intMMUAsserted();
195 break;
196
197 default:
198 return NOMALI_E_INVALID;
199 }
200
201 return NOMALI_E_OK;
202 }
203
204
205 void
206 NoMaliApi::callbackInt(nomali_int_t intno, int set)
207 {
208 const nomali_callback_t &c(callbacks[NOMALI_CALLBACK_INT]);
209
210 if (c.func.interrupt)
211 c.func.interrupt(static_cast<nomali_handle_t>(this), c.usr, intno, set);
212 }
213
214 void
215 NoMaliApi::callbackReset()
216 {
217 const nomali_callback_t &c(callbacks[NOMALI_CALLBACK_RESET]);
218
219 if (c.func.reset)
220 c.func.reset(static_cast<nomali_handle_t>(this), c.usr);
221 }
222
223
224
225 static NoMaliApi *
226 get_gpu(nomali_handle_t h)
227 {
228 return h ? static_cast<NoMaliApi *>(h) : nullptr;
229 }
230
231
232 extern "C" EXPORT nomali_api_version_t
233 nomali_api_version()
234 {
235 return NOMALI_API_VERSION;
236 }
237
238 extern "C" EXPORT nomali_error_t
239 nomali_create(nomali_handle_t *h, const nomali_config_t *cfg)
240 {
241 if (h && cfg) {
242 NoMaliApi *api(new NoMaliApi());
243 *h = api;
244 if (!h)
245 return NOMALI_E_MEMORY;
246
247 NoMali::GPU *gpu;
248 switch (cfg->type) {
249 case NOMALI_GPU_T60X:
250 gpu = new NoMaliApiGpu<NoMali::MaliT60x>(
251 *api,
252 cfg->ver_maj, cfg->ver_min, cfg->ver_status);
253 break;
254
255 case NOMALI_GPU_T62X:
256 gpu = new NoMaliApiGpu<NoMali::MaliT62x>(
257 *api,
258 cfg->ver_maj, cfg->ver_min, cfg->ver_status);
259 break;
260
261
262 case NOMALI_GPU_T76X:
263 gpu = new NoMaliApiGpu<NoMali::MaliT76x>(
264 *api,
265 cfg->ver_maj, cfg->ver_min, cfg->ver_status);
266 break;
267
268 default:
269 delete api;
270 return NOMALI_E_INVALID;
271 };
272
273 if (!gpu) {
274 delete api;
275 return NOMALI_E_MEMORY;
276 }
277
278 api->setGpu(gpu);
279
280 return NOMALI_E_OK;
281 } else {
282 return NOMALI_E_INVALID;
283 }
284 }
285
286 extern "C" EXPORT nomali_error_t
287 nomali_destroy(nomali_handle_t h)
288 {
289 NoMaliApi *gpu(get_gpu(h));
290
291 if (gpu) {
292 delete gpu;
293 return NOMALI_E_OK;
294 } else {
295 return NOMALI_E_HANDLE;
296 }
297 }
298
299 extern "C" EXPORT const char *
300 nomali_errstr(nomali_error_t error)
301 {
302 if (error < NOMALI_E_NUM_ERRORS)
303 return errstrs[error];
304 else
305 return "Invalid error number";
306 }
307
308 extern "C" EXPORT nomali_error_t
309 nomali_set_callback(nomali_handle_t h,
310 const nomali_callback_t *callback)
311 {
312 NoMaliApi *gpu(get_gpu(h));
313 return gpu ? gpu->setCallback(callback) : NOMALI_E_HANDLE;
314 }
315
316 extern "C" EXPORT nomali_error_t
317 nomali_get_info(nomali_handle_t h, nomali_info_t *info)
318 {
319 NoMaliApi *gpu(get_gpu(h));
320 return gpu ? gpu->getInfo(info) : NOMALI_E_HANDLE;
321 }
322
323 extern "C" EXPORT nomali_error_t
324 nomali_reset(nomali_handle_t h)
325 {
326 NoMaliApi *gpu(get_gpu(h));
327 return gpu ? gpu->reset() : NOMALI_E_HANDLE;
328 }
329
330 extern "C" EXPORT nomali_error_t
331 nomali_reg_read(nomali_handle_t h, uint32_t *value,
332 nomali_addr_t addr)
333 {
334 NoMaliApi *gpu(get_gpu(h));
335 return gpu ? gpu->regRead(value, addr) : NOMALI_E_HANDLE;
336 }
337
338 extern "C" EXPORT nomali_error_t
339 nomali_reg_write(nomali_handle_t h,
340 nomali_addr_t addr, uint32_t value)
341 {
342 NoMaliApi *gpu(get_gpu(h));
343 return gpu ? gpu->regWrite(addr, value) : NOMALI_E_HANDLE;
344 }
345
346
347 extern "C" EXPORT nomali_error_t
348 nomali_reg_read_raw(nomali_handle_t h, uint32_t *value,
349 nomali_addr_t addr)
350 {
351 NoMaliApi *gpu(get_gpu(h));
352 return gpu ? gpu->regReadRaw(value, addr) : NOMALI_E_HANDLE;
353 }
354
355 extern "C" EXPORT nomali_error_t
356 nomali_reg_write_raw(nomali_handle_t h,
357 nomali_addr_t addr, uint32_t value)
358 {
359 NoMaliApi *gpu(get_gpu(h));
360 return gpu ? gpu->regWriteRaw(addr, value) : NOMALI_E_HANDLE;
361 }
362
363 extern "C" EXPORT nomali_error_t
364 nomali_int_state(nomali_handle_t h, int *state,
365 nomali_int_t intno)
366 {
367 NoMaliApi *gpu(get_gpu(h));
368 return gpu ? gpu->intState(state, intno) : NOMALI_E_HANDLE;
369 }
370