地址与数据对齐¶
“对齐”在 c220 上不是一个统一数字。编写汇编时至少要区分指令编码、Scalar 数据访问、Vector 操作数、MTE 拆包,以及 cache line/Bank 仲裁五个层次。只有前几类可能决定指令是否有效;line 和 Bank 粒度通常只决定请求如何归并、占用端口或发生冲突。
本页使用以下记号:
其中 \(a\) 是字节地址,\(G\) 是字节粒度。\(G\) 为 2 的幂时,可分别写成 a & ~(G - 1) 和 (a + G - 1) & ~(G - 1)。
先判断是哪一种对齐¶
| 层次 | 典型规则 | 不满足时的含义 |
|---|---|---|
| 指令与标签 | 指令 4 B;分支标签 4 B;ADRP 页 4096 B |
汇编/重定位约束或错误的 PC |
| Scalar 数据 | 最终有效地址按访问宽度 ½/4/8 B | 执行期输出非对齐诊断;普通请求仍继续形成 |
| Vector 数据 | 普通源和目标 32 B,少数归约目标使用动态阈值 | 记录地址非对齐指令异常 |
| MTE/AIPP 拆包 | 常见 32 B;部分路径按 64 B 或接口粒度拆分 | 扩大覆盖范围、补齐或产生多个 uop,不等同于通用许可 |
| cache line/Bank | D-cache 64 B、UB Bank 32 B、L1 Bank 32 B | line 归并、Bank 占用和冲突;通常不是独立的地址合法性判断 |
bisheng 能检查什么¶
bisheng 能固定立即数字段、标签和重定位的编码约束,却通常不知道 X 寄存器在设备执行时的值。下列程序能够汇编:
这里的 #1 是 1 字节偏移。汇编成功只说明 12 位有符号立即数可以表示 1;最终地址 X1 + 1 是否按 8 字节对齐,要到执行期才能判断。相同原则适用于 Xs 描述字中的 stride、repeat,以及 MTE、Vector 和 Cube 的地址寄存器。
因此,立即数表中的 alignment=1 表示字段以 1 字节为单位,不表示 .b64 访问允许任意字节地址。分支的 alignment=4 和 ADRP 的 alignment=4096 才是标签/页的编码约束。
Scalar LSU¶
有效地址¶
令 \(W\) 为访问宽度:.b8=1、.b16=2、.b32=4、.b64=8 字节。普通地址模式下,各形式使用:
LDP/STP 的 6 位有符号偏移同样按字节加入基址;成对的第二个元素位于第一个元素之后。原子 store 的寄存器索引和立即数形式分别沿用上述两种计算。
运行时检查¶
普通 Scalar 访存检查:
不满足时会输出地址非对齐诊断。该路径没有把诊断升级为独立的指令异常,之后仍会构造访存请求;因此程序不能依靠这种行为取得可移植的“非对齐加载/存储”语义。
DC_PRELOAD 的寄存器和立即数形式不执行上述诊断。预取路径把请求粒度设为 64 B,但这表示 cache-line 预取范围,并不要求预取地址本身是 64 B 整数倍。
推荐始终让 Scalar 数据满足自然对齐,且让成对访问的首地址按元素宽度对齐:
Vector 地址检查¶
普通规则¶
Vector 指令在发射前按源地址 0、源地址 1、目标地址三个槽检查。普通阈值为:
| 地址槽 | 普通阈值 |
|---|---|
| source 0 | 32 B |
| source 1 | 32 B |
| destination | 32 B |
每个启用的地址槽都必须满足 address % threshold == 0。任一槽失败都会记录地址非对齐指令异常;这比 Scalar 的诊断路径更严格。
归约目标的动态阈值¶
源地址仍使用 32 B。部分归约指令只改变 destination 的阈值。令 \(E\) 为后缀对应的元素字节数:
| 指令 | 模式 | destination 对齐 |
|---|---|---|
VCADD |
.f16 |
2 B |
VCADD |
其他合法 dtype | 4 B |
VCMAX / VCMIN |
reduce_mode=0/1 |
\(2E\) B |
VCMAX / VCMIN |
reduce_mode=2 |
\(E\) B |
VCMAX / VCMIN |
reduce_mode=3 |
4 B |
VCGMAX / VCGMIN / VCGADD |
.f16 |
16 B |
VCGMAX / VCGMIN / VCGADD |
其他合法 dtype | 32 B |
VCPADD |
所有已知形式 | 32 B |
reduce_mode 就是 VCADD/VCMAX/VCMIN 文本形式末尾的立即数。它既改变归约布局,也可能改变结果地址要求,不能只按立即数位宽判断合法性。
专用地址槽¶
有些指令不使用普通的“两个源、一个目标”组合:
| 指令 | 执行的通用模数检查 |
|---|---|
VGATHER、VGATHERB、MOVEV、VMOVMASK_XD |
仅 destination,使用 destination 动态阈值 |
VMOVMASK_XN |
仅 source 0,32 B |
VREDUCE、VREDUCEV2 |
source 0 和 destination;仅当内部归约模式非 0 时再检查 source 1 |
MOVEVA、MOVEMASK、LD_VAD、VNCHWCONV |
不进入普通地址模数检查 |
“不进入普通检查”不表示任意地址都安全。这些指令使用 VA、MASK、VAD 或专用重排状态,合法性还取决于相应描述字和逐 lane 地址。
MTE 的对齐、补齐与拆包¶
MTE 没有一个适用于所有搬运指令的固定 address % N 判定。许多路径会把一个逻辑请求转换成覆盖对齐边界的多个物理片段。
32 字节覆盖区间¶
普通对齐缓存先计算:
随后按接口最大包长或指令选择的顺序粒度拆包。末包可能按 32 B 向上补齐;特定输入路径直接按 64 B 分包。由此得到两条开发规则:
- 非 32 B 对齐的逻辑起点可能让底层请求覆盖逻辑区间之前的字节。
bytes没跨边界不代表底层包也不跨边界;边界检查必须使用扩展后的覆盖区间。
MOV_SRC_TO_DST_ALIGN¶
MOV_SRC_TO_DST_ALIGN 使用专用对齐搬运路径。它按 32 B 计算头部填充:
元素宽度为 1、2 或 4 B 时,填充数据分别按相同宽度复制。其行推进在源、目标两侧使用一组“原始跨度”和“32 B 向上对齐跨度”,搬运方向决定哪一侧采用:
因此这条指令能够处理指定格式的头尾不齐,但不能推广成“所有 MTE 指令都支持任意非对齐地址”。普通 MOV_<SRC>_TO_<DST> 仍要按它自己的 Xs、burst、stride 和地址空间规则建立描述字。
AIPP 读取¶
AIPP 读取以路径给出的读粒度 \(G\) 扩大请求:
再以 \(G\) 为步长生成读取 uop。该实现按 \(\lfloor\log_2G\rfloor\) 做移位取整,所以 \(G\) 应为 2 的幂。逻辑图像区域即使从非对齐位置开始,映射也必须覆盖扩大后的首尾请求。
cache line 与 Bank 粒度¶
下面的数字用于请求归并和冲突分析,不能代替前面的 operand 对齐规则。
| 资源 | 当前执行模型粒度 | 地址映射 |
|---|---|---|
| D-cache line | 64 B | line_base = floor(EA / 64) * 64 |
| UB Bank | 32 B | bank = ((EA >> 12) & 0x30) | ((EA >> 5) & 0x0f) |
| L1 Bank | 32 B,8 Banks | start = floor(EA / 32) % 8 |
| L1 buffer line | 16 B | 接口分段粒度,不是通用 operand 对齐 |
| L0A/L0B 请求 line | 512 B | Cube/MTE 请求分段和占用粒度 |
UB 公式等价于 bank = concat(EA[17:16], EA[8:5])。因此地址相差 32 B 通常切换低 4 位 Bank,地址相差 64 KiB 切换高 2 位;自然对齐并不能保证同拍多路访问无 Bank 冲突。
L1 的请求 Bank mask 使用:
其中当前 \(B=32\)、\(N=8\)。span 不额外加入 EA % B 的头部偏移,说明到达该层的请求应已由上游拆分,或以 Bank 宽度对齐。手写直接面向 L1 的描述字时,保守做法是让每段首地址按 32 B 对齐。
地址窗口与扩大后的边界¶
Vector 读写还会检查配置描述字定义的 32 B 粒度异常窗口。对一个 64 位窗口字 \(D\):
读窗口由 \(D[29]\) 启用,写窗口由 \(D[28]\) 启用;地址落入闭区间 [lower, upper] 时记录数据访问异常。它与 address % alignment 是两次独立判断。
对 MTE/AIPP,还应使用 align_down 后的首地址和 align_up 后的末地址检查映射范围。仅验证逻辑 payload 的首尾,可能漏掉为拆包或补齐而访问的前导/尾随字节。
Cube 地址¶
Cube 指令没有套用 Vector 那种统一的 operand 模数检查。地址先由 L1/L0 布局、Cube shape 和描述字展开,再由 L0 请求 line、端口和 Bank 处理。没有通用检查不等于任意地址有效;手写 MMAD/加载描述字时应按 tile 布局构造 L0A/L0B/L0C 地址,并把 512 B line 视为请求和冲突粒度,而不是宣称所有 Cube operand 都有一个固定 512 B 硬对齐条件。
推荐检查清单¶
- 先按立即数表检查字段范围和编码缩放。
- 计算完整 \(EA\),不要只检查基址或立即数。
- Scalar 按后缀宽度自然对齐;Vector 普通地址按 32 B,对归约目标应用动态表。
- MTE 使用 Xs 展开每个 burst/stride,并把首尾扩展到实际分包粒度。
- 将扩展区间与 GM/UB/L1/L0 的映射边界比较。
- 合法之后再用 UB/L1 Bank 公式分析冲突;不要把“无异常”和“无冲突”当成同一件事。
机器可读版本见地址与数据对齐规则 CSV。