2 Copyright (c) 2014 Intel Corporation. All Rights Reserved.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "cean_util.h"
32 #include "offload_common.h"
34 // 1. allocate element of CeanReadRanges type
35 // 2. initialized it for reading consequently contiguous ranges
36 // described by "ap" argument
37 CeanReadRanges
* init_read_ranges_arr_desc(const arr_desc
*ap
)
41 // find the max contiguous range
42 int64_t rank
= ap
->rank
- 1;
43 int64_t length
= ap
->dim
[rank
].size
;
44 for (; rank
>= 0; rank
--) {
45 if (ap
->dim
[rank
].stride
== 1) {
46 length
*= (ap
->dim
[rank
].upper
- ap
->dim
[rank
].lower
+ 1);
47 if (rank
> 0 && length
!= ap
->dim
[rank
- 1].size
) {
56 res
=(CeanReadRanges
*)malloc(sizeof(CeanReadRanges
) +
57 (ap
->rank
- rank
) * sizeof(CeanReadDim
));
59 LIBOFFLOAD_ERROR(c_malloc
);
60 res
->current_number
= 0;
61 res
->range_size
= length
;
62 res
->last_noncont_ind
= rank
;
64 // calculate number of contiguous ranges inside noncontiguous dimensions
66 bool prev_is_cont
= true;
69 for (; rank
>= 0; rank
--) {
70 res
->Dim
[rank
].count
= count
;
71 res
->Dim
[rank
].size
= ap
->dim
[rank
].stride
* ap
->dim
[rank
].size
;
72 count
*= (prev_is_cont
&& ap
->dim
[rank
].stride
== 1? 1 :
73 (ap
->dim
[rank
].upper
- ap
->dim
[rank
].lower
+
74 ap
->dim
[rank
].stride
) / ap
->dim
[rank
].stride
);
76 offset
+=(ap
->dim
[rank
].lower
- ap
->dim
[rank
].lindex
) *
79 res
->range_max_number
= count
;
80 res
-> ptr
= (void*)ap
->base
;
81 res
-> init_offset
= offset
;
85 // check if ranges described by 1 argument could be transfered into ranges
86 // described by 2-nd one
87 bool cean_ranges_match(
88 CeanReadRanges
* read_rng1
,
89 CeanReadRanges
* read_rng2
92 return ( read_rng1
== NULL
|| read_rng2
== NULL
||
93 (read_rng1
->range_size
% read_rng2
->range_size
== 0 ||
94 read_rng2
->range_size
% read_rng1
->range_size
== 0));
97 // Set next offset and length and returns true for next range.
98 // Returns false if the ranges are over.
100 CeanReadRanges
* read_rng
,
104 if (++read_rng
->current_number
> read_rng
->range_max_number
) {
105 read_rng
->current_number
= 0;
109 int num
= read_rng
->current_number
- 1;
110 int64_t cur_offset
= 0;
112 for (; rank
<= read_rng
->last_noncont_ind
; rank
++) {
113 num_loc
= num
/ read_rng
->Dim
[rank
].count
;
114 cur_offset
+= num_loc
* read_rng
->Dim
[rank
].size
;
115 num
= num
% read_rng
->Dim
[rank
].count
;
117 *offset
= cur_offset
+ read_rng
->init_offset
;
121 bool is_arr_desc_contiguous(const arr_desc
*ap
)
123 int64_t rank
= ap
->rank
- 1;
124 int64_t length
= ap
->dim
[rank
].size
;
125 for (; rank
>= 0; rank
--) {
126 if (ap
->dim
[rank
].stride
> 1 &&
127 ap
->dim
[rank
].upper
- ap
->dim
[rank
].lower
!= 0) {
130 else if (length
!= ap
->dim
[rank
].size
) {
131 for (; rank
>= 0; rank
--) {
132 if (ap
->dim
[rank
].upper
- ap
->dim
[rank
].lower
!= 0) {
138 length
*= (ap
->dim
[rank
].upper
- ap
->dim
[rank
].lower
+ 1);
143 int64_t cean_get_transf_size(CeanReadRanges
* read_rng
)
145 return(read_rng
->range_max_number
* read_rng
->range_size
);
148 static uint64_t last_left
, last_right
;
149 typedef void (*fpp
)(const char *spaces
, uint64_t low
, uint64_t high
, int esize
);
151 static void generate_one_range(
160 "%s generate_one_range(lrange=%p, rrange=%p, esize=%d)\n",
161 spaces
, (void*)lrange
, (void*)rrange
, esize
);
162 if (last_left
== -1) {
167 if (lrange
== last_right
+1) {
168 // Extend previous range, don't print
171 (*fp
)(spaces
, last_left
, last_right
, esize
);
178 static void generate_mem_ranges_one_rank(
182 const struct dim_desc
*ddp
,
187 uint64_t lindex
= ddp
->lindex
;
188 uint64_t lower
= ddp
->lower
;
189 uint64_t upper
= ddp
->upper
;
190 uint64_t stride
= ddp
->stride
;
191 uint64_t size
= ddp
->size
;
194 "generate_mem_ranges_one_rank(base=%p, rank=%lld, lindex=%lld, "
195 "lower=%lld, upper=%lld, stride=%lld, size=%lld, esize=%d)\n",
196 spaces
, (void*)base
, rank
, lindex
, lower
, upper
, stride
, size
, esize
);
198 uint64_t lrange
, rrange
;
200 lrange
= base
+ (lower
-lindex
)*size
;
201 rrange
= lrange
+ (upper
-lower
+1)*size
- 1;
202 generate_one_range(spaces
, lrange
, rrange
, fp
, esize
);
205 for (int i
=lower
-lindex
; i
<=upper
-lindex
; i
+=stride
) {
206 lrange
= base
+ i
*size
;
207 rrange
= lrange
+ size
- 1;
208 generate_one_range(spaces
, lrange
, rrange
, fp
, esize
);
213 for (int i
=lower
-lindex
; i
<=upper
-lindex
; i
+=stride
) {
214 generate_mem_ranges_one_rank(
215 spaces
, base
+i
*size
, rank
-1, ddp
+1, fp
, esize
);
221 static void generate_mem_ranges(
232 "generate_mem_ranges(adp=%p, deref=%d, fp)\n",
237 // Element size is derived from last dimension
238 esize
= adp
->dim
[adp
->rank
-1].size
;
240 generate_mem_ranges_one_rank(
241 // For c_cean_var the base addr is the address of the data
242 // For c_cean_var_ptr the base addr is dereferenced to get to the data
243 spaces
, deref
? *((uint64_t*)(adp
->base
)) : adp
->base
,
244 adp
->rank
, &adp
->dim
[0], fp
, esize
);
245 (*fp
)(spaces
, last_left
, last_right
, esize
);
248 // returns offset and length of the data to be transferred
249 void __arr_data_offset_and_length(
255 int64_t rank
= adp
->rank
- 1;
256 int64_t size
= adp
->dim
[rank
].size
;
257 int64_t r_off
= 0; // offset from right boundary
259 // find the rightmost dimension which takes just part of its
260 // range. We define it if the size of left rank is not equal
261 // the range's length between upper and lower boungaries
263 size
*= (adp
->dim
[rank
].upper
- adp
->dim
[rank
].lower
+ 1);
264 if (size
!= adp
->dim
[rank
- 1].size
) {
270 offset
= (adp
->dim
[rank
].lower
- adp
->dim
[rank
].lindex
) *
273 // find gaps both from the left - offset and from the right - r_off
274 for (rank
--; rank
>= 0; rank
--) {
275 offset
+= (adp
->dim
[rank
].lower
- adp
->dim
[rank
].lindex
) *
277 r_off
+= adp
->dim
[rank
].size
-
278 (adp
->dim
[rank
+ 1].upper
- adp
->dim
[rank
+ 1].lindex
+ 1) *
279 adp
->dim
[rank
+ 1].size
;
281 length
= (adp
->dim
[0].upper
- adp
->dim
[0].lindex
+ 1) *
282 adp
->dim
[0].size
- offset
- r_off
;
285 #if OFFLOAD_DEBUG > 0
297 OFFLOAD_TRACE(3, "%s print_range(low=%p, high=%p, esize=%d)\n",
298 spaces
, (void*)low
, (void*)high
, esize
);
300 if (console_enabled
< 4) {
303 OFFLOAD_TRACE(4, "%s values:\n", spaces
);
311 sprintf(number
, "%d ", *((char *)low
));
315 sprintf(number
, "%d ", *((short *)low
));
319 sprintf(number
, "%d ", *((int *)low
));
323 sprintf(number
, "0x%016x ", *((uint64_t *)low
));
327 strcat(buffer
, number
);
330 OFFLOAD_TRACE(4, "%s %s\n", spaces
, buffer
);
336 OFFLOAD_TRACE(4, "%s %s\n", spaces
, buffer
);
340 void __arr_desc_dump(
347 OFFLOAD_TRACE(2, "%s%s CEAN expression %p\n", spaces
, name
, adp
);
350 OFFLOAD_TRACE(2, "%s base=%llx, rank=%lld\n",
351 spaces
, adp
->base
, adp
->rank
);
353 for (int i
= 0; i
< adp
->rank
; i
++) {
355 "%s dimension %d: size=%lld, lindex=%lld, "
356 "lower=%lld, upper=%lld, stride=%lld\n",
357 spaces
, i
, adp
->dim
[i
].size
, adp
->dim
[i
].lindex
,
358 adp
->dim
[i
].lower
, adp
->dim
[i
].upper
,
361 // For c_cean_var the base addr is the address of the data
362 // For c_cean_var_ptr the base addr is dereferenced to get to the data
363 generate_mem_ranges(spaces
, adp
, deref
, &print_range
);
366 #endif // OFFLOAD_DEBUG