03章 内核状态 - “Vega“ 7nm Instruction Set ArchitectureReference Guide

本章描述着色器程序可见的内核状态。

3.1. 状态概览

下表显示了着色器程序可读或可写的所有硬件状态【注,硬件状态寄存器】。

表2. 可读可写硬件状态

缩写 名称 大小 描述
PC 程序计数器 48位 指向下一条要执行的着色器指令的内存地址。
V0-V255 向量通用寄存器 32位 向量通用寄存器。
S0-S103 标量通用寄存器 32位 标量通用寄存器。
LDS 本地数据共享 64kB 本地数据共享是一块具有内置算术能力的暂存RAM,允许工作组内的线程之间共享数据。
EXEC 执行掩码 64位 一个按线程分布的位掩码(每位对应一个线程),应用于向量指令,控制哪些线程执行指令、哪些线程忽略指令。
EXECZ EXEC 为零 1位 一个单比特标志,指示 EXEC 掩码是否全为零。
VCC 向量条件码 64位 一个按线程分布的位掩码;保存向量比较操作的结果。
VCCZ VCC 为零 1位 一个单比特标志,指示 VCC 掩码是否全为零。
SCC 标量条件码 1位 标量ALU比较指令的结果。
FLAT_SCRATCH Flat 暂存地址 64位 暂存内存的基地址
XNACK_MASK 地址转换失败 64位 地址转换失败的线程的位掩码。
STATUS 状态 32位 只读的着色器状态位。
MODE 模式 32位 可写的着色器模式位。
M0 内存寄存器 32位 一个具有多种用途的临时寄存器,包括GPR索引和边界检查
TRAPSTS 陷阱状态 32位 保存有关异常和待处理陷阱的信息。
TBA 陷阱基地址 64位 保存指向当前陷阱处理程序的指针。
TMA 陷阱内存地址 64位 用于着色器操作的临时寄存器。例如,可以保存陷阱处理程序使用的内存指针。
TTMP0-TTMP15 陷阱临时SGPR 32位 仅对陷阱处理程序可用的16个SGPR,用于临时存储。
VMCNT 向量内存指令计数 6位 统计已发出但尚未完成的向量内存指令的数量。
EXPCNT 导出计数 3位 统计已发出但尚未完成的导出和GDS指令数量。也统计尚未将其写入数据发送到纹理缓存器的向量内存写指令。
LGKMCNT LDS, GDS, 常量和消息计数 4位 统计已发出但尚未完成的LDS、GDS、常量获取(标量内存读)和消息指令的数量。

3.2. 程序计数器

程序计数器是一个字节地址,指向下一条要执行的指令。当创建 wavefront 时,PC被初始化为程序中的第一条指令。

PC 与三条指令交互:S_GET_PCS_SET_PCS_SWAP_PC。这些指令在 PC 和偶地址对齐的 SGPR 对之间传输数据。

分支跳转到 (分支指令的下一条指令的PC + 偏移量)。着色器程序不能直接读取或写入 PC。分支、GET_PCSWAP_PC 指令的地址是相对于下一条指令的 PC,而不是当前指令的 PC。S_TRAP 指令保存的是 S_TRAP 指令自身的 PC。

3.3. 执行掩码

执行掩码(64位)决定向量中的哪些线程会被执行:1 = 执行,0 = 不执行。

可以通过标量指令读取和写入 EXEC 寄存器;它也可以作为向量 ALU 比较的结果被写入。此掩码影响向量 ALU、向量内存、LDS 和导出指令。它不影响标量执行或分支。

辅助位 EXECZ 可用作分支条件,以便在 EXEC 为零时跳过代码。

注意:当 EXEC = 0 时,此 GPU 不会进行优化。着色器硬件仍会执行每条指令,浪费指令发射带宽。当 EXEC 掩码可能为零时,应使用 CBRANCHVSKIP 指令来快速跳过代码。

3.4. 状态寄存器

