网资酷

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 156|回复: 0

TI C7x DSP 编程 (五) 流地址生成器

[复制链接]

2

主题

2

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2022-9-21 21:01:17 | 显示全部楼层 |阅读模式

  • TI C7x DSP 编程 (一) 简介
  • TI C7x DSP 编程 (二) 向量数据类型
  • TI C7x DSP 编程 (三) 流引擎基础
  • TI C7x DSP 编程 (四) 流引擎进阶
  • TI C7x DSP 编程 (五) 流地址生成器
  • TI C7x DSP 编程 (六) DMA
  • TI C7x DSP 编程 (七) 查找表与直方图
  • TI C7x DSP 编程 后记
流地址生成器 (Streaming Address generator,SA) 与流引擎非常相似——接口相似、配置结构体的成员相似、工作的方式相似。流引擎会根据配置的方式不断获取数据,流地址生成器会根据配置的方式不断计算数据的首地址。流引擎只能获取数据,而通过流地址生成器返回的地址可以读取数据也可以写入数据。当前的 C7x DSP 硬件支持 4 个流地址生成器实例,不排除以后支持更多。
流地址生成器接口

接口一览

接口名接口说明
__gen_SA_TEMPLATE_v1()生成带默认值的流地址生成器配置结构体,当前仅有 1 个版本的配置结构体。
__SA0_OPEN(tmpl)
__SA1_OPEN(tmpl)
__SA2_OPEN(tmpl)
__SA3_OPEN(tmpl)
启动流地址生成器,tmpl 为流地址生成器配置结构体。 0 ~ 3 分别对应四个流地址生成器实例,下同。
__SA0_CLOSE()
__SA1_CLOSE()
__SA2_CLOSE()
__SA3_CLOSE()
关闭流地址生成器
__SA0(_type, baseptr)
__SA1(_type, baseptr)
__SA2(_type, baseptr)
__SA3(_type, baseptr)
以 baseptr 为基准,计算出对应的地址并解析为指向 _type 类型 (各种向量数据类型) 的指针。调用接口后不会触发流地址生成器下一步的计算。
__SA0ADV(_type, baseptr)
__SA1ADV(_type, baseptr)
__SA2ADV(_type, baseptr)
__SA3ADV(_type, baseptr)
以 baseptr 为基准,计算出对应的地址并解析为指向 _type 类型 (各种向量数据类型) 的指针。调用接口后会触发流地址生成器下一步的计算。
__SA0_VPRED(_type)
__SA1_VPRED(_type)
__SA2_VPRED(_type)
__SA3_VPRED(_type)
根据 _type 类型 (各种向量数据类型) 计算当前的越界标记并返回,返回类型为 vpred,vpred 数据类型的说明见下。
__SA0_BOOL(_type)
__SA1_BOOL(_type)
__SA2_BOOL(_type)
__SA3_BOOL(_type)
与 __SAn_VPRED 接口差不多,只不过返回的为每个元素均为 bool 的向量数据类型,向量的长度与 _type 一致。由于相关指令大多接受 vpred 类型为参数,故常使用 __SAn_VPRED 接口而不是 __SAn_BOOL 接口。
__SA0_BREAK(level)
__SA1_BREAK(level)
__SA2_BREAK(level)
__SA3_BREAK(level)
我没有实践过,官方教程也没有提及。
__SA0_SET_CR(data)
__SA1_SET_CR(data)
__SA2_SET_CR(data)
__SA3_SET_CR(data)
我没有实践过,官方教程也没有提及。
__SA0_GET_CR()
__SA1_GET_CR()
__SA2_GET_CR()
__SA3_GET_CR()
我没有实践过,官方教程也没有提及。
__SA0_GET_CNTR0()
__SA1_GET_CNTR0()
__SA2_GET_CNTR0()
__SA3_GET_CNTR0()
我没有实践过,官方教程也没有提及。
__SA0_GET_CNTR1()
__SA1_GET_CNTR1()
__SA2_GET_CNTR1()
__SA3_GET_CNTR1()
我没有实践过,官方教程也没有提及。
__SA0_GET_CNTR1()
__SA1_GET_CNTR1()
__SA2_GET_CNTR1()
__SA3_GET_CNTR1()
我没有实践过,官方教程也没有提及。
__SA0_GET_CNTR1()
__SA1_GET_CNTR1()
__SA2_GET_CNTR1()
__SA3_GET_CNTR1()
我没有实践过,官方教程也没有提及。
流地址生成器接口的一般调用流程

流地址生成器常会配合流引擎使用,实践的基本流程如下:

  • 调用 __gen_SE_TEMPLATE_v1() __gen_SE_TEMPLATE_v2() __gen_SE_TEMPLATE_v3() 生成带默认值的流引擎配置结构体,并根据需求修改结构体的成员值。
  • 调用 __gen_SA_TEMPLATE_v1() 生成带默认值的流地址生成器配置结构体,并根据需求修改结构体的成员值。
  • 调用 __SEn_OPEN() 启动流引擎。
  • 调用 __SAn_OPEN() 启动流地址生成器。
  • 调用 __SEn() __SEnADV() 读取数据。
  • 根据算法的需要调用各种指令进行数据处理。
  • 调用 __SAn_VPRED()  获取当前待写入内存的越界信息。
  • 调用 __SAn()__SAnADV() 获得当前待写入内存对应变量的指针。
  • 调用 __vstore_pred() 等相关指令存储计算结果。也可以使用“*”运算符通过指针变量直接读写数据,不过需要注意越界问题。
  • 算法流程结束后,调用 __SEn_CLOSE() 关闭流引擎,调用 __SAn_CLOSE() 关闭流地址生成器。
vpred 数据类型

