Skip to content

TEPL inline region path rejects CubeM32 sub-views and SharedTile sub-view sources — both contradict PTO-ISA 0.58.6 #75

Description

@lvhao7896

TEPL inline region path rejects CubeM32 sub-views and SharedTile sub-view sources — both contradict PTO-ISA 0.58.6

Summary

The inline Tile region producer path (pto_tile_region_inline_asm.hpp) imposes two constraints that are not grounded in the PTO-ISA specification and block legitimate, ISA-legal usage of B.SUBVIEW with TPARTVIEW on TEPL operations (TROWSUM, TADD, TEXP, …):

  1. CubeM32 rejectionstatic_assert(SubTile::BFractal == BLayout::RowMajor) rejects CubeM32 sub-tiles even though the ISA spec normatively defines CUBE sub-view descriptor derivation (BundleCubeSubviewDescriptorOf).
  2. SharedTile rejectionSubTileView::data() calls parent_->data(), which does not exist on SharedTile (Shared tiles use handle()), even though the ISA spec explicitly allows B.SUBVIEW after B.IOS (Shared binder).

Both constraints are acknowledged as intentional limitations in the compiler's own documentation (range-modifiers.md), but neither is supported by the ISA spec. The ISA spec explicitly supports both CUBE sub-views and Shared sub-views.


Constraint 1: CubeM32 sub-view rejected by RowMajor static_assert

Symptom

Compiling TPARTVIEW<CubeTileM32<float,32,4>, 1, 4>(parent) followed by TROWSUM(dst, subview) fails:

static_assert(SubTile::BFractal == BLayout::RowMajor,
              "inline Tile region path requires RowMajor fragments")

Location: pto_tile_region_inline_asm.hpp:13 (in pto_region_unary)

ISA spec evidence

The PTO-ISA 0.58.6 specification normatively supports CUBE B.SUBVIEW:

NDF PTO-B-SUBVIEW-DESCRIPTOR-001 (asl/block/model/operands/subview-descriptor.asl:3-9):

A legal Local CUBE B.SUBVIEW MUST derive a bounded descriptor from the parent descriptor, XLEN offset, and encoded view capacity in CELL order. Parent lifetime and payload remain unchanged; non-CUBE, zero-valid, and out-of-range geometry is rejected with Fault_TileLegality before effects.

This NDF explicitly contemplates "Local CUBE B.SUBVIEW" as a legal construct.

BundleCubeSubviewDescriptorOf() (asl/block/model/operands/subview-descriptor.asl:36-124):
The function derives a bounded sub-view descriptor from a CUBE parent tile. It:

  • Requires TileLayoutIsCube(parent.layout) (line 44) — the function is specifically designed for CUBE layouts
  • Computes cell_rows / cell_columns from the CUBE layout (lines 59-60)
  • Handles CUBE_N8 and other CUBE layouts (e.g., CUBE_M32) in separate branches (lines 65-83)
  • For non-N8 CUBE layouts (including M32): origin_column = offset_cells * cell_columns (line 81-82)

MaterializeBundleSubview() (asl/block/model/operands/subview-descriptor.asl:264-423):
When the consuming operation is a non-CUBE (TEPL) operation like TROWSUM:

  • Lines 293-295: operation_is_cube = BundleTileDecodeFamily(...) == TileDecode_CUBE
  • Lines 330-387: For non-CUBE operations, the materialized view is configured as RowMajor (TileLayout_RowMajor, line 385), reading from the CUBE parent in its original CELL order
  • Lines 389-401: Data is copied from the CUBE parent (ReadTileElement(parent, origin_row+row, origin_column+column)) into the RowMajor materialized view

This means the ISA spec's intended behavior for a CUBE parent + TEPL consumer is: the hardware materializes a RowMajor view of the CUBE parent's sub-region at execution time. The compiler does not need to emit RowMajor fragments — it can emit B.SUBVIEW on a CUBE source and the hardware handles the CUBE→RowMajor materialization.

Applicability is total (asl/block/model/operands/subview-descriptor.asl:133-140):

B.SUBVIEW applicability is total over accepted Tile operations; the selected operation handler retains ownership of dtype, layout, shape, and definedness legality.

There is no operation-specific restriction — TROWSUM, TADD, and all other TEPL operations are legal consumers.

Compiler's own acknowledgment

docs/tileop-usage/range-modifiers.md:119-123:

CubeTileM16 and CubeTileM32 are supported by the Tile type and partition contract checks. The current region producer inline-asm path is intentionally limited to RowMajor + NoneBox; do not use TCVT or row-wise region producers with Cube fragments until the Cube binder/CELL ordering path is implemented and validated.

This is a documented known limitation and future implementation item, not an ISA constraint.

Impact