状态寄存器字段可以被着色器读取,但不能写入。这些位在 wavefront 创建时初始化。下表列出并简要描述了状态寄存器字段。

表 3. 状态寄存器字段

字段 位位置 描述
SCC 1 标量条件码。用作进位输出位。对于比较指令,此位表示失败或成功。对于逻辑操作,如果结果非零,则此位为 1。
SPI_PRIO 2:1 波前创建时由着色器处理器插值器设置的 wavefront 优先级 。详情见 S_SETPRIO 指令(第 12-49 页)。0 为最低,3 为最高优先级。
WAVE_PRIO 4:3 由着色器程序设置的wavefront 优先级 。详情见 S_SETPRIO 指令(第 12-49 页)。
PRIV 5 特权模式 。仅在陷阱处理程序中可能为活动状态。提供对 TTMPTMATBA 寄存器的写入权限。
TRAP_EN 6 指示存在陷阱处理程序。当设置为零时,不处理陷阱。
TTRACE_EN 7 指示是否为该波前启用了线程追踪。如果为零,则忽略任何着色器生成的(指令)线程追踪数据。
EXPORT_RDY 8 此状态位指示是否已分配导出缓冲区空间。着色器会暂停任何导出指令,直到此位变为 1。当导出缓冲区空间分配后,此位被置为 1。像素或顶点着色器在导出之前,硬件会检查此位的状态。如果此位为 1,则可以发出导出指令。如果此位为零,则 wavefront 进入休眠状态,直到导出缓冲区中有可用空间。然后,此位被置为 1,wavefront 恢复执行。
EXECZ 9 执行掩码为零
VCCZ 10 向量条件码为零
IN_TG 11 波前是属于一个包含多个 wavefront 的工作组的成员
IN_BARRIER 12 波前正在屏障处等待
HALT 13 波前已停止或计划停止HALT 可以由主机通过波前控制消息设置,也可以由着色器自身设置。在陷阱处理程序中(PRIV = 1)忽略此位;如果收到主机发起的陷阱(请求进入陷阱处理程序)也忽略此位。
TRAP 14 波前被标记为尽快进入陷阱处理程序
TTRACE_CU_EN 15 为此计算单元启用/禁用线程追踪。此位允许多个 CU 输出 USERDATA(着色器发起的对线程追踪缓冲区的写入)。请注意,每个着色器阵列每次仅从一个 CU 追踪波前数据。如果此位为零,仍可输出波前用户数据(基于指令)。
VALID 16 波前处于活动状态(已创建且尚未结束)。
ECC_ERR 17 发生了 ECC 错误
SKIP_EXPORT 18 仅用于顶点着色器 。1 = 此着色器未分配导出缓冲区空间;所有导出指令被忽略(视为 NOP)。以前称为 VS_NO_ALLOC。用于多流输出(对同一 VS 进行多次遍历),以及在 VS 阶段运行的、未产生图元的波前的域着色器。
PERF_EN 19 为此 wavefront 启用了性能计数器
COND_DBG_USER 20 用户模式的条件调试指示器
COND_DBG_SYS 21 系统模式的条件调试指示器
ALLOW_REPLAY 22 指示 ATC 重放已启用
MUST_EXPORT 27 此波前在终止前必须执行一次带有 Done=1 的导出操作

3.5. 模式寄存器

模式寄存器字段可以通过标量指令被着色器读取和写入。下表列出并简要描述了模式寄存器字段。

表 4. 模式寄存器字段

