Copy and Shared Memory Semantics

By default, hardware function calls involve copy-in, copy-out semantics for function arguments. It is possible to impose a shared memory model for hardware function arguments, but you must keep in mind that while throughput on burst transfers is quite good, the latency to external DDR from the programmable logic is significantly higher than it is for the CPU. The following pragma, inserted immediately preceding the function declaration, is used to declare that a variable transfer employs shared memory semantics.
#pragma SDS data zero_copy(A[0:<array_size>]) // array_size = number of elements

Within a synthesizeable hardware function, it is usually inefficient to read/write single words from the shared memory (specified using the zero-copy pragma). A more efficient approach is to employ memcpy to read/write data from memory in bursts and store it in a local memory.

For copy and zero copy memory semantics, another efficient alternative is to stream data between programmable logic and external DDR to maximize memory efficiency, storing data in local memory within a hardware function whenever you need to make non-sequential and repeated accesses to variables. For example, video applications typically have data coming in as pixel streams and implement line buffers in FPGA memory to support multiple accesses to the pixel stream data.

To declare to sdscc that a hardware function can admit streaming access for an array data transfer (that is, each element is accessed precisely once in index order), insert the following pragma immediately preceding the function prototype.

#pragma SDS data access_pattern(A:SEQUENTIAL) // access pattern = SEQUENTIAL | RANDOM

For arrays passed as pointer typed arguments to hardware functions, sometimes the compilers can infer transfer size, but if they cannot, they issue the following message.

ERROR: [SDSoC 0:0] The bound callers of accelerator foo have different/indeterminate data size for port p.

Use the following to specify the size of the data to be transferred.

#pragma SDS data copy(p[0:<array_size>]) // for example, int *p
You can vary the data transfer size on a per function call basis to avoid transferring data that is not required by a hardware function by setting <array_size> in the pragma definition to be an expression defined in the scope of the function call (that is, all variables in the size expression must be scalar arguments to the function), for example:
#pragma SDS data copy(A[0:L+2*T/3]) // scalar arguments L, T to same function