SPRUIG8J January 2018 – March 2024
Similar to the SE, once the Streaming Address Generator (SA) has been configured, a corresponding SA can be opened and used. The following API is provided to facilitate this, which takes the parameter template as input:
__SA0_OPEN(__SA_TEMPLATE_v1
param);
__SA1_OPEN(__SA_TEMPLATE_v1
param);
__SA2_OPEN(__SA_TEMPLATE_v1
param);
__SA3_OPEN(__SA_TEMPLATE_v1
param);
The Streaming Address Generators are accessed using the following API. Note that for Streaming Address Generators, the base address is given as an input to the read operation, and the return value is a pointer to the location that is then used by a memory load or memory store operation. This is because, unlike the SE, an SA simply provides an offset added to the given base address. The given type is used to cast the type of the data loaded or stored through the SA.
__SA0(type, baseptr), __SA0ADV(type, baseptr)
__SA1(type, baseptr), __SA1ADV(type, baseptr)
__SA2(type, baseptr), __SA2ADV(type, baseptr)
__SA3(type, baseptr), __SA3ADV(type, baseptr)
__SA0(int2, baseptr)
__SA0(__int2, baseptr)
__SA0(const __int2, baseptr)
For additional template support in C++ when reading from a Streaming Address Generator, see "strm_agen" in Section 5.16.
Streaming Address Generators are closed using the corresponding close API:
__SA0_CLOSE();
__SA1_CLOSE();
__SA2_CLOSE();
__SA3_CLOSE();
When the accessor APIs shown above are used by themselves, the compiler will match a basic load or store operation for them, depending on whether they are on the left-hand-side (LHS) or right-hand-side (RHS) of an assignment operator.
The following is an example of an SA-returned pointer dereferenced by itself on both the LHS and RHS to copy data from one location to another. Because the SA returns a pointer, dereferencing it on the RHS generates a load, and dereferencing it on the LHS generates a store.
// OPEN THE STREAMS, SA0 AND SA1
__SA0_OPEN(params);
__SA1_OPEN(params);
// COPY DATA FROM *(src_addr+SA1) TO *(dst_addr+SA0)
for (I0 = 0; I0 < 8; I0++)
{
// COMPILER MATCHES VECTOR LOAD AND STORE FOR FOUR WORD DATA
*__SA0ADV(uint8, dst_addr) = *__SA1ADV(uint8, src_addr);
}
// CLOSE THE STREAMS
__SA0_CLOSE();
__SA1_CLOSE();
However, the SA accessor APIs can also be given as input to a load or store intrinsic, as in the following example. In this case, since the SA simply returns a pointer that is not dereferenced, the compiler will not attempt to match a corresponding basic vector load or store and will instead use the load or store indicated by the intrinsic.
// OPEN THE STREAMS, SA0 AND SA1
__SA0_OPEN(params);
__SA1_OPEN(params);
// COPY DATA (WITH UNPACK + PACK) FROM *(src_addr+SA1) TO *(dst_addr+SA0)
for (I0 = 0; I0 < 8; I0++)
{
ulong8 data = __vload_unpack_long(__SA1ADV(uint8, src_addr));
__vstore_packl(__SA0ADV(uint8, dst_addr), data);
}
// CLOSE THE STREAMS
__SA0_CLOSE();
__SA1_CLOSE();
If the Streaming Address Generator is used with a
base pointer that is flagged as restrict
, then derivations
based on that pointer (base + offset), as calculated by the SA, are also assumed
to be restrict
. This means that SA-generated pointers, and all
loads and stores that use them, are assumed to not alias other memory
pointers.
Therefore, using the SA based on
restrict
base pointers implies a contract in which the
program promises never to modify the data in any area of memory that can be
reached by that Streaming Address Generator during its lifetime.