字段 位位置 描述
FP_ROUND 3:0 [1:0]:单精度舍入模式。 [3:2]:双精度/半精度舍入模式。舍入模式:0=向最近的偶数舍入,1=向正无穷舍入,2=向负无穷舍入,3=向零舍入。
FP_DENORM 7:4 [1:0]:单精度非规格化数模式。 [3:2]:双精度/半精度非规格化数模式 。非规格化数模式: 0 = 将输入和输出的非规格化数刷新为零。 1 = 允许输入非规格化数,将输出的非规格化数刷新为零。 2 = 将输入的非规格化数刷新为零,允许输出非规格化数。 3 = 允许输入和输出非规格化数。
DX10_CLAMP 8 由向量 ALU 使用,强制采用 DX10 风格的 NaN 处理:置位时,将 NaN 钳制为零;否则,直接传递 NaN。
IEEE 9 浮点操作码支持按照 IEEE 754-2008 标准收集异常标志,并使信令 NaN 输入静默和传播 。由于信令 NaN 的传播和静默,min_dx10max_dx10 操作将符合 IEEE 754-2008 标准。
LOD_CLAMPED 10 粘滞位,指示一次或多次纹理访问的细节级别被钳制
DEBUG 11 强制波前在执行每条指令后(但不在 ENDPGM 后)跳转到异常处理程序 。仅在 TRAP_EN = 1 时有效。
EXCP_EN 18:12 异常启用掩码 。启用意味着如果发生异常且 TRAP_EN == 1,则会触发陷阱。 [12] : 无效操作 [13] : 输入非规格化数 [14] : 浮点除零 [15] : 上溢 [16] : 下溢 [17] : 不精确结果 [18] : 整数除零 [19] : 地址监视 [20] : 内存违规
FP16_OVFL 23 如果置位,溢出的 FP16 结果将被钳制到 +/- MAX_FP16,无论舍入模式如何,同时仍保留真正的 INF 值。
POPS_PACKER0 24 1 = 此波前与打包器 0 关联 。用户着色器必须将其设置为来自 POPS 初始化 SGPR 的 !PackerID,如果不使用 POPS 则设置为零。
POPS_PACKER1 25 1 = 此波前与打包器 1 关联 。用户着色器必须将其设置为来自 POPS 初始化 SGPR 的 PackerID,如果不使用 POPS 则设置为零。
DISABLE_PERF 26 1 = 禁用此波前的性能计数
GPR_IDX_EN 27 GPR 索引启用
VSKIP 28 0 = 正常操作。1 = 跳过(不执行)任何向量指令:valu、vmem、export、lds、gds。"跳过"指令以高速进行(每时钟周期最多可跳过 10 个波前的单条指令)。这比发射并丢弃指令要快得多。
CSP 31:29 条件分支堆栈指针

3.6. 通用寄存器和本地数据共享

本节描述 GPR 和 LDS 空间如何分配给一个波前,以及如何处理越界和未对齐的访问。

3.6.1. 越界行为

本节定义了当源或目标 GPR 或内存地址超出波前的合法范围时的行为。

越界可能由 GPR 索引或错误的编程引起。不允许从一个寄存器类型索引到另一个寄存器类型(例如:从 SGPR 索引到陷阱寄存器或内联常量)。也不允许在内联常量内部进行索引。