Any kernel that loads data into a CubeM32 local tile (the standard local L0 layout for matrix data) and wants to partition it with TPARTVIEW for element-wise or reduction operations is blocked. The only workaround is to use RowMajor local tiles, which is not the correct L0 layout for matrix data and forces an extra layout conversion on TLOAD.


Constraint 2: SharedTile sub-view source rejected by data() dependency

Symptom

Compiling TPARTVIEW<SharedTile<SharedMatrixLeft<float,32,4>>, 1, 4>(shared_parent) followed by TROWSUM(dst, subview) fails:

no member named 'data' in 'pto::SharedTile<...>'

Location: pto_tile_region.hpp:97SubTileView::data() calls parent_->data(), but SharedTile has no data() method (it exposes handle() / handle_ref() instead).

ISA spec evidence

The PTO-ISA 0.58.6 specification explicitly supports B.SUBVIEW with B.IOS (Shared):

B.SUBVIEW block composition (asl/block/operands/B.SUBVIEW.asl:1, contract "block_composition"):

Immediately follows B.IOT or B.IOS and is contiguous with the associated modifier group.

B.SUBVIEW legality (asl/block/operands/B.SUBVIEW.asl:1, contract "legality"):

SubviewSizeCode raw values 1..12 are decoded; Local-associated groups require 1..10 and Shared-associated groups accept 1..12.

The ISA distinguishes Local (SizeCode 1..10) from Shared (1..12) — Shared B.SUBVIEW is explicitly legal.

NDF PTO-B-SUBVIEW-RANGE-001 (asl/block/operands/B.SUBVIEW.asl:3-11):

B.SUBVIEW MUST decode the exact 0x53 form, preserve raw fields and the XLEN-wrapped GPR-plus-uimm11 offset, and apply only to its preceding contiguous B.IOT/B.IOS group. Raw SizeCodes 11 and 12 attached to a Local group MUST raise Fault_TileLegality before GPR reads or carrier updates; the same raw codes attached to a Shared group remain legal.

ADR-BLOCK-0016 (docs/status/decisions/ADR-BLOCK-0016-b-range-modifiers.md:93-94):

Each modifier belongs only to the immediately preceding contiguous B.IOT or B.IOS syntactic group.

TSTORE already implements this correctly

TSTORE in jcore/template_asm.hpp:2054-2180 already handles both cases:

  • is_subview_v<tile_shape> check (line 2054)
  • Shared parent: uses B.IOS + handle() + B.SUBVIEW (lines 2056-2118)
  • Local parent: uses B.IOT + data() + B.SUBVIEW (lines 2119-2182)

The range::Subview carrier already supports both:

  • data()requires(!is_shared_tile_v<Parent>) (pto_tile.hpp:1948-1951)
  • handle() / handle_ref()requires(is_shared_tile_v<Parent>) (pto_tile.hpp:1952-1959)

The compiler's range-modifiers.md:274-296 documents this as implemented for TLOAD/TSTORE:

Range carriers over a SharedTile parent bind through the Shared B.IOS binder instead of B.IOT, and expose handle() / handle_ref() instead of data().

Gap: TEPL operations lack Subview carrier support

The problem is that TEPL operations (TROWSUM, TADD, etc.) have no Subview carrier overload — only the SubTileView (from TPARTVIEW) overload in pto_tile_region_inline_asm.hpp. The SubTileView class:

  • Has data() that calls parent_->data() — fails for SharedTile
  • Has no handle() method for Shared parents

The generic TROWSUM in template_asm.hpp:9606 uses is_tile_data_v which matches Subview carriers (via is_tile<range::Subview<...>> at pto_tile.hpp:2249), but does not emit B.SUBVIEW — it would use the parent's full data without range restriction.

Impact

Any kernel that loads data into a SharedTile (the standard L1 shared storage for multi-PE cooperation) and wants to partition it with TPARTVIEW for element-wise or reduction operations is blocked. There is no workaround through the Subview carrier either, because TEPL operations don't emit B.SUBVIEW for Subview carriers.


Proposed fix

Fix A: CubeM32 sub-view in inline region path

The inline region path (pto_region_unary, pto_region_binary, etc. in pto_tile_region_inline_asm.hpp) should be extended to accept CubeM32 (and CubeM16) sub-tiles. Two possible approaches:

Option A1 (compiler-side materialization): Remove the RowMajor static_assert and emit B.IOT + B.SUBVIEW for CubeM32 sources, relying on the hardware's BundleCubeSubviewDescriptorOf + MaterializeBundleSubview to materialize the RowMajor view at execution time (as the ISA spec describes). The inline asm already emits B.SUBVIEW — the only change is removing the static_assert and ensuring the B.DIM operands use the sub-tile's ValidCol/ValidRow (which SubTileView already forwards from SubTile).

