TASSIGN

指令示意图

TASSIGN tile operation

简介

将Tile对象绑定到实现定义的片上地址(手动放置)。

数学语义

不适用。

汇编语法

TASSIGN 通常在将SSA tile映射到物理存储时由缓冲化/降级引入。

同步形式:

tassign %tile, %addr : !pto.tile<...>, dtype

AS Level 1(SSA)

pto.tassign %tile, %addr : !pto.tile<...>, dtype

AS Level 2(DPS)

pto.tassign ins(%tile, %addr : !pto.tile_buf<...>, dtype)

C++内建接口

声明于 include/pto/common/pto_instr.hpp

公共包含头为 <pto/pto-inst.hpp>,内部声明位于 pto/common/pto_instr.hpp

形式1:运行时地址

template <typename T, typename AddrType>
PTO_INST void TASSIGN(T& obj, AddrType addr);

obj 绑定到片上地址 addr。不执行编译时边界检查(地址值在编译时不可知)。

形式2:编译时地址(含静态边界检查)

template <std::size_t Addr, typename T>
PTO_INST void TASSIGN(T& obj);

obj 绑定到片上地址 Addr。由于 Addr 是非类型模板参数,编译器通过 static_assert 执行以下编译时检查:

检查项 条件 断言ID 错误信息
内存空间存在 capacity > 0 SA-0351 当前架构不支持该内存空间。
Tile可放入内存 tile_size <= capacity SA-0352 Tile存储大小超出内存空间容量。
地址未越界 Addr + tile_size <= capacity SA-0353 addr + tile_size超出内存空间容量(越界)。
地址对齐 Addr % alignment == 0 SA-0354 addr未按目标内存空间要求对齐。

修复建议请参阅 docs/coding/debug.md(修复方案 FIX-A12)。

内存空间、容量和对齐由Tile的 TileType(即 Loc 模板参数)自动确定:

TileType 内存空间 容量 (Atlas A2/A3 训练系列产品/Atlas A2/A3 推理系列产品) 容量 (Ascend 950PR/Ascend 950DT) 容量 (Kirin9030) 容量 (KirinX90) 对齐
Vec UB 192KB 256KB 128KB 128KB 32Byte
Mat L1 512KB 512KB 512KB 1024KB 32Byte
Left L0A 64KB 64KB 32KB 64KB 32Byte
Right L0B 64KB 64KB 32KB 64KB 32Byte
Acc L0C 128KB 256KB 64KB 128KB 32Byte
Bias Bias 1KB 4KB 1KB 1KB 32Byte
Scaling FBuffer 2KB 4KB 7KB 6KB 32Byte
ScaleLeft L0A N/A 4KB N/A N/A 32Byte
ScaleRight L0B N/A 4KB N/A N/A 32Byte

容量可通过编译标志 -D 覆盖(如 -DPTO_UBUF_SIZE_BYTES=262144)。详见 include/pto/common/buffer_limits.hpp

注意: 该重载仅适用于 TileConvTile 类型。对于 GlobalTensor,请使用 TASSIGN(obj, pointer)(形式1)。

约束

  • 实现检查:
    • 如果 obj 是Tile(含ConvTile):
      • 在手动模式下(未定义 __PTO_AUTO__ 时),addr 必须是整数类型,并被重新解释为tile的存储地址。
      • 在自动模式下(定义了 __PTO_AUTO__ 时),TASSIGN(tile, addr) 是空操作。
    • 如果 objGlobalTensor
      • addr 必须是指针类型。
      • 指向的元素类型必须匹配 GlobalTensor::DType

示例

运行时地址(无编译时检查)

#include <pto/pto-inst.hpp>

using namespace pto;

void example_runtime() {
  using TileT = Tile<TileType::Vec, float, 16, 16>;
  TileT a, b, c;
  TASSIGN(a, 0x1000);
  TASSIGN(b, 0x2000);
  TASSIGN(c, 0x3000);
  TADD(c, a, b);
}

编译时地址(含静态边界检查)

#include <pto/pto-inst.hpp>

using namespace pto;

void example_checked() {
  using TileT = Tile<TileType::Vec, float, 16, 16>;
  TileT a, b, c;

  TASSIGN<0x0000>(a);   // OK: 0x0000 + 1024 <= 192KB
  TASSIGN<0x0400>(b);   // OK: 0x0400 + 1024 <= 192KB
  TASSIGN<0x0800>(c);   // OK: 0x0800 + 1024 <= 192KB
  TADD(c, a, b);
}

以下示例触发编译错误:

void example_oob() {
  // Tile<Vec, float, 256, 256> 占用 256*256*4 = 256KB
  using BigTile = Tile<TileType::Vec, float, 256, 256>;
  BigTile t;

  // 主要触发 [SA-0352]: tile_size (256KB) > UB 容量 (A2A3 为 192KB)
  // (tile 已超过整块缓冲区,SA-0353 越界断言同时成立)
  TASSIGN<0x0>(t);
}
void example_oob_addr() {
  using TileT = Tile<TileType::Vec, float, 128, 128>;  // 64KB
  TileT t;

  // static_assert 触发 [SA-0353]: 0x20020 + 64KB > 192KB(地址已对齐,仅越界)
  TASSIGN<0x20020>(t);
}

Ping-pong L0缓冲区分配

void example_pingpong() {
  using L0ATile = TileLeft<half, 64, 128>;   // L0A tile
  using L0BTile = TileRight<half, 128, 64>;  // L0B tile

  L0ATile a0, a1;
  L0BTile b0, b1;

  TASSIGN<0x0000>(a0);   // L0A ping
  TASSIGN<0x8000>(a1);   // L0A pong
  TASSIGN<0x0000>(b0);   // L0B ping(与 L0A 为不同物理内存)
  TASSIGN<0x8000>(b1);   // L0B pong
}

汇编示例(ASM)

自动模式

# 自动模式:由编译器/运行时负责资源放置与调度。
pto.tassign %tile, %addr : !pto.tile<...>, dtype

手动模式

# 手动模式:先显式绑定资源,再发射指令。
# 可选(当该指令包含 tile 操作数时):
# pto.tassign %arg0, @tile(0x1000)
# pto.tassign %arg1, @tile(0x2000)
pto.tassign %tile, %addr : !pto.tile<...>, dtype

PTO汇编形式

tassign %tile, %addr : !pto.tile<...>, dtype
# AS Level 2 (DPS)
pto.tassign ins(%tile, %addr : !pto.tile_buf<...>, dtype)