以下描述了各种存储类型的越界行为。

  • SGPR

    • 源或目标越界 = (sgpr < 0 || (sgpr >= sgpr_size))

    • 源越界:返回 SGPR0 的值(不是数值0)。

    • 目标越界:指令不写入任何 SGPR 结果。

  • VGPR

    • 与 SGPR 类似。不允许从 SGPR 索引到 VGPR,反之亦然。

    • 越界 = (vgpr < 0 || (vgpr >= vgpr_size))

    • 如果源 VGPR 越界,则使用 VGPR0

    • 如果目标 VGPR 越界,则忽略该指令(视为空操作)。

  • LDS

    • 如果 LDS 地址越界:(addr < 0 或 > (MIN(lds_size, m0))

      • 越界的写入被丢弃;如果 SIZE 不是写入数据大小的倍数,则行为未定义。

      • 读取返回值 0。

    • 如果任何源 VGPR 越界,则使用 VGPR0 的值。

    • 如果目标 VGPR 越界,则使指令无效(以 exec=0 发射)。

  • 内存、LDS 和 GDS:读取和带返回值的原子操作

    • 如果任何源 VGPR 或 SGPR 越界,数据值是未定义的。

    • 如果任何目标 VGPR 越界,操作通过以 EXEC 掩码被清零(0)的方式发射指令而被取消。

      • 此越界检查必须检查所有可能返回的 VGPR(例如:BUFFER_LOAD_DWORDx4 指令中的 VDSTVDST+3)。

      • 此检查还必须包含额外的部分驻留纹理 VGPR,如果此 VGPR 越界,则取消获取,无论纹理系统是否实际返回此值。

      • 目标 VGPR 越界的原子操作被取消:指令会发射,但 EXEC 掩码为 0。

对于有多个目标(例如:V_ADDC)的指令:如果任何目标越界,则不写入任何结果。

3.6.2. SGPR 分配与存储

一个波前可以分配 16 到 102 个 SGPR,分配单位是 16 个 GPR(双字)。这些寄存器在逻辑上被视为 SGPR0SGPR101VCC 物理上存储在波前 SGPR 中编号最高的两个 SGPR(SGPR106SGPR107)里;源/目标 VCC 是这两个 SGPR 的别名。当存在陷阱处理程序时,VCC 之后会额外保留 16 个 SGPR,用于保存陷阱地址、保存的 PC 和陷阱处理程序临时数据。这些都是特权寄存器(除非设置了特权位,否则无法写入)。请注意,如果一个波前分配了 16 个 SGPR,通常有 2 个用作 VCC,剩下的 14 个可供着色器使用。着色器硬件不阻止使用全部 16 个 SGPR。

3.6.3. SGPR 对齐

在以下情况下需要使用偶地址对齐的 SGPR:

  • 当使用 64 位数据时。这是与 64 位寄存器(包括 PC)之间进行数据传输所要求的。

  • 当标量内存读取的地址基址来自 SGPR 对时(无论是 SGPR 内部还是之间)。

当标量内存读取返回四个或更多双字时,数据 GPR 需要四字节对齐。当 64 位数据存储在 SGPR 中时,最低有效位在 SGPR[n] 中,最高有效位在 SGPR[n+1] 中。

3.6.4. VGPR 分配与对齐

VGPR 以四个双字为一组进行分配。使用 VGPR 对的操作(例如:双精度浮点数)没有对齐限制。在物理上,VGPR 的分配可以环绕 VGPR 内存池。

3.6.5. LDS 分配与钳位

当不使用工作组时,LDS 按工作组或按.wavefront 分配。LDS 空间以连续的 128 双字块为单位,按 128 双字边界对齐的方式分配给工作组或波前。LDS 分配不会环绕 LDS 存储空间。所有对 LDS 的访问都被限制在该波前/工作组分配的空间内。

LDS 读取和写入的钳位由两个大小寄存器控制,它们包含 SPI 分配给此.wavefront 或工作组的 LDS 空间大小,以及 LDS 指令中可能指定的较小值(大小保存在 M0 中)。LDS 操作使用这两个值中较小的一个来确定如何钳位读/写地址。

3.7. M# 内存描述符

每个波前有一个 32 位的 M#(M0)寄存器,可用于:

  • 本地数据共享

    • 插值:保存 { 1'b0, new_prim_mask[15:1], parameter_offset[15:0] } // 单位:字节

    • LDS 直接读取偏移和数据类型:{ 13'b0, DataType[2:0], LDS_address[15:0] } // 地址单位:字节

    • 用于内存/Vfetch → LDS 的 LDS 寻址:{16'h0, lds_offset[15:0]} // 单位:字节

  • 全局数据共享

    • { base[15:0] , size[15:0] } // base 和 size 单位:字节
  • 向量和标量指令的间接 GPR 寻址。M0 是一个无符号索引。

  • 发送消息值EMIT/CUT 使用 M0 和 EXEC 作为发送消息的数据。

3.8. SCC:标量条件码

大多数标量 ALU 指令会设置标量条件码位,表示操作的结果。

  • 比较操作:1 = 真

  • 算术操作:1 = 进位

  • 位/逻辑操作:1 = 结果非零

  • 移动指令:不改变 SCC

SCC 可用作扩展精度整数算术的进位输入,也可用作条件移动和分支的选择器。

3.9. 向量比较:VCC 和 VCCZ

向量 ALU 比较指令设置向量条件码寄存器(1=通过,0=失败)。此外,向量比较指令可以选择将 EXEC 设置为 VCC 的值。

还有一个 VCC 汇总位 vccz,当 VCC 结果为零时被设置为 1。这对于提前退出的分支测试很有用。VCC 也会为选定的整数 ALU 操作(进位)而设置。

向量比较指令可以选择将结果写入 VCC(32位指令编码)或任何 SGPR(64位指令编码)。每次更新 VCC 时都会更新 VCCZ:向量比较和对 VCC 的标量写入都会更新。

EXEC 掩码决定哪些线程执行指令。VCC 指示哪些正在执行的线程通过了条件测试,或者哪些线程在整数加法或减法中产生了进位。

V_CMP_*VCC[n] = EXEC[n] & (线程[n] 的测试通过)

VCC 会被完整写入;没有部分掩码更新。

VCC 物理上驻留在 SGPR 寄存器文件中,因此当一条指令将 VCC 作为源时,会计入该指令所能引用的 SGPR 总数限制。VCC 物理上位于用户 SGPR 中编号最高的两个。

关于 VCC 的着色器冒险

用户/编译器必须防止在标量 ALU 写入保存 VCC 的 SGPR 之后,立即使用 VCCZ 进行条件分支。硬件无法检测这种情况,因此需要插入一个必需的等待状态(当 SALU 写入 VCC 时硬件可以检测到,只有当 SALU 指令恰好引用了保存 VCC 的 SGPR 时,硬件才无法检测)。

3.10. 陷阱与异常寄存器

每种类型的异常都可以通过设置或清除 TRAPSTS 寄存器的 EXCP_EN 字段中的位来独立启用或禁用。本节描述控制和报告内核异常的寄存器。

所有陷阱临时 SGPR 在写入时都是特权操作------只有在陷阱处理程序中(status.priv = 1)才能写入它们。在非特权状态下,对这些寄存器的写入被忽略。TMATBA 是只读的;可以通过 S_GETREG_B32 指令访问。

当发生陷阱时(无论是用户发起、异常还是主机发起),着色器硬件会生成一条 S_TRAP 指令。这将陷阱信息加载到一对 SGPR 中:
{TTMP1, TTMP0} = {3'h0, pc_rewind[3:0], HT[0], trapID[7:0], PC[47:0]}

对于主机发起的陷阱,HT 设为 1;对于用户陷阱或异常,HT 设为 0。TRAP_ID 对于异常为零,对于用户/主机陷阱则为对应的 trapID。进入陷阱处理程序时,出错指令的 PC 将是:(PC - PC_rewind*4)

STATUS.TRAP_EN - 此位向着色器指示是否存在陷阱处理程序。当不存在时,无论它们是浮点异常、用户还是主机发起的陷阱,都不会被处理。当存在陷阱处理程序时,wavefront 会额外使用 16 个 SGPR 进行陷阱处理。如果 trap_en == 0,所有陷阱和异常都被忽略,s_trap 指令会被硬件转换为 NOP。

MODE.EXCP_EN[8:0] - 浮点异常启用位。定义哪些异常和事件会引发陷阱。

3.10.1. 陷阱状态寄存器

陷阱状态寄存器记录先前见过的陷阱或异常。它可以被内核读取和写入。

表 5. 异常字段位

字段 描述
EXCP 8:0 记录已发生异常的 状态位。这些位是粘滞 的,会累积结果,直到着色器程序将其清除。无论 EXCP_EN 如何设置,这些位都会累积结果。无需着色器特权即可读取或写入这些位。 位 异常 0 无效操作 1 输入非规格化数 2 除零 3 上溢 4 下溢 5 不精确结果 6 整数除零 7 地址监视 8 内存违规
SAVECTX 10 由主机命令设置的位 ,指示此 wavefront 必须跳转到其陷阱处理程序并保存其上下文。此位必须由陷阱处理程序使用 S_SETREG 指令清除。注意 - 着色器可以将此位置 1 以触发保存上下文的陷阱,由于硬件延迟,着色器在触发陷阱前最多可能再执行 2 条额外指令。
ILLEGAL_INST 11 检测到非法指令
ADDR_WATCH1-3 14:12 指示地址监视点 1、2 或 3 已被命中。位 12 是地址监视点 1;位 13 是地址监视点 2;位 14 是地址监视点 3。
EXCP_CYCLE 21:16 当浮点异常发生时,此字段告知陷阱处理程序异常发生在哪个周期 。对于常规浮点操作为 0-3,对于双精度浮点加法为 0-7,对于双精度浮点乘加或超越函数为 0-15。此寄存器记录第一个启用的(未屏蔽的)异常发生的周期号。 EXCP_CYCLE[1:0] 相位 :线程 0-15 处于相位 0,线程 48-63 处于相位 3。 EXCP_CYCLE[3:2] 多槽阶段EXCP_CYCLE[5:4] 混合阶段:用于以较低速率运行的机器。
DP_RATE 31:29 决定着色器如何解释 TRAP_STS.cycle。不同的向量着色器处理器以不同的速率处理指令。

3.11. 内存违规

内存违规在以下情况被报告:

  • LDS 对齐错误。

  • 内存读/写/原子操作对齐错误。

  • Flat 访问地址无效(不在任何孔径内)。

  • 写入只读表面。

  • GDS 对齐或地址范围错误。

  • GWS 操作中止(信号量或屏障未执行)。

    指令或标量数据访问不报告内存违规。

如果 LDS 地址越界,内存缓冲区到 LDS 的操作不会返回内存违规,但会屏蔽掉会越界的线程对应的 EXEC 位。

当内存访问违规时,相应的内存(LDS 或纹理缓存)会向 wavefront 返回 MEM_VIOL。这被存储在波前的 TRAPSTS.mem_viol 位中。此位是粘滞的,一旦设置为 1,它将保持为 1,直到用户清除它。

有一个对应的异常启用位。如果在此位置 1 时内存返回违规,wavefront 会跳转到陷阱处理程序。

内存违规报告不是精确的。当 LDS 或纹理缓存处理地址时报告违规;在此期间,wavefront 可能已经处理了更多指令。当报告 mem_viol 时,保存的程序计数器是下一条要执行的指令的 PC;它与引发错误的指令没有关联。

相关推荐
Eloudy19 小时前
02 程序组织 - “Vega“ 7nm Instruction Set ArchitectureReference Guide
gpu·arch
Eloudy1 天前
00前言 01 简介 - “Vega“ 7nm Instruction Set ArchitectureReference Guide
gpu·arch
Eloudy2 天前
learning_gem5 part2_06 创建一个简单的缓存对象
gpu·arch·gem5
Eloudy2 天前
learning_gem5 part2_08 ARM DVFS 建模
gpu·arch·gem5
Eloudy4 天前
一问理解 gem5 与 archmodel 和 cmodel 的关系
gpu·arch·gem5
Seal软件7 天前
GPUStack v2:推理加速释放算力潜能,开源重塑大模型推理下半场
llm·gpu
Eloudy8 天前
learning_gem5 part1_05 gem5 v24.1:使用 gem5 标准库配置脚本
gpu·arch·gem5
Eloudy8 天前
gem5 的统计包 和 API
arch·gem5
Eloudy10 天前
learning_gem5 part1_04 理解gem5统计信息与输出文件
gpu·arch·gem5