Bug Summary

File:OMCompiler/SimulationRuntime/ParModelica/explicit/openclrt/omc_ocl_interface.cpp
Warning:line 194, column 5
Value stored to 'elements' is never read

Annotated Source Code

[?] Use j/k keys for keyboard navigation

1/*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-CurrentYear, Linköping University,
5 * Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3
11 * AND THIS OSMC PUBLIC LICENSE (OSMC-PL).
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S
13 * ACCEPTANCE OF THE OSMC PUBLIC LICENSE.
14 *
15 * The OpenModelica software and the Open Source Modelica
16 * Consortium (OSMC) Public License (OSMC-PL) are obtained
17 * from Linköping University, either from the above address,
18 * from the URLs: http://www.ida.liu.se/projects/OpenModelica or
19 * http://www.openmodelica.org, and in the OpenModelica distribution.
20 * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
21 *
22 * This program is distributed WITHOUT ANY WARRANTY; without
23 * even the implied warranty of MERCHANTABILITY or FITNESS
24 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
25 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS
26 * OF OSMC-PL.
27 *
28 * See the full OSMC Public License conditions for more details.
29 *
30 */
31
32
33/*
34
35 This file contains interfacing functions. Theses are the
36 actuall functions that are available for calling by the
37 code generated from Modelica source.
38 If a function is not called from the generated code please
39 don not add it here.
40 If the feature involves complex operations then define it
41 somewhere else and and just create interface for it here
42 (If it needs to be exported.)
43
44 See the header file for more comments.
45
46 Mahder.Gebremedhin@liu.se 2012-03-31
47
48*/
49
50
51
52#include <omc_ocl_interface.h>
53
54
55size_t modelica_array_nr_of_elements(base_array_t *a){
56 int i;
57 size_t nr_of_elements = 1;
58 for (i = 0; i < a->ndims; ++i) {
59 nr_of_elements *= a->dim_size[i];
60 }
61 return nr_of_elements;
62}
63
64size_t device_array_nr_of_elements(device_array *a){
65 int i;
66 size_t nr_of_elements = 1;
67 for (i = 1; i <= a->info[0]; ++i) {
68 nr_of_elements *= a->info[i];
69 }
70 return nr_of_elements;
71}
72
73
74static inline__inline__ modelica_real *real_ptrget(real_array_t *a, size_t i){
75 return ((modelica_real *) a->data) + i;
76}
77
78static inline__inline__ modelica_integer *integer_ptrget(integer_array_t *a, size_t i){
79 return ((modelica_integer *) a->data) + i;
80}
81
82
83int array_shape_eq(const base_array_t *a, const device_array *b)
84{
85 int i;
86
87 if(a->ndims != b->info[0]) {
88 fprintf(stderrstderr, "a->ndims != b->ndims, %d != %ld\n", a->ndims, b->info[0]);
89 return 0;
90 }
91
92 for(i = 0; i < a->ndims; ++i) {
93 if(a->dim_size[i] != b->info[i+1]) {
94 fprintf(stderrstderr, "a->dim_size[%d] != b->dim_size[%d], %d != %d\n",
95 i, i, (int) a->dim_size[i], (int) b->info[i+1]);
96 return 0;
97 }
98 }
99
100 return 1;
101}
102
103int array_shape_eq(const device_array *a, const device_array *b)
104{
105 int i;
106
107 if(a->info[0] != b->info[0]) {
108 fprintf(stderrstderr, "a->ndims != b->ndims, %ld != %ld\n", a->info[0], b->info[0]);
109 return 0;
110 }
111
112 for(i = 0; i < a->info[0]; ++i) {
113 if(a->info[i+1] != b->info[i+1]) {
114 fprintf(stderrstderr, "a->dim_size[%d] != b->dim_size[%d], %d != %d\n",
115 i, i, (int) a->info[i+1], (int) b->info[i+1]);
116 return 0;
117 }
118 }
119
120 return 1;
121}
122
123
124/* One based index*/
125size_t ocl_calc_base_index_va(base_array_t *source, int ndims, va_list ap){
126 int i;
127 size_t index;
128 int dim_i;
129
130 index = 0;
131 for (i = 0; i < ndims; ++i) {
132 dim_i = va_arg(ap, modelica_integer)__builtin_va_arg(ap, modelica_integer) - 1;
133 index = index * source->dim_size[i] + dim_i;
134 }
135
136 return index;
137}
138
139
140
141
142//functions for allocating device arrays. these should be the entry points to allocate
143//device arrays. the first one is a base array which only initializes the info of the array.
144//the rest allocate the space for the actuall data
145size_t alloc_device_base_array(device_array *dest, int ndims, va_list ap){
146
147 int i;
148
149 dest->info = (modelica_integer*)malloc((ndims + 1)*sizeof(modelica_integer));
150 dest->info[0] = ndims;
151
152 for (i = 1; i < ndims + 1; i++) {
153 dest->info[i] = va_arg(ap, modelica_integer)__builtin_va_arg(ap, modelica_integer);
154 }
155 va_end(ap)__builtin_va_end(ap);
156 return device_array_nr_of_elements(dest);
157
158}
159
160//entry point for allocating integer array on device
161void alloc_integer_array(device_integer_array *dest, int ndims, ...){
162
163 size_t elements = 0;
164 va_list ap;
165 va_start(ap, ndims)__builtin_va_start(ap, ndims);
166 elements = alloc_device_base_array(dest,ndims,ap);
167 va_end(ap)__builtin_va_end(ap);
168 dest->data = ocl_device_alloc(elements*sizeof(modelica_integer));
169 dest->info_dev = ocl_device_alloc_init(dest->info,
170 (ndims+1)*sizeof(modelica_integer));
171
172}
173
174//entry point for allocating real array on device
175void alloc_real_array(device_real_array *dest, int ndims, ...){
176
177 size_t elements = 0;
178 va_list ap;
179 va_start(ap, ndims)__builtin_va_start(ap, ndims);
180 elements = alloc_device_base_array(dest,ndims,ap);
181 va_end(ap)__builtin_va_end(ap);
182 dest->data = ocl_device_alloc(elements*sizeof(modelica_real));
183 dest->info_dev = ocl_device_alloc_init(dest->info,
184 (ndims+1)*sizeof(modelica_integer));
185
186}
187
188//entry point for allocating LOCAL real array on device
189void alloc_device_local_real_array(device_local_real_array *dest, int ndims, ...){
190
191 size_t elements = 0;
192 va_list ap;
193 va_start(ap, ndims)__builtin_va_start(ap, ndims);
194 elements = alloc_device_base_array(dest,ndims,ap);
Value stored to 'elements' is never read
195 va_end(ap)__builtin_va_end(ap);
196 // dest->data = ocl_device_alloc(elements*sizeof(modelica_real));
197 // dest->info_dev = ocl_device_alloc_init(dest->info,
198 // (ndims+1)*sizeof(modelica_integer));
199
200}
201
202
203void free_device_array(device_array* dest){
204 cl_int err;
205 err = clReleaseMemObject(dest->data);
206 ocl_error_check(OCL_REALEASE_MEM_OBJECT, err);
207 err = clReleaseMemObject(dest->info_dev);
208 ocl_error_check(OCL_REALEASE_MEM_OBJECT, err);
209 free(dest->info);
210}
211
212// This is just overloaded to allow the device arrays
213// be freed properly.
214void free_device_array(base_array_t* dest){
215}
216
217
218
219
220void copy_real_array_data(device_real_array dev_array, real_array_t* host_array_ptr){
221 assert(array_shape_eq(host_array_ptr, &dev_array))(static_cast <bool> (array_shape_eq(host_array_ptr, &
dev_array)) ? void (0) : __assert_fail ("array_shape_eq(host_array_ptr, &dev_array)"
, "omc_ocl_interface.cpp", 221, __extension__ __PRETTY_FUNCTION__
))
;
222 int nr_of_elm = device_array_nr_of_elements(&dev_array);
223 ocl_copy_back_to_host_real(dev_array.data, (modelica_real* )host_array_ptr->data, nr_of_elm);
224}
225
226void copy_real_array_data(real_array_t host_array, device_real_array* dev_array_ptr){
227 assert(array_shape_eq(&host_array, dev_array_ptr))(static_cast <bool> (array_shape_eq(&host_array, dev_array_ptr
)) ? void (0) : __assert_fail ("array_shape_eq(&host_array, dev_array_ptr)"
, "omc_ocl_interface.cpp", 227, __extension__ __PRETTY_FUNCTION__
))
;
228 int nr_of_elm = modelica_array_nr_of_elements(&host_array);
229 ocl_copy_to_device_real(dev_array_ptr->data, (modelica_real* )host_array.data, nr_of_elm);
230}
231
232void copy_real_array_data(device_real_array dev_array1, device_real_array* dev_array_ptr2){
233 assert(array_shape_eq(&dev_array1, dev_array_ptr2))(static_cast <bool> (array_shape_eq(&dev_array1, dev_array_ptr2
)) ? void (0) : __assert_fail ("array_shape_eq(&dev_array1, dev_array_ptr2)"
, "omc_ocl_interface.cpp", 233, __extension__ __PRETTY_FUNCTION__
))
;
234 int nr_of_elm = device_array_nr_of_elements(&dev_array1);
235 ocl_copy_device_to_device_real(dev_array1.data, dev_array_ptr2->data, nr_of_elm);
236}
237
238void copy_integer_array_data(device_integer_array dev_array, integer_array_t* host_array_ptr){
239 assert(array_shape_eq(host_array_ptr, &dev_array))(static_cast <bool> (array_shape_eq(host_array_ptr, &
dev_array)) ? void (0) : __assert_fail ("array_shape_eq(host_array_ptr, &dev_array)"
, "omc_ocl_interface.cpp", 239, __extension__ __PRETTY_FUNCTION__
))
;
240 int nr_of_elm = device_array_nr_of_elements(&dev_array);
241 ocl_copy_back_to_host_integer(dev_array.data, (modelica_integer* )host_array_ptr->data, nr_of_elm);
242}
243
244void copy_integer_array_data(integer_array_t host_array, device_integer_array* dev_array_ptr){
245 assert(array_shape_eq(&host_array, dev_array_ptr))(static_cast <bool> (array_shape_eq(&host_array, dev_array_ptr
)) ? void (0) : __assert_fail ("array_shape_eq(&host_array, dev_array_ptr)"
, "omc_ocl_interface.cpp", 245, __extension__ __PRETTY_FUNCTION__
))
;
246 int nr_of_elm = modelica_array_nr_of_elements(&host_array);
247 ocl_copy_to_device_integer(dev_array_ptr->data, (modelica_integer* )host_array.data, nr_of_elm);
248}
249
250
251void copy_integer_array_data(device_integer_array dev_array1, device_integer_array* dev_array_ptr2){
252 assert(array_shape_eq(&dev_array1, dev_array_ptr2))(static_cast <bool> (array_shape_eq(&dev_array1, dev_array_ptr2
)) ? void (0) : __assert_fail ("array_shape_eq(&dev_array1, dev_array_ptr2)"
, "omc_ocl_interface.cpp", 252, __extension__ __PRETTY_FUNCTION__
))
;
253 int nr_of_elm = device_array_nr_of_elements(&dev_array1);
254 ocl_copy_device_to_device_integer(dev_array1.data, dev_array_ptr2->data, nr_of_elm);
255}
256
257
258
259// //functions used for copying scalars. Scalars in the normal(serial C) code genertation
260// //of modelica are copied by assignment (a = b). However to be able to copy them b'n
261// //GPU and host CPU we need to change the assignments to copy functions.
262// void copy_assignment_helper_integer(modelica_integer* v1, modelica_integer* v2){
263 // *v1 = *v2;
264// }
265
266// void copy_assignment_helper_integer(device_integer* v1, modelica_integer* v2){
267 // ocl_copy_to_device_integer(*v1, (modelica_integer* )v2, 1);
268// }
269
270// void copy_assignment_helper_integer(modelica_integer* v1, device_integer* v2){
271 // ocl_copy_back_to_host_integer(*v2, (modelica_integer* )v1, 1);
272// }
273
274// void copy_assignment_helper_integer(device_integer* v1, device_integer* v2){
275 // ocl_copy_device_to_device_integer(*v2, *v1, 1);
276// }
277
278// void copy_assignment_helper_real(modelica_real* v1, modelica_real* v2){
279 // *v1 = *v2;
280// }
281
282// void copy_assignment_helper_real(device_real* v1, modelica_real* v2){
283 // ocl_copy_to_device_real(*v1, (modelica_real* )v2, 1);
284// }
285
286// void copy_assignment_helper_real(modelica_real* v1, device_real* v2){
287 // ocl_copy_back_to_host_real(*v2, (modelica_real* )v1, 1);
288// }
289
290// void copy_assignment_helper_real(device_real* v1, device_real* v2){
291 // ocl_copy_device_to_device_real(*v2, *v1, 1);
292// }
293
294
295
296//this function is added to solve a problem with a memory leak when returning arrays
297//from functions. Arrays used to be assigned just like normal scalar variables. Which causes the
298//allocated memory on the lhs to be lost when the pointer is replaced with the new one.
299//this fixes the problem for parallel arrays. for serial arrays the memory is restored when the
300//function returns(not dynamic allocation), So the only lose in serial case is visible just until
301//the function returns.
302void swap_and_release(device_array* lhs, device_array* rhs){
303 clReleaseMemObject(lhs->data);
304 clReleaseMemObject(lhs->info_dev);
305 free(lhs->info);
306 lhs->data = rhs->data;
307 lhs->info_dev = rhs->info_dev;
308 lhs->info = rhs->info;
309}
310
311//simple assignemnt works fine for srial arrays.
312void swap_and_release(base_array_t* lhs, base_array_t* rhs){
313 *lhs = *rhs;
314}
315
316
317//functions following here are just the same function(the one in real/integer_array.c/h) declared with different names
318//this is done to be able to use the same generated code in normal c runtime and as well as in OpenCL kernels
319//which, right now, doesn't support overloading or the stdarg standard library.
320//even though the functions have the same body here they will have different body on the OpenCL counterparts
321
322m_real* real_array_element_addr_c99_1(real_array_t* source,int ndims,...){
323 va_list ap;
324 m_real* tmp;
325
326 va_start(ap,ndims)__builtin_va_start(ap, ndims);
327 tmp = real_ptrget(source, ocl_calc_base_index_va(source, ndims, ap));
328 va_end(ap)__builtin_va_end(ap);
329
330 return tmp;
331}
332
333m_real* real_array_element_addr_c99_2(real_array_t* source,int ndims,...){
334 va_list ap;
335 m_real* tmp;
336
337 va_start(ap,ndims)__builtin_va_start(ap, ndims);
338 tmp = real_ptrget(source, ocl_calc_base_index_va(source, ndims, ap));
339 va_end(ap)__builtin_va_end(ap);
340
341 return tmp;
342}
343
344m_real* real_array_element_addr_c99_3(real_array_t* source,int ndims,...){
345 va_list ap;
346 m_real* tmp;
347
348 va_start(ap,ndims)__builtin_va_start(ap, ndims);
349 tmp = real_ptrget(source, ocl_calc_base_index_va(source, ndims, ap));
350 va_end(ap)__builtin_va_end(ap);
351
352 return tmp;
353}
354
355m_integer* integer_array_element_addr_c99_1(integer_array_t* source,int ndims,...){
356 va_list ap;
357 m_integer* tmp;
358
359 va_start(ap,ndims)__builtin_va_start(ap, ndims);
360 tmp = integer_ptrget(source, ocl_calc_base_index_va(source, ndims, ap));
361 va_end(ap)__builtin_va_end(ap);
362
363 return tmp;
364}
365
366m_integer* integer_array_element_addr_c99_2(integer_array_t* source,int ndims,...){
367 va_list ap;
368 m_integer* tmp;
369
370 va_start(ap,ndims)__builtin_va_start(ap, ndims);
371 tmp = integer_ptrget(source, ocl_calc_base_index_va(source, ndims, ap));
372 va_end(ap)__builtin_va_end(ap);
373
374 return tmp;
375}
376
377m_integer* integer_array_element_addr_c99_3(integer_array_t* source,int ndims,...){
378 va_list ap;
379 m_integer* tmp;
380
381 va_start(ap,ndims)__builtin_va_start(ap, ndims);
382 tmp = integer_ptrget(source, ocl_calc_base_index_va(source, ndims, ap));
383 va_end(ap)__builtin_va_end(ap);
384
385 return tmp;
386}
387
388
389//array dimension size functions.
390modelica_integer size_of_dimension_real_array(device_real_array dev_arr, modelica_integer dim){
391 return dev_arr.info[dim];
392}
393
394//array dimension size functions.
395modelica_integer size_of_dimension_integer_array(device_integer_array dev_arr, modelica_integer dim){
396 return dev_arr.info[dim];
397}
398
399
400/*
401void print_array_info(device_real_array* arr){
402
403 printf("nr of dims = %ld \n", arr->info[0]);
404
405 for (int i = 1; i <= arr->info[0]; i++){
406 printf("size of dim %d = %ld \n", i,arr->info[i]);
407 }
408 printf("array data pts to %d\n", arr->data);
409}
410*/
411
412void print_array(real_array_t* arr){
413 printf("\n\n");
414 for(int q = 1; q < arr->dim_size[0]; q++){
415 printf(" | %f", (*real_array_element_addr_c99_1(arr, 1, ((modelica_integer) q))));
416 }
417 printf("\n\n\n");
418}
419
420/*
421void print_array(device_real_array* dev_arr){
422 real_array_t arr;
423 int nr_of_elm = device_array_nr_of_elements(dev_arr);
424 alloc_real_array(&arr, 1, nr_of_elm);
425 copy_real_array_data(dev_arr, &arr);
426 print_array(&arr);
427}
428*/