Data Transfer Size
#pragma SDS data copy|zero_copy(ArrayName[offset:length])
This pragma must be specified immediately preceding a function declaration, or immediately preceding other#pragma SDS
bound to the function declaration. This pragma applies to all the callers of the bound function.
- The
copy
implies that data is explicitly copied from the processor memory to the hardware function. A suitable data mover as described inImproving System Performanceperforms the data transfer. Thezero_copy
means that the hardware function accesses the data directly from shared memory through an AXI4 bus interface. If nocopy
orzero_copy
pragma is specified to an array argument, the SDSoC compiler assumes thecopy
semantics. - The
[offset:length]
part is optional. When this part is not specified, this pragma is only used to select between copying the memory to/from the accelerator versus directly accessing the memory by the accelerator. For the array size, the SDSoC compiler first analyzes the callers to the accelerator function to determine the transfer size based on the memory allocation APIs for the array (for example, malloc or sds_alloc etc.). If the analysis fails, it checks the argument type to see if the argument type has a compile-time array size and use that size as the data transfer size. If no data transfer size can be determined, the compiler generates an error message so that the user can specify this pragma. If the data size is different between the caller and callee, or different between multiple callers, the compiler also generates an error message so that the user can correct the source code or use this pragma to override the compiler analysis. - For a multi-dimensional array, each dimension should be specified. For example, for a 2-dimensional array, use
ArrayName[offset_dim1:length_dim1][offset_dim2:length2_dim2]
- Multiple arrays can be specified in the same pragma, separated by a comma(,). For example, use
copy(ArrayName1[offset1:length1], ArrayName2[offset2:length2])
ArrayName
must be one of the formal parameters of the function definition, that is, not from the prototype (where parameter names are optional) but from the function definition.offset
is the number of elements from the first element in the corresponding dimension. It must be a compile-time constant. This is currently ignored.length
is the number of elements transferred for that dimension. It can be an arbitrary expression as long as the expression can be resolved at runtime inside the function.
Example 1
#pragma SDS data copy(A[0:size*size], B[0:size*size]) void foo(int *A, int *B, int size)
void _p0_foo_0(int *A, int *B, int size) { ... cf_send_i(&(_p0_swinst_foo_0.A), A, (size*size) * 4, &_p0_request_0); cf_receive_i(&(_p0_swinst_foo_0.B), B, (size*size) * 4, &_p0_request_1); ... }
As shown above, the pragma value "size*size
" is used to tell the SDSoC runtime the number of elements of array "A" and "B". Thecf_send_i
andcf_receive_i
require the number of bytes, so the compiler will multiply the "size*size
" with the number of bytes for each element (4 in this case). As shown in the example above,length
need not be a compile-time constant; it can be a C arithmetic expression involving other scalar arguments of the same function.
Example 2
zero_copy
" pragma instead of the "
copy
" pragma above:
#pragma SDS data zero_copy(A[0:size*size], B[0:size*size]) void foo(int *A, int *B, int size)
cf_send_ref_i(&(_p0_swinst_foo_0.A), A, (size*size) * 4, &_p0_request_0); cf_receive_ref_i(&(_p0_swinst_foo_0.B), B, (size*size) * 4, &_p0_request_1);
Thecf_send_ref_i
andcf_receive_ref_i
mean only transfer the reference or pointer of the array to the accelerator, and the accelerator will access the memory directly.
Example 3
"foo.h" #pragma SDS data copy(in_A[0:1024]) void foo(int *in_A, int *out_B) "foo.cpp" #include "foo.h" void foo(int *A, int *B) { ... }
WARNING: [SDSoC 0-0] Cannot find argument in_A in accelerator function foo(int *A, int *B)