ZHCUAU3J January 2018 – March 2024
与 SE 类似,一旦配置了流地址生成器 (SA),就可以打开和使用相应的 SA。提供了以下 API 来方便此操作,其将参数模板作为输入:
__SA0_OPEN(__SA_TEMPLATE_v1
param);
__SA1_OPEN(__SA_TEMPLATE_v1 param);
__SA2_OPEN(__SA_TEMPLATE_v1 param);
__SA3_OPEN(__SA_TEMPLATE_v1 param);
使用以下 API 访问流地址生成器。请注意,对于流地址生成器,基地址作为读取操作的输入给出,返回值是指向位置的指针,该位置随后被内存加载或被内存存储操作使用。这是因为,与 SE 不同,SA 只是提供一个添加到给定基地址的偏移量。给定类型用于转换通过 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)
有关从流地址生成器读取时 C++ 中支持的其他模板,请参见节 5.16 中的“strm_agen”。
使用相应的关闭 API 来关闭流地址生成器:
__SA0_CLOSE();
__SA1_CLOSE();
__SA2_CLOSE();
__SA3_CLOSE();
当上面显示的访问器 API 被自身使用时,编译器将为它们匹配基本的加载或存储操作,具体取决于它们是在赋值运算符的左侧 (LHS) 还是右侧 (RHS)。
以下是 SA 返回指针的一个示例,在 LHS 和 RHS 上对该示例进行解引用,以便将数据从一个位置复制到另一个位置。因为 SA 返回一个指针,所以在 RHS 上对其解引用会生成加载操作,而在 LHS 上对其解引用会生成存储操作。
// 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();
但是,SA 访问器 API 也可以作为加载或存储内在函数的输入,如下示例所示。在此示例中,由于 SA 只是返回一个未被解引用的指针,因此编译器不会试图匹配相应的基本向量加载或存储操作,而是使用内在函数指示的加载或存储操作。
// 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();
如果流地址生成器与标记为 restrict
的基址指针一起使用,则由 SA 计算的基于该指针的推导结果(基址 + 偏移量)也被认为是 restrict
。这意味着 SA 生成的指针以及使用这些指针的所有加载和存储操作都不会被认为是其他存储器指针的别名。
因此,使用基于 restrict
基址指针的 SA 则约定:程序承诺始终不会修改流地址生成器在其生命周期内可以访问的任何存储器区域中的数据。