vpred 是 C7000 CGT 编译器引入的数据类型,可以理解为包含 64 个标志位的变量 (当前向量数据类型最大元素个数为 64),标志位的值只能为 0 或 1。许多 SIMD 指令包含 vpred 类型的参数。
对于元素大小为 8 比特的向量数据类型 (char64uchar8 等),每个元素对应 1 个 vpred 标志位;对于元素大小为 16 比特的向量数据类型 (short32ushort16 等),每个元素对应连续的 2 个 vpred 标志位,这 2 个标志位同时为 0 或 1。以此类推。
流地址生成器配置结构体

成员一览

当前仅有 1 个版本的配置结构体 (__SA_TEMPLATE_v1)。
__SA_TEMPLATE_v1 结构体成员数据类型可取值成员功能说明
ICNT0
ICNT1
ICNT2
ICNT3
ICNT4
ICNT5
uint32_t非零正整数多维数据每个维度的长度,最多支持 6 维数据的读取。
DECDIM1_WIDTH
DECDIM2_WIDTH
DECDIM3_WIDTH
uint32_t非零正整数用于读写数据的越界检测,配合成员 DECDIM1、DECDIM1SD、DECDIM2、DECDIM2SD、DECDIM3、DECDIM3SD
DIM1
DIM2
DIM3
DIM4
DIM5
uint32_t非负整数 (可为 0)仅第 n ( 1≤n≤5 ) 维度增加 1 时,数据索引的变化值。
VECLENenum__SA_VECLEN_1ELEM
__SA_VECLEN_2ELEMS
__SA_VECLEN_4ELEMS
__SA_VECLEN_8ELEMS
__SA_VECLEN_16ELEMS
__SA_VECLEN_32ELEMS
__SA_VECLEN_64ELEMS
读或写数据的元素个数。
INV_DD1
INV_DD2
INV_DD3
enum__SA_INV_DD_OFF
__SA_INV_DD_ON
不太清楚其功能,官方教程没有提及。
DIMFMTenum__SA_DIMFMT_1D
__SA_DIMFMT_2D
__SA_DIMFMT_3D
__SA_DIMFMT_4D
__SA_DIMFMT_5D
__SA_DIMFMT_6D
数据的维度,最多 6 维。
DECDIM1
DECDIM2
DECDIM3
enum__SA_DECDIM_DIM0
__SA_DECDIM_DIM1
__SA_DECDIM_DIM2
__SA_DECDIM_DIM3
__SA_DECDIM_DIM4
__SA_DECDIM_DIM5
用于读写数据的越界检测,配合成员 DECDIM1_WIDTH、DECDIM2_WIDTH、DECDIM3_WIDTH
DECDIM1SD
DECDIM2SD
DECDIM3SD
enum__SA_DECDIMSD_DIM0
__SA_DECDIMSD_DIM1
__SA_DECDIMSD_DIM2
__SA_DECDIMSD_DIM3
用于读写数据的越界检测,配合成员 DECDIM1、DECDIM2、DECDIM3
流地址的计算

以最高的 6 维为例 (即 DIMFMT __SA_DIMFMT_6D),流地址生成器记录内部会维护 6 个变量 in (n = 0 ~ 5),分别对应 ICNTn,满足 0 ≤ inICNTn - 1。调用 __SAn()__SAnADV() 返回的地址,对应数组中的索引值
\mathrm{Index}= i_5 * \mathrm{DIM_5} + i_4 * \mathrm{DIM_4} + i_3 * \mathrm{DIM_3} + i_2 * \mathrm{DIM_2} + i_1 * \mathrm{DIM_1} +  i_0
与流引擎不同,流地址生成器配置参数没有与数据类型相关的成员,而是根据 __SAn()__SAnADV() 的输入参数确定数据类型。例如 __SAn(uchar64, baseptr),则数据的类型推断为 uint8_t (8 比特无符号整数),计算的地址等于 &((uint8_t *)baseptr)[Index],最后函数返回类型为 uchar64 * 指针。又如 __SAn(int2, baseptr),则数据的类型推断为 int32_t (32 比特有符号整数),计算的地址等于 &((int32_t *)baseptr)[Index],最后函数返回类型为 int2* 指针类型。
调用 __SAnADV() 函数之后,i0 会根据配置结构体成员 VECLEN 的值增加,例如 VECLEN __SA_VECLEN_16ELEMS i0 增加 16。当 i0 ICNT0 时,i0 复 0 且 i1 的值加 1。类似的,当 in ICNTn 时,in 复 0 且 in+1 的值 加 1 (n = 0 ~ 4)。最后 i5 ≥ ICNT5 时计算结束。计算结束后调用 __SAn()__SAnADV() 将会返回基础地址,即参数 baseptr
越界检测

流地址生成器越界检测的机制与流引擎的一致,这里不再赘述。
流地址生成器越界检测的结果不会体现在 __SAn()__SAnADV() 函数的返回值上,而是体现在 __SAn_VPRED() 函数的返回值上。例如通过越界检测得知当前仅能读写的数据个数为 3,则 __SAn_VPRED(uchar64) 返回值的低 3 个标志位为 1,剩余标志位为 0;__SAn_VPRED(int16) 返回值的低 12 个标志位为 1,剩余标志位为 0 (对于元素大小为 32 比特的向量数据类型,每个元素对应 4 个标志位,见上面章节说明)。注意,__SAn_VPRED() 的返回值仅依赖类型参数的元素大小,例如 __SAn_VPRED(int16)__SAn_VPRED(uint2) 的返回值相同。
参考资料


  • TI C7X DSP TRAINING (页面搜索 C7x Training)
  • C7000 CGT (页面下还包括编译器的使用说明书等资料)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|网资酷

GMT+8, 2025-3-15 15:46 , Processed in 0.083318 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表