Skip to content

[PTO v0.58][TSEL] API emits single-B.IOT but spec requires an explicit false-source binding #39

Description

@ziyang-cheng

问题描述

TSEL(dst, mask, trueSrc)dst = mask ? trueSrc : dst_prior,false-source 就是 dst 自身)经工具链
lower 成一条 B.IOT:两个 tile 源(mask、trueSrc)+ ->dst 就地。官方发布版 emulator 却按
显式三源建模,于是 validate 侧要求首拍 dsts.empty()、execute 侧读 srcTile[2] → 一条 TSEL 即崩。

复现步骤 / 触发条件

复现基线

仓库 HEAD 说明
SuperNPUBench 3ecd9083 pr: PTO-ISA/SuperNPUBench#49
SuperScalarModel(gfrun) 63dbb5a2
linx-toolchain-build e6a31ef
Linx-TileOP-API cdeb624

最简复现探针

test/kernel/quant/dynamic_mx_quant/src/tsel_inplace_probe.cpp(Makefile TYPE=TSEL_INPLACE_PROBE)——
整个 kernel 只有一条 TSEL,不牵涉 dynamic_mx_quant 的任何 scale 计算:

tile_u16 x, mask, k;
TEXPANDS(x,    (uint16_t)0xABCD);   // 就地 false-source 种子
TEXPANDS(mask, (uint16_t)1);        // 全真谓词
TEXPANDS(k,    (uint16_t)0x1234);   // true-source 常量
TSEL(x, mask, k);                   // 就地: x = mask ? k : x_prior
TSTORE(gy, x);

实测报错( bin/gfrun @ 63dbb5a2)

gfrun: illegal instruction: ASSERTION FAILED:
  inst->srcs.size() == 3 && inst->dsts.empty() &&
  IsCompatibleLogicalTile(inst->srcs[1], ...) &&
  IsCompatibleDataTile(inst->srcs[2], ...) &&
  "select first B.IOT requires mask then true/source Tile"
, func ValidateCompareSelectTepl, file emulator/engine/AccumulateBlockInfo.cpp:383

同一条 ELF 在带修复的 emulator 上 R2 = 0 跑通(12 block / 61 inst)——隔离出缺陷在
emulator 的 TSEL 建模层,非 kernel、非 ISA 编码。

附加信息

Ground truth:工具链实发的 TSEL lowering

.../tileop-api/jcore/template_asm.hpp TSEL(dst,src0,src1) 汇编体 = 一条 B.IOT

BSTART.TEPL 0, 26, %D1
B.DIM %2, 0, ->lb0            ; validCol
B.DIM %3, 0, ->lb1            ; validRow
B.DIM zero, %c4, ->lb2        ; physicalCol = Cols
B.IOT %5, %6, mask=1111, last, ->%0<%Z7>   ; %5=mask, %6=trueSrc, ->%0=dst 兼就地 false-source

两个源 tile(mask、trueSrc)+ dst 就地兼隐式 false-source;无第二拍、无独立第三源。TSELS
(scalar false-source)同族形态,属 ISA 固有 lowering。

emulator 现状(63dbb5a2,两侧都假设显式三源)

  • validate AccumulateBlockInfo.cpp:383 ValidateCompareSelectTepl 首拍分支强制
    inst->srcs.size()==3 && inst->dsts.empty()(首拍不许带 dst、要独立第三源)→ 工具链单拍带 dst(->%0) 撞断言。
  • execute TEPLEngine.cpp:1118 ExecuteTSEL:1126 无条件block->srcTile[2](假设三源)→
    工具链只 2 源 → 越界(validate 放宽后才会暴露)。

按最新 PTO ASL 复核后的结论

需要修正本 issue 当前的根因判断:按最新 PTO-ISA/pto-spec/main@8f8244d3ce71174a048f852625ca6138296b6dcc,这里复现的“单条 B.IOT + destination 就地作为 false-source”不是 TSEL 的合法 canonical lowering。当前现象的真实原因是 compiler/用例生成的 TSEL bundle 不符合最新 PTO spec contract,模型在 validate 阶段拒绝该 bundle 是符合规范的 fail-closed 行为。

规范原文见:

ASL 中的 canonical binding 原文

TSEL.aslcontract.block_composition 原文要求:

BSTART.VEC TSEL, DataType
B.DATR PadValue (optional)
B.DIM LB0=ValidCol
B.DIM LB1=ValidRow (optional)
B.DIM LB2=Col (optional)
B.IOT Predicate, SrcTrue, mask=PE_MASK
B.IOT SrcFalse, mask=PE_MASK, <last>, ->DstTile<TSize>
BSTOP

同一个 ASL contract 的 legality 原文是:

Exactly two ordered Local B.IOT bindings are required.
The first supplies packed Predicate and SrcTrue without Last or a destination;
the second supplies SrcFalse and one new terminating destination.
B.IOR, B.IOS, and additional bindings are illegal.

ASL 对 operand role 的原文定义是:

destination0 | new Local numeric destination
source0      | packed one-bit Local predicate mask
source1      | persistent Local source selected by one
source2      | persistent Local source selected by zero

因此 TSEL 的标准语义是:

predicate bit = 1 -> SrcTrue
predicate bit = 0 -> SrcFalse

而不是:

predicate bit = 0 -> implicit destination prior

ASL 的 state/ordering contract 还要求 source snapshot 先于 destination write,但这表示 source/destination alias 时必须观察旧值,并不表示可以省略显式的 SrcFalse binding:

Predicate bits and both data payloads are snapshotted before the first destination write,
so equal sources and source/destination aliases observe read-old values.

当前 issue 复现违反了哪些字段

Issue 中给出的 lowering 是:

B.IOT %5, %6, mask=1111, last, ->%0<%Z7>

它相当于把 Predicate + SrcTrue + Last + Destination 放在一条 B.IOT 中,和最新 ASL 有以下冲突:

  1. 第一条 B.IOT 不允许带 Last
  2. 第一条 B.IOT 不允许带 destination;
  3. 缺少第二条 B.IOT 提供 SrcFalse
  4. destination 被错误地当成了隐式 false-source;
  5. ASL 要求 destination 是新的 Local numeric destination,而不是用 destination prior 替代 source2

所以 issue 中“工具链实发的单拍 B.IOT 是 ISA 固有 lowering”这一判断,与当前最新 ASL 不一致。旧版本工具链、旧 compiler lowering 或旧 benchmark ELF 的运行成功,不能作为 0.58.4 contract 的依据;permissive emulator 能运行 malformed bundle 也不能证明该 bundle 合法。

模型代码与规范的对应关系

当前模型的 TSEL validate 逻辑已经按上述两段 binding 处理:

  • 第一拍要求 Predicate + SrcTrue,无 destination;
  • 第二拍要求 SrcFalse,并分配 destination;
  • execute 路径使用三个 source roles:mask、true source、false source。

对应代码:

当前首拍触发的 assertion:

select first B.IOT requires mask then true/source Tile

对于 issue 给出的非 canonical single-B.IOT ELF,属于预期的 legality rejection,不应通过放宽 dsts.empty() 或将 dstTile[0] 自动当作 srcTile[2] 来绕过。那样会让模型接受 ASL 明确禁止的 binding schema。

应该怎样修复

compiler/用例应按最新 ASL 重新生成 ELF,形式应为:

BSTART.VEC TSEL, DataType
B.DIM LB0=ValidCol
B.DIM LB1=ValidRow
B.DIM LB2=Col
B.IOT Predicate, SrcTrue, mask=PE_MASK
B.IOT SrcFalse, mask=PE_MASK, last, ->DstTile<TSize>
BSTOP

如果高级 API 仍然提供:

TSEL(x, mask, trueSrc)

并希望用户看到“就地更新”,compiler 应在内部将旧的 x 作为第二条 B.IOT 的 SrcFalse,生成新的 destination binding,再更新后续 x 的 tile binding;不能把旧 destination 隐式塞进第一条 B.IOT。

请 compiler/用例侧基于最新 pto-spec 重新生成 tsel_inplace_probe,并提供 canonical two-B.IOT ELF。若 canonical ELF 在模型上仍失败,再单独建立模型修复;当前 issue 中的 single-B.IOT 复现不应作为模型放宽依据。

归属结论

根因:compiler / benchmark ELF lowering 不符合最新 PTO TSEL ASL
模型:当前 fail-closed 行为符合最新 TSEL binding contract
修复侧:compiler/用例生成链

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions