5. 陷阱与 trapcause
5.1 精确陷阱
陷阱一律精确:陷入的指令不留任何寄存器、EXEC、CSR、内存或挂起写回的效果(核心按逆序回放本条指令的全部改动,deferred 写回与计数在提交时才入队),然后锁存 trapcause/trappc/trapinfo。唯一例外:FP 异常陷阱保留本条指令新置起的 fflags(指令本身不写回)。一条指令只记第一个陷阱;trappc 是相对 CODE_BASE 的偏移。
v0.1 策略:暂停 warp 并上报 CP。CP 可选择终止、修复后重启或交调试器;trapbase 指向可选处理程序(不自动跳转),处理程序返回前必须恢复 EXEC、MODE 与 pending wait 状态。
5.2 trapcause 编码
| 值 | 原因 | trapinfo |
|---|---|---|
| 1 | 非法指令:非法长度/编码、未实现单元(tex/gfx)、保留枚举值(rm 5/6、cpol 4..7、lane7 ≥ 32)、奇数寄存器对、未对齐 udesc4 | 指令低 32 位 |
| 2 | 显式 trap | imm(零扩展 20 位) |
| 3 | brk | 0 |
| 4 | 使能的 FP 异常 | 本条指令置起的 fflags |
| 5 | MMU 访存故障(含取指) | 故障 VA 低 32 位 |
| 6 | 未对齐(v0.1 访存无对齐要求,保留) | — |
| 7 | scratch 越界(保留:越界读 0、写丢弃,不陷入) | — |
| 8 | 非法 MODE | 写入值(csrs/csrc 为组合后的候选值) |
| 9 | 未知 CSR 或写只读 CSR | CSR 号 |
| 10 | 寄存器号超出 dispatch 分配 | 第一个越界的寄存器号 |
| 11 | shared 访问超出 workgroup 分配 | 偏移低 32 位(负偏移为补码) |
5.3 may_trap 的覆盖范围
YAML 只给 trap/brk/csr* 标了 may_trap,但 FP 使能异常、保留枚举值、奇数寄存器对与访存故障同样会陷入。编译器调度必须把带 fp_mode、访存与含上述操作数的指令按可能陷阱处理;精确陷阱要求核心可回滚,不得假设"陷阱对调度不可见"。
5.4 访存故障、越界与回滚
- lane 按 0→31 顺序访问;某 lane 故障(如 MMU fault)时,本指令此前对内存/寄存器的全部改动被完整撤销——包括编号更小 lane 已完成的 store;已提交的更早指令不受影响。
bounds_checked(buffer/uld.buf)越界或 null:load 读 0、store/atomic 丢弃;越界访问不访存,不会因越界地址落入不存在的页而故障。宽度 ≤ 4 整体检查;> 4 的 load/store 按 4 字节分段、逐段检查;64 位原子不拆段(8 字节整体在界内才执行,.rtn返回 0)。- shared 越界触发 cause 11(不读 0/丢写);scratch 越界读 0、写丢弃、不陷阱(布局为线性:
ScratchBase + (GlobalWarpSlot*32 + lane) * ScratchBytes,YAML 的 "swizzled" 作废)。 - 原子一律需要写权限(只读页上故障,cause 5);浮点原子固定 RNE、不做 DAZ/FTZ、不影响 fflags;同一地址多 lane 原子按 lane 号从小到大串行,各 lane 的
.rtn返回各自看到的旧值。