Option A2 (compiler-side CUBE→RowMajor conversion): Implement the "Cube binder/CELL ordering path" mentioned in range-modifiers.md:123. This would be a more complex change but would match the ISA spec's materialization model where the hardware copies CUBE parent data into a RowMajor materialized tile.

Option A1 is simpler and sufficient for TEPL operations (TROWSUM, TADD, etc.), since the ISA spec says non-CUBE operations consume the bounded view in RowMajor representation.

Fix B: SharedTile sub-view in TEPL operations

Two changes needed:

  1. SubTileView should support Shared parents: Add handle() / handle_ref() methods to SubTileView (in pto_tile_region.hpp) that forward to parent_->handle() / parent_->handle_ref() for SharedTile parents, similar to how Subview already does (pto_tile.hpp:1952-1959).

  2. Inline region path should emit B.IOS for Shared sources: In pto_region_unary / pto_region_binary (in pto_tile_region_inline_asm.hpp), add a if constexpr (is_shared_tile_v<Parent>) branch that uses B.IOS + handle() instead of B.IOT + data(), mirroring the pattern already implemented in TSTORE (template_asm.hpp:2054-2118).

Alternatively (or additionally), TEPL operations in template_asm.hpp (TROWSUM, TADD, etc.) should gain is_subview_v checks to handle Subview carriers directly, similar to TSTORE. This would allow the range::subview() factory API to be used with TEPL operations, not just TSTORE.


Reproduction

Both issues are reproducible with the rowsum_subview_local and rowsum_subview_shared test cases in SuperNPUBench/benchmark/one-level-arch/test/kernel/reduction/reducesum_row/src/.

Constraint 1 (CubeM32)

make diss TESTCASE=rowsum_subview_local \
  COMPILER_DIR=$COMPILER_DIR \
  ROWSUM_ROWS=128 ROWSUM_COLS=16 ROWSUM_PARTS=4 \
  OBJ_ROOT=/tmp/rowsum_local_build

Error: static assertion failed: inline Tile region path requires RowMajor fragments

Constraint 2 (SharedTile)

make diss TESTCASE=rowsum_subview_shared \
  COMPILER_DIR=$COMPILER_DIR \
  ROWSUM_ROWS=128 ROWSUM_COLS=16 ROWSUM_PARTS=4 \
  OBJ_ROOT=/tmp/rowsum_shared_build

Error: no member named 'data' in 'pto::SharedTile<...>'


References

Source Path Key evidence
B.SUBVIEW ASL pto-spec/asl/block/operands/B.SUBVIEW.asl Block composition: "Immediately follows B.IOT or B.IOS"; Legality: Local 1..10, Shared 1..12
Subview descriptor ASL pto-spec/asl/block/model/operands/subview-descriptor.asl NDF PTO-B-SUBVIEW-DESCRIPTOR-001: "A legal Local CUBE B.SUBVIEW"; BundleCubeSubviewDescriptorOf(): CUBE descriptor derivation; MaterializeBundleSubview(): CUBE→RowMajor materialization for non-CUBE ops
ADR-BLOCK-0016 pto-spec/docs/status/decisions/ADR-BLOCK-0016-b-range-modifiers.md "Each modifier attaches only to the eligible Local or Shared binding group"
B.SUBVIEW reader doc pto-spec/docs/block/operands/B.SUBVIEW.md Legality section: "Local-associated groups require 1..10 and Shared-associated groups accept 1..12"
Compiler doc (acknowledgment) linx-toolchain-build/src/Linx-TileOP-API/docs/tileop-usage/range-modifiers.md L119-123: "intentionally limited to RowMajor + NoneBox"; L274-296: Shared Tile ranges documented as implemented for TLOAD/TSTORE
TSTORE (reference impl) linx-toolchain-build/.../jcore/template_asm.hpp:2054-2180 is_subview_v check with Shared (B.IOS + handle) and Local (B.IOT + data) branches
Subview carrier linx-toolchain-build/.../common/pto_tile.hpp:1896-1968 data() for Local, handle() for Shared
Inline region path (constraint) linx-toolchain-build/.../common/pto_tile_region_inline_asm.hpp:13 static_assert(SubTile::BFractal == BLayout::RowMajor)
SubTileView (constraint) linx-toolchain-build/.../common/pto_tile_region.hpp:97 data() { return parent_->data(); } — no handle() for Shared
Test cases SuperNPUBench/.../reducesum_row/src/rowsum_subview_local.cpp CubeTileM32 + TPARTVIEW + TROWSUM
Test cases SuperNPUBench/.../reducesum_row/src/rowsum_subview_shared.cpp SharedTile + TPARTVIEW + TROWSUM

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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