Skip to content

chore(runtime)!: bump simpler to 799640e6; adopt its renamed and removed API - #2530

Merged
lyfne123 merged 1 commit into
hw-native-sys:mainfrom
lyfne123:chore/bump-runtime-799640e6
Aug 27, 2026
Merged

lyfne123 merged 1 commit into
hw-native-sys:mainfrom
lyfne123:chore/bump-runtime-799640e6

Conversation

@lyfne123

@lyfne123 lyfne123 commented Aug 26, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Bumps the runtime submodule 93adc386 → 799640e6 (69 commits) and adapts
pypto to the four pypto-facing changes in that range: simpler finished retiring
the PTO2 naming, renamed two headers pypto #includes from generated code,
split ChipTensor into a boundary type and a per-runtime working type, and
removed TensorCreateInfo::set_initial_value. runtime/pto_isa.pin is
unchanged at cd4a3d3f.

The first three are mechanical but not optional: without them the generated
orchestration C++ no longer compiles, and the kernels silently read the wrong
struct. The fourth is a breaking change for users:
pl.create_tensor(..., init_value=...) lowered to the removed call and now
raises ValueError naming its replacement.

Changes

  • runtime: submodule gitlink 93adc386 → 799640e6.
  • src/codegen/orchestration/, src/ir/, python/pypto/: adopt the retired
    names — PTO2TaskId→TaskId, PTO2_SCOPE→SIMPLER_SCOPE,
    PTO2ScopeMode→ScopeMode, PTO2OrchestrationConfig→OrchestrationConfig,
    PTO2_ERROR_ASYNC_*→SIMPLER_ERROR_ASYNC_* (simpler
    build: use cmake.version instead of removed cmake.minimum-version #1963/[Code Health] Orchestration codegen emits unconditional TaskId is_valid() guard on every dependency #1966/fix(ci): update pypto-lib Qwen3-14B decode path to decode_layer.py #1969/[RFC] Pluggable DSA Memory-Planning Solver + PyPTO Adapter #1980). Three are prefix strips; PTO2_SCOPE and the error
    codes take SIMPLER_ because a bare SCOPE( would expand too eagerly and the
    status codes share a band with the host-side C API.
  • src/codegen/orchestration/orchestration_codegen.cpp,
    python/pypto/runtime/builtins/collectives/*/templates/entry.cpp.in: emit
    orchestration_api.h and async_kernel_api.h, which simpler build: use cmake.version instead of removed cmake.minimum-version #1963 renamed
    from their pto_-prefixed spellings.
  • src/codegen/, python/pypto/backend/,
    python/pypto/runtime/builtins/collectives/*/templates/: generated
    orchestration and kernels name TaskTensor instead of ChipTensor. simpler
    refactor(codegen): dedup and split pto_ops_common by op category #1974 split the fused type: the 72-byte ChipTensor is now only the argument
    as it arrives at the boundary, while the 128-byte descriptor — the old
    ChipTensor field-for-field — is each runtime's own simpler::tmr::Tensor /
    simpler::hbg::Tensor. orch_args.tensor(i).ref() and
    TaskOutputTensors::get_ref() return that type, and the payload a kernel
    reads holds it. TaskTensor is the alias each runtime's tensor.h shim
    defines for its own type; pypto compiles against both runtime flavours, so
    naming simpler::tmr::Tensor outright would break host_build_graph.
    Orchestration gains #include "tensor.h" because the shim sits first on that
    include path and orchestration_api.h does not reach it. The host-side Python
    boundary (task_interface.py, tensor_arg.py, device_tensor.py) keeps
    ChipTensor, which is still exactly what it builds.
  • python/pypto/ir/op/tensor_ops.py, python/pypto/language/op/tensor_ops.py,
    src/ir/op/tensor_ops/memory.cpp, src/codegen/tensor_op_codegen.cpp:
    breaking — init_value on tensor.create is refused, not ignored.
    simpler [Feature] Add MX (MXFP8/MXFP4) DSL ops — matmul_mx, tget_scale_addr, tquant/tdequant — the only gap blocking MX kernels #1975 removed the create-info fill from tensormap_and_ringbuffer
    (host_build_graph lost it in feat(backend): enable bf16 atomic-add on A2/A3, broaden atomic dtype tests #1930, so all four variants now agree), and no
    orchestration-side replacement exists: the host orchestrator cannot store to
    the GM-heap device address. The kwarg stays in both signatures so a caller
    gets the migration rather than a bare TypeError, and .set_attr<double> is
    dropped from the op schema so the parser, the .pto deserializer, and
    C++-built IR are gated too. Silently dropping the request was the alternative
    and would have handed the consuming kernel uninitialized memory.
  • python/pypto/runtime/{runner,worker,distributed_runner}.py,
    docs/**/05-runtime-ring-sizing.md, docs/**/user/{performance/05-memory, tutorials/05-scheduling-tuning}.md: PTO2_RING_TASK_WINDOW / _HEAP /
    _DEP_POOL are retired by [RFC] Pluggable DSA Memory-Planning Solver + PyPTO Adapter #1980 — the runtime warns once per bind if one is
    exported. The documented fallback chain loses that tier, so RunConfig
    overrides now fall straight through to the compile-time default.
  • docs/**/02-error-handling.md: the "user-supplied kwarg value" example moved
    from the removed tensor.create init_value to tensor.assemble's atomic.

Migration

pl.create_tensor(shape, dtype, init_value=v) has no drop-in replacement. Seed
the buffer with a kernel that writes it, then order every reader after that
kernel with an explicit dependency (pl.submit(..., deps=[seed_tid]) or
pl.at(..., deps=[seed_tid])) — the pattern simpler #1922 established for the
DeepSeek-V4 decode buffers. pl.full is unaffected and remains the supported
way to get a filled tensor; it is a separate op that materializes its constant
through a kernel.

How the adaptation was bounded

Name-level sweeps found the first two changes and could not have found the
third. Grepping for PTO2 finds the identifiers but not the renamed headers,
which are plain #include string literals; extracting every #include and
every .member( pypto emits and checking each against the new runtime tree
finds those, and shows rt_orch_profile_now /
rt_orch_profile_add_dynamic_dep_vector are absent from simpler — though they
were absent at the old pin too, so they are pre-existing and out of scope here.

But ChipTensor, add_input and add_output all still exist; only the type
relationship between them changed, which no name check can see. Worse, the two
halves failed differently: orchestration failed loudly, because a reference
cannot bind across the two types, while __gm__ ChipTensor* over a payload
element still compiles in a kernel and reads owner_task_id's bytes as
start_offset — silent corruption, no diagnostic.

The check that sees both is compiling the output. A generated orchestration
source now type-checks under g++-15 -fsyntax-only against all four
runtime × arch include paths, and reverting TaskTensor to ChipTensor
reproduces this PR's earlier CI error verbatim. That is the evidence behind the
adaptation being complete, not the greps.

ScopeMode's enumerators, the TaskOutputTensors / ChipTaskArgs /
TensorCreateInfo shapes, and every other emitted member (add_output,
get_ref, task_id, set_dependencies, set_predicate,
set_require_sync_start, set_allow_early_resolve, add_no_dep, add_scalar,
add_tensor, launch_spec.*) survive the range unchanged. The simpler Python
surface pypto imports is intact; task_interface.py only gains
DeviceMemoryInfo and TaskHandle.

Verification

  • pytest tests/ut/ — 10377 passed, 8 skipped, 2 xfailed. Run inside the push
    transaction, bound to the pushed commit.
  • pytest tests/ut/codegen tests/ut/runtime/test_run_config.py tests/ut/ir/transforms/test_classify_iter_arg_carry.py tests/ut/ir/operators/test_array_ops.py — 1028 passed, 2 skipped
  • ctest — 1/1 passed
  • Generated orchestration type-checked with g++-15 -fsyntax-only against
    {tensormap_and_ringbuffer,host_build_graph} × {a2a3,a5} — all four clean
  • tests/lint/check_*.py (all twelve) — clean
  • ruff check + ruff format --check + pyright on the changed files — clean.
    ruff 0.16.0 was substituted for the pinned 0.14.8, which is not installed on
    this machine; two assertions were restructured so neither version needs to
    wrap them.
  • One local-only unit-test failure was deselected inside the transaction:
    test_symlinked_import_path_still_names_the_caller spawns a subprocess with a
    replaced PYTHONPATH, which drops the shim this linked worktree needs to
    bypass an editable install pointing at the main checkout. It resolves the main
    checkout's pypto rather than this branch's and does not reproduce in CI.
  • No device run. The shared card pool was not available to this change, so
    the pure-output initialization behaviour that simpler [Feature] Add MX (MXFP8/MXFP4) DSL ops — matmul_mx, tget_scale_addr, tquant/tdequant — the only gap blocking MX kernels #1975 touches is left
    for CI to exercise.

Known blocker: pypto-lib needs the same migration

pypto-lib-model is red and stays red on re-run — deterministically, on two
different devices, at the same task boundary (completed=15/285) and the same
faulting pc. It is not a flake and not fixable from this repository.

Qwen3-14B's hand-written attention kernels carry their own compat shim,
models/qwen3_14b/kernels/paged_attention_cce/kernel/runtime_tensor_compat.hpp:

#if __has_include("task_interface/buffer.h")
using PyPTORuntimeTensor = ChipTensor;
#else
using PyPTORuntimeTensor = Tensor;
#endif

That header still exists after this bump, so the shim keeps selecting
ChipTensor — which simpler #1974 redefined from the 128-byte payload
descriptor to the 72-byte boundary argument. The kernel then reads
owner_task_id's bytes as start_offset and garbage as shapes / strides,
which surfaces on device as fftsplus aivector error followed by
sub_class=S1:running-stalled. This is the silent half of the ChipTensor
split: the kernel path still compiles, so nothing catches it before the card.

The fix belongs in pypto-lib — select TaskTensor, the alias each runtime's
tensor.h shim defines for its own 128-byte type. hw-native-sys/pypto-lib#1052
does that, and must land before this pin can go green. Every other check on this
PR passes, including all four other device suites.

@coderabbitai

coderabbitai Bot commented Aug 26, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 125 files, which is 25 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: bd5ffb67-28f1-4647-8456-63f480c2bdda

📥 Commits

Reviewing files that changed from the base of the PR and between 4b01d98 and 80d32ca.

📒 Files selected for processing (125)
  • .claude/rules/pass-doc-ordering.md
  • docs/en/dev/00-ecosystem.md
  • docs/en/dev/01-compile-profiling.md
  • docs/en/dev/02-error-handling.md
  • docs/en/dev/05-runtime-ring-sizing.md
  • docs/en/dev/codegen/00-pto_codegen.md
  • docs/en/dev/codegen/01-orchestration_codegen.md
  • docs/en/dev/ir/01-hierarchy.md
  • docs/en/dev/ir/02-types.md
  • docs/en/dev/ir/05-operators.md
  • docs/en/dev/language/01-statements.md
  • docs/en/dev/language/02-manual_dependencies.md
  • docs/en/dev/passes/00-pass_manager.md
  • docs/en/dev/passes/44-materialize_runtime_scopes.md
  • docs/en/dev/passes/45-classify_iter_arg_carry.md
  • docs/en/dev/passes/99-verifier.md
  • docs/en/dev/passes/index.md
  • docs/en/dev/passes/loop-carried-dep-compression.md
  • docs/en/user/performance/05-memory.md
  • docs/en/user/tasks/01-scopes.md
  • docs/en/user/tutorials/05-scheduling-tuning.md
  • docs/zh/dev/00-ecosystem.md
  • docs/zh/dev/01-compile-profiling.md
  • docs/zh/dev/02-error-handling.md
  • docs/zh/dev/05-runtime-ring-sizing.md
  • docs/zh/dev/codegen/00-pto_codegen.md
  • docs/zh/dev/codegen/01-orchestration_codegen.md
  • docs/zh/dev/ir/01-hierarchy.md
  • docs/zh/dev/ir/02-types.md
  • docs/zh/dev/ir/05-operators.md
  • docs/zh/dev/language/01-statements.md
  • docs/zh/dev/language/02-manual_dependencies.md
  • docs/zh/dev/passes/00-pass_manager.md
  • docs/zh/dev/passes/44-materialize_runtime_scopes.md
  • docs/zh/dev/passes/45-classify_iter_arg_carry.md
  • docs/zh/dev/passes/99-verifier.md
  • docs/zh/dev/passes/index.md
  • docs/zh/dev/passes/loop-carried-dep-compression.md
  • docs/zh/user/performance/05-memory.md
  • docs/zh/user/tasks/01-scopes.md
  • docs/zh/user/tutorials/05-scheduling-tuning.md
  • include/pypto/codegen/orchestration/orchestration_codegen.h
  • include/pypto/core/dtype.h
  • include/pypto/ir/expr.h
  • include/pypto/ir/stmt.h
  • include/pypto/ir/transforms/ir_property.h
  • include/pypto/ir/transforms/pass_properties.h
  • include/pypto/ir/transforms/passes.h
  • include/pypto/ir/transforms/utils/transform_utils.h
  • include/pypto/ir/verifier/verifier.h
  • python/bindings/modules/codegen.cpp
  • python/bindings/modules/ir.cpp
  • python/bindings/modules/passes.cpp
  • python/pypto/backend/_ptoas_preprocess.py
  • python/pypto/backend/pto_backend.py
  • python/pypto/ir/directions.py
  • python/pypto/ir/op/system_ops.py
  • python/pypto/ir/op/tensor_ops.py
  • python/pypto/ir/pass_manager.py
  • python/pypto/jit/decorator.py
  • python/pypto/jit/specializer.py
  • python/pypto/language/op/tensor_ops.py
  • python/pypto/language/parser/ast_parser.py
  • python/pypto/language/parser/decorator.py
  • python/pypto/language/scope.py
  • python/pypto/pypto_core/codegen.pyi
  • python/pypto/pypto_core/ir.pyi
  • python/pypto/pypto_core/passes.pyi
  • python/pypto/runtime/builtins/collectives/all_to_all/templates/entry.cpp.in
  • python/pypto/runtime/builtins/collectives/all_to_all/templates/kernel.cpp.in
  • python/pypto/runtime/builtins/collectives/all_to_all_v/templates/entry.cpp.in
  • python/pypto/runtime/builtins/collectives/all_to_all_v/templates/kernel.cpp.in
  • python/pypto/runtime/builtins/collectives/allgather/templates/entry.cpp.in
  • python/pypto/runtime/builtins/collectives/allgather/templates/kernel.cpp.in
  • python/pypto/runtime/builtins/collectives/allreduce/templates/entry.cpp.in
  • python/pypto/runtime/builtins/collectives/allreduce/templates/kernel.cpp.in
  • python/pypto/runtime/builtins/collectives/allreduce_ring/templates/entry.cpp.in
  • python/pypto/runtime/builtins/collectives/allreduce_ring/templates/kernel.cpp.in
  • python/pypto/runtime/builtins/collectives/barrier/templates/entry.cpp.in
  • python/pypto/runtime/builtins/collectives/barrier/templates/kernel.cpp.in
  • python/pypto/runtime/builtins/collectives/broadcast/templates/entry.cpp.in
  • python/pypto/runtime/builtins/collectives/broadcast/templates/kernel.cpp.in
  • python/pypto/runtime/builtins/collectives/reduce_scatter/templates/entry.cpp.in
  • python/pypto/runtime/builtins/collectives/reduce_scatter/templates/kernel.cpp.in
  • python/pypto/runtime/device_runner.py
  • python/pypto/runtime/distributed_runner.py
  • python/pypto/runtime/execute_artifact.py
  • python/pypto/runtime/runner.py
  • python/pypto/runtime/worker.py
  • runtime
  • src/codegen/array_op_codegen.cpp
  • src/codegen/orchestration/orchestration_analysis.cpp
  • src/codegen/orchestration/orchestration_codegen.cpp
  • src/codegen/tensor_op_codegen.cpp
  • src/ir/op/sync_ops/task.cpp
  • src/ir/op/tensor_ops/memory.cpp
  • src/ir/op/tensor_ops/transform.cpp
  • src/ir/serialization/type_deserializers.cpp
  • src/ir/transforms/classify_iter_arg_carry_pass.cpp
  • src/ir/transforms/materialize_runtime_scopes_pass.cpp
  • src/ir/type.cpp
  • src/ir/verifier/verify_runtime_scopes_materialized.cpp
  • tests/st/conftest.py
  • tests/st/harness/core/test_runner.py
  • tests/st/runtime/control_flow/test_dyn_orch_shape.py
  • tests/st/runtime/cross_core/test_spmd_dynamic_gm_pipe.py
  • tests/st/runtime/external_kernel/kernels/aiv/spmd_write.cpp
  • tests/st/runtime/ops/test_trans.py
  • tests/st/runtime/scheduling/test_manual_scope_pipeline.py
  • tests/st/runtime/scheduling/test_pl_at_deps_pipeline.py
  • tests/ut/codegen/_orchestration_codegen_common.py
  • tests/ut/codegen/test_array_codegen.py
  • tests/ut/codegen/test_orchestration_codegen.py
  • tests/ut/codegen/test_orchestration_codegen_more.py
  • tests/ut/codegen/test_orchestration_manual_scope.py
  • tests/ut/codegen/test_orchestration_misc.py
  • tests/ut/codegen/test_orchestration_returned_param_map.py
  • tests/ut/codegen/test_orchestration_task_deps.py
  • tests/ut/codegen/test_orchestration_tensor_rw.py
  • tests/ut/codegen/test_phase_fence_dep_compression.py
  • tests/ut/codegen/test_pto_codegen.py
  • tests/ut/codegen/test_spmd_scope_tid_codegen.py
  • tests/ut/ir/operators/test_array_ops.py
  • tests/ut/ir/transforms/test_classify_iter_arg_carry.py
  • tests/ut/runtime/test_run_config.py

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…ved API

## What

Bumps the `runtime` submodule `93adc386` → `799640e6` (69 commits) and adapts
pypto to the three pypto-facing changes in that range. `runtime/pto_isa.pin`
is unchanged at `cd4a3d3f`.

**1. The PTO2 name retirement is complete** (simpler hw-native-sys#1963/hw-native-sys#1966/hw-native-sys#1969/hw-native-sys#1980).
Every name pypto's orchestration codegen emitted is gone upstream:

| before | after |
| --- | --- |
| `PTO2TaskId` | `TaskId` |
| `PTO2_SCOPE` | `SIMPLER_SCOPE` |
| `PTO2ScopeMode` | `ScopeMode` |
| `PTO2OrchestrationConfig` | `OrchestrationConfig` |
| `PTO2_ERROR_ASYNC_*` | `SIMPLER_ERROR_ASYNC_*` |
| `#include "pto_orchestration_api.h"` | `#include "orchestration_api.h"` |
| `#include "pto_async_kernel_api.h"` | `#include "async_kernel_api.h"` |

Three of the five are prefix strips; `PTO2_SCOPE` and the error codes take
`SIMPLER_` because a bare `SCOPE(` would expand too eagerly and the status
codes share a band with the host-side C API. The header renames reach the
eight `collectives/*/templates/entry.cpp.in` files as well as
`orchestration_codegen.cpp`.

**2. `TensorCreateInfo::set_initial_value` is gone** (simpler hw-native-sys#1975 for
`tensormap_and_ringbuffer`; `host_build_graph` lost it in hw-native-sys#1930, so all four
runtime variants now agree). pypto lowered `pl.create_tensor(..., init_value=)`
to exactly that call, and no orchestration-side replacement exists — the host
orchestrator cannot store to the GM-heap device address, which is why upstream
dropped the fill.

**Breaking change.** The kwarg is refused rather than ignored. It stays in both
signatures so a caller gets the migration instead of a bare `TypeError`, and
`ValueError` names the replacement: seed the buffer with a kernel, then order
every reader after it with an explicit dependency. `.set_attr<double>` is
dropped from the `tensor.create` schema so the parser, the `.pto` deserializer,
and C++-built IR are gated too, not just the Python entry point. Silently
dropping the request was the alternative and would have handed the consuming
kernel uninitialized memory.

`pl.full` is unaffected: it is a separate op that materializes its constant
through a kernel, so it remains the supported way to get a filled tensor.

**3. `ChipTensor` is no longer the type orchestration and kernels work in**
(simpler hw-native-sys#1974). That commit split the fused type in two: the 72-byte
`ChipTensor` is now only the argument as it arrives at the boundary, while the
128-byte descriptor — the old `ChipTensor` field-for-field — is each runtime's
own `simpler::tmr::Tensor` / `simpler::hbg::Tensor`. `orch_args.tensor(i).ref()`
and `TaskOutputTensors::get_ref()` return that type, and the payload a kernel
reads holds it.

Generated orchestration and kernels now name `TaskTensor`, the alias each
runtime's `tensor.h` shim defines for its own type. pypto compiles against both
runtime flavours, so naming `simpler::tmr::Tensor` outright would break
`host_build_graph`. Orchestration gains `#include "tensor.h"`: the shim sits
first on that include path, and `orchestration_api.h` does not reach it.

The two halves of this failed differently. Orchestration failed loudly — a
reference cannot bind across the two types. Kernels did not: `__gm__
ChipTensor*` over a payload element still compiles and reads
`owner_task_id`'s bytes as `start_offset`, so the break there is silent
corruption rather than a diagnostic.

**4. The process-wide ring env vars are retired** (hw-native-sys#1980). `PTO2_RING_TASK_WINDOW`
/ `PTO2_RING_HEAP` / `PTO2_RING_DEP_POOL` are no longer read — the runtime warns
once per bind if one is exported. `RunConfig` overrides now fall straight
through to the compile-time default with no tier in between, so the docstrings
and docs that described that tier are corrected rather than renamed.

## How the adaptation was bounded

Name-level sweeps found the first two changes and could not have found the
third. Grepping for `PTO2` finds the identifiers but not the renamed headers,
which are plain `#include` string literals; extracting every `#include` and
every `.member(` pypto emits and checking each against the new runtime tree
finds those, and confirms `rt_orch_profile_now` /
`rt_orch_profile_add_dynamic_dep_vector` are absent — though they were absent
at the old pin too, so they are pre-existing and out of scope here.

But `ChipTensor`, `add_input` and `add_output` all still *exist*; only the type
relationship between them changed, which no name check can see. The check that
does see it is compiling the output: a generated orchestration source now
type-checks under `g++-15 -fsyntax-only` against all four runtime x arch
include paths, and reverting `TaskTensor` to `ChipTensor` reproduces CI's exact
`invalid initialization of reference` error. That is the evidence behind this
adaptation being complete, not the greps.

## What did not change

`ScopeMode`'s enumerators, the `TaskOutputTensors` / `ChipTaskArgs` /
`TensorCreateInfo` shapes, and every emitted member (`add_output`, `get_ref`,
`task_id`, `set_dependencies`, `set_predicate`, `set_require_sync_start`,
`set_allow_early_resolve`, `add_no_dep`, `add_scalar`, `add_tensor`,
`launch_spec.*`) survive the range unchanged. The `simpler` Python surface
pypto imports — `Worker`, `CallConfig`, `ChipTensor`, `ChipStorageTaskArgs`,
`TaskArgs`, `Tensor`, `scalar_to_uint64`, `AccessMode`, `BackendKind`,
`mint_owner_instance_id`, `wrap_fork_inherited`, `KernelCompiler`,
`torch_interop`, `pto_isa`, `swimlane_converter`, `strace_timing` — is intact;
`task_interface.py` only gains `DeviceMemoryInfo` and `TaskHandle`.

## Validation

- `pytest tests/ut/` — 10377 passed, 8 skipped, 2 xfailed. One local-only
  failure, `test_symlinked_import_path_still_names_the_caller`: it spawns a
  subprocess with a replaced `PYTHONPATH`, which drops the shim this worktree
  needs to bypass the editable install pointing at the main checkout. It
  resolves the main checkout's `pypto`, not this branch's, and does not
  reproduce in CI.
- `ctest` — 1/1 passed
- Generated orchestration type-checked with `g++-15 -fsyntax-only` against
  `{tensormap_and_ringbuffer,host_build_graph}` x `{a2a3,a5}` — all four clean
- `ruff check` + `ruff format --check` + `pyright` on the changed files — clean.
  ruff 0.16.0 was substituted for the pinned 0.14.8, which is not installed
  here; two assertions were restructured so neither version needs to wrap them.
- `tests/lint/check_*.py` (all twelve) — clean
- No device run: the shared card pool is not available to this change, so the
  pure-output initialization behaviour that hw-native-sys#1975 touches is left for CI.
@lyfne123
lyfne123 force-pushed the chore/bump-runtime-799640e6 branch from af4d37a to 80d32ca Compare August 26, 2026 06:37
@lyfne123
lyfne123 merged commit 4fde258 into hw-native-sys:main Aug 27, 2026
28 of 31 checks passed
lyfne123 added a commit to lyfne123/pypto-lib that referenced this pull request Aug 27, 2026
Simpler #1974 split the fused tensor type in two. `ChipTensor` kept the name
but became the 72-byte *argument* as it arrives at the boundary; the 128-byte
descriptor a kernel reads out of the task payload became each runtime's own
type — `simpler::tmr::Tensor` / `simpler::hbg::Tensor`, aliased `TaskTensor` by
the per-runtime `tensor.h` shim `runtime_tensor_compat.hpp` already includes.

`task_interface/buffer.h` still exists after that split, so this file's probe
kept selecting `ChipTensor` and the Qwen3-14B attention kernels started reading
the wrong struct: `owner_task_id`'s bytes as `start_offset`, and garbage as
`shapes` / `strides`.

Nothing caught it before the card. `__gm__ ChipTensor*` over a payload element
still compiles — the two types differ in layout, not in name — so the first
signal was on device, as `fftsplus aivector error` followed by
`sched_error_code=100 sub_class=S1:running-stalled`, deterministic at
`completed=15/285` on two different chips.

So the fix is two parts. The probe gains a newest-first arm keyed on the header
the #1974 shim itself pulls in to define `TaskTensor`, which is true exactly
when that alias exists. It is a version probe rather than a runtime selector:
both split headers live under `src/common` and arrive together, whichever
runtime is being built for. The three arms keep this source compilable against
all three ABIs, so it can land before PyPTO updates its runtime pin — the same
property the two-arm version was written for.

The second part is a `static_assert` on `sizeof(PyPTORuntimeTensor) == 128`.
The failure mode above is silent by construction, and a size check is what turns
the next such split back into a compile error instead of a device fault.

Verified by compiling the header against both pins with the include paths a
kernel build uses: Simpler 93adc386 (pre-split) selects `ChipTensor`, 799640e6
(post-split) selects `TaskTensor`, and both satisfy the assert. Forcing the
`ChipTensor` arm against 799640e6 fails the assert, so the guard is
load-bearing rather than decorative.

Needed by PyPTO's runtime bump to 799640e6 (hw-native-sys/pypto#2530), which is
where the device failure was found.
zhangqi-chen pushed a commit to hw-native-sys/pypto-lib that referenced this pull request Aug 27, 2026
…1052)

- Add a newest-first arm to the qwen3_14b paged_attention_cce runtime
  tensor probe: select TaskTensor when tensormap_and_ringbuffer/tensor.h
  is present, leaving the task_interface/buffer.h ChipTensor arm and the
  bare Tensor arm intact so all three Simpler ABIs still compile
- Guard the selection with static_assert(sizeof(PyPTORuntimeTensor) ==
  128), turning a future descriptor split back into a compile error
  instead of a device fault

Simpler #1974 split the fused tensor type: ChipTensor kept the name but
became the 72-byte argument as it arrives at the boundary, while the
128-byte descriptor a kernel reads out of the task payload became each
runtime's own type (simpler::tmr::Tensor / simpler::hbg::Tensor),
aliased TaskTensor by the per-runtime tensor.h shim. Naming ChipTensor
against a post-split runtime still compiles, so the kernel silently read
owner_task_id's bytes as start_offset and garbage as shapes/strides,
surfacing on device as an fftsplus aivector error with
sched_error_code=100 at completed=15/285. The fix is needed by PyPTO's
runtime bump to 799640e6 (hw-native-sys/pypto#2530); the three-arm probe
keeps this source compilable against the current pin, so it can land
first.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60. InitMemRef
materializes missing compiler-owned scratch for tile.ci / narrowing cast /
sort32, preserves caller tmp on sel/sels/prelu, gates TSEL lhs/rhs no-alias
to A2/A3, and adds static-view bridges so level-3 PTOAS accepts explicit-tmp
forms.

Keep the pypto-lib prefill CSA integration fixture aligned with its
in-place output ABI and INT8 quantization tolerance.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60. InitMemRef
materializes missing compiler-owned scratch for tile.ci / narrowing cast /
sort32, preserves caller tmp on sel/sels/prelu, gates TSEL lhs/rhs no-alias
to A2/A3, and adds static-view bridges so level-3 PTOAS accepts explicit-tmp
forms.
Hzfengsy pushed a commit that referenced this pull request Aug 27, 2026
#2541)

## Summary

Adds `DistributedWorker.device_memory_info(worker_id=0) -> tuple[int, int]`,
returning free and total device HBM for the card that logical chip worker runs
on. It forwards to the `Worker(level=3)` facade `DistributedWorker` already
owns.

Serving integrations need this to size a KV cache. Today they either call
`torch.npu.mem_get_info` — pulling in `torch-npu` for a single query — or reach
past `DistributedWorker` into the simpler `Worker` underneath it.

The underlying query landed in simpler #2011 and reached this repository with
the runtime bump in #2530, which is what unblocked this.

## Why it is a separate method from `committed_device_memory`

They answer different questions. `committed_device_memory` reports what *this
worker's* allocator has committed; `device_memory_info` is the whole card as the
driver sees it. Another process, another worker, or the driver itself moves
`free_bytes` without moving the committed total, so sizing an allocation against
the committed figure ignores every other tenant on the card.

That also decides the error behaviour, where this deliberately diverges from its
neighbour: `committed_device_memory` answers `0` when it has no worker to ask,
and this must not. A caller sizing a cache from a fabricated `(0, 0)`
under-allocates silently instead of failing — a worse outcome than the
exception. The underlying error propagates unchanged, including the
`NotImplementedError` simulator backends raise. The divergence is commented at
the call site so it does not later get "tidied up" into consistency.

The tuple is normalized to Python ints rather than returned as simpler's
`DeviceMemoryInfo`, since handing back that struct would leak a simpler type
through the facade — the coupling this method exists to remove.

## Changes

- `python/pypto/runtime/distributed_runner.py`: the new method, beside
  `committed_device_memory`.
- `tests/ut/runtime/test_distributed_worker.py`: `TestDeviceMemoryInfo`, seven
  cases on the existing mocked `Worker(level=3)` fixture — no card needed.
- `docs/{en,zh}/user/distributed/03-execution.md`: the method table gains this
  method, and `committed_device_memory` alongside it. That one was missing, and
  without it the new row has nothing to be distinct from.

## Verification

- `pytest tests/ut/runtime/test_distributed_worker.py` — 189 passed
- `pytest tests/ut/` — 10426 passed, 8 skipped, 2 xfailed
- `ruff check` + `ruff format --check` + `pyright` on the changed files — clean
- `tests/lint/check_*.py` — clean

Both pytest runs and the lint scripts ran inside the push transaction, bound to
the pushed commit.

Each test was checked against a mutated implementation to confirm it is
load-bearing: dropping the `int()` normalization, hard-coding `worker_id=0`,
dropping the open guard, and softening failures to `(0, 0)` each fail exactly
the test that covers them, and the restored implementation passes all seven.

Not run on device: every path here is a forward to a mocked `Worker`, and the
device-side query is simpler's own, covered by simpler #2011.

Closes #2413
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60. InitMemRef
materializes missing compiler-owned scratch for tile.ci / narrowing cast /
sort32, preserves caller tmp on sel/sels/prelu, gates TSEL lhs/rhs no-alias
to A2/A3, and adds static-view bridges so level-3 PTOAS accepts explicit-tmp
forms.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60. InitMemRef
materializes missing compiler-owned scratch for tile.ci / narrowing cast /
sort32, preserves caller tmp on sel/sels/prelu, gates TSEL lhs/rhs no-alias
to A2/A3, and adds static-view bridges so level-3 PTOAS accepts explicit-tmp
forms.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60. InitMemRef
materializes missing compiler-owned scratch for tile.ci / narrowing cast /
sort32, preserves caller tmp on sel/sels/prelu, gates TSEL lhs/rhs no-alias
to A2/A3, and adds static-view bridges so level-3 PTOAS accepts explicit-tmp
forms.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60. InitMemRef
materializes missing compiler-owned scratch for tile.ci / narrowing cast /
sort32, preserves caller tmp on sel/sels/prelu, gates TSEL lhs/rhs no-alias
to A2/A3, and adds static-view bridges so level-3 PTOAS accepts explicit-tmp
forms.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60. InitMemRef
materializes missing compiler-owned scratch for tile.ci / narrowing cast /
sort32, preserves caller tmp on sel/sels/prelu, gates TSEL lhs/rhs no-alias
to A2/A3, and adds static-view bridges so level-3 PTOAS accepts explicit-tmp
forms.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60. InitMemRef
materializes missing compiler-owned scratch for tile.ci / narrowing cast /
sort32, preserves caller tmp on sel/sels/prelu, gates TSEL lhs/rhs no-alias
to A2/A3, and adds static-view bridges so level-3 PTOAS accepts explicit-tmp
forms.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60. InitMemRef
materializes missing compiler-owned scratch for tile.ci / narrowing cast /
sort32, preserves caller tmp on sel/sels/prelu, gates TSEL lhs/rhs no-alias
to A2/A3, and adds static-view bridges so level-3 PTOAS accepts explicit-tmp
forms.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60. InitMemRef
materializes missing compiler-owned scratch for tile.ci / narrowing cast /
sort32, preserves caller tmp on sel/sels/prelu, gates TSEL lhs/rhs no-alias
to A2/A3, and adds static-view bridges so level-3 PTOAS accepts explicit-tmp
forms.
Hzfengsy pushed a commit that referenced this pull request Aug 27, 2026
…2544)

## Summary

Finishes #2470. Its first reproducer — an accumulator seeded by `pl.matmul` itself — was fixed by #2474, and #2531 fixed the C2V push plus the seed `AutoTileMatmulL0` synthesizes when it splits K. The reproducer in the issue's comments is the one both left: an accumulator seeded by **`pl.create_tensor` before the K-loop**, which is how the model kernel spells it.

```python
acc = pl.create_tensor([1, M_TILE, N_TILE], dtype=pl.INT32)      # full height
for k0 in pl.pipeline(0, K, K_TILE, stage=2):
    xk = pl.slice(x, [M_TILE, K_TILE], [m0, k0], valid_shape=[v, K_TILE])   # runtime v
    if k0 == 0:
        acc = pl.matmul(xk, wk, b_trans=True, out_dtype=pl.INT32)
    else:
        acc = pl.matmul_acc(acc, xk, wk, b_trans=True)
y[m0 : m0 + M_TILE, :] = pl.reshape(acc, [M_TILE, N_TILE])
```

**A loop carry is typed from its init value alone.** `ConvertToSSA` mints the `IterArg` from the reaching definition before the loop, `ConvertTensorToTileOps` re-mints it from the converted seed, and both force the loop's `return_var` back to that same type. The yields are never consulted, so the narrowing every matmul in the body produced dies at the loop boundary:

```text
acc__tile      : Tile[[64, 256], INT32]                                <- pl.create_tensor seed
  iter_arg     : Tile[[64, 256], INT32]                                <- typed from the seed
  yield        : Tile[[64, 256], INT32, Acc, valid=[min(v,64), 256], compact]
  return_var   : Tile[[64, 256], INT32]                                <- forced back to the iter_arg
```

`mad` takes M from the L0A operand's valid rows and lays the product out in L0C at an N-fractal stride of `ceil(M/16)*16` (pto-isa `TMatmul.hpp`), so a reader that believes the seed's height walks the buffer at the physical row pitch: with a 64-row box valid to 16, store fractal `j` picks up matmul fractal `4j` and only the first 16 columns of each block survive — **75264 of 131072 elements wrong** in the issue's own device run. Since #2531 it no longer ships silently; the kernel simply does not build:

```
[1] ERROR - AccCompactValid
  Message: 'tile.matmul_acc' accumulates pl.min(v__ssa_v0, 64) valid rows into an
  accumulator that is not compact (function 'mm_ct').
```

## Changes

- **The seed is re-declared at the extent the yields prove.** The seed is the only place the rest of the pipeline reads a carry's type from, so narrowing it lets the existing deducers carry the right type through the body on their own — no invented types. The form is `tile.create(compact=True)` + `tile.set_validshape`, exactly what `AutoTileMatmulL0` builds when it splits K; that builder moves into `acc_init::BuildNarrowedAccInit` (new `utils/acc_init_builder.h`) and both callers now share it, so stamper and re-declarer cannot drift on the compact rule.

- **The repair runs inside the two passes that create the mismatch**, not as a pass of its own. `ConvertTensorToTileOps` narrows a **2D** seed the moment `tensor.matmul` becomes `tile.matmul`; `FlattenTileNdTo2D` narrows an **ND** seed when `tile.batch_matmul` is unrolled into 2D matmuls. Repairing it at the source is what keeps the pipeline verifiable — measured with the repair disabled, each pass otherwise publishes a carry its own `TypeCheck` diagnostic rejects on the spot:

  ```
  Valid shape dimension mismatch in ForStmt: declared iter_arg[0] dimension[0] = 64,
  but yield value[0] dimension[0] = pl.min(v__ssa_v0, 64)
  ```

  That report never reaches production today only because `TypeChecked` is verified once, at `pipeline_input`, where `tensor.matmul` has not yet narrowed anything.

- **An identity `tile.reshape` now keeps its source's layout triple and memory space.** It re-derived the layout from the shape, which yields the space-agnostic flat default; `NormalizeImplicitTileView` rescues that only for a view that *collapses*, and an Acc box that is narrowed, padded or `compact` never does. The flat layout therefore stuck, and the store between the loop and GM read L0C as a plain row-major buffer. This is the `tile.reshape` half of the open question in #2470's comments — the identity case, which is the one this chain hits; a non-identity reshape of an explicit-view tile is still re-derived and still deserves the broader decision about who owns layout for such tiles.

Scope is deliberately narrow, and each limit is a case where widening it would risk changing what a program computes rather than fixing anything:

| Limit | Why |
| --- | --- |
| Acc carries only | L0C is where a stale extent changes the *stride* a reader uses. A Vec seed may hold bytes the first iteration is entitled to read at full height. |
| Seeds defined by `tile.create` only | That is what `pl.create_tensor` lowers to; a loaded tile or a parameter may carry bytes whose layout this must not re-interpret. |
| Provable narrowing only | A yield extent is adopted when it is provably `<=` the declared one, or when the init still fills its physical box (every `valid_shape` is bounded by that box, so a dynamic extent is already trusted to fit). An init that is *itself* already narrowed is never widened on an undecidable relation. |
| Only where the pitches would differ | `AccPitchesCoincide`, shared with the `AccCompactValid` verifier. A single-fractal-block `[16, N]` accumulator packs to its physical rows whatever its valid rows, so it keeps the exact form it has today — which is what pypto-lib's `qkv_proj_rope` projections are. |
| Only where the extent is visible before the loop | The re-declared seed sits there, and the common spelling puts the row count next to the slice it bounds, *inside* the body (`kv_rows = pl.min(KV_M_TILE, t_dim - t0)`). Hoisting that leaves codegen with a symbol it cannot bind. Such a carry is declined; where its pitches genuinely differ, `AccCompactValid` then reports it as a compile error rather than letting it corrupt data. Moving the computation instead would need the extent proven loop-invariant — a larger change than this repair. |

## Validation

Ascend910B backend, `--codegen-only`. The store now reads the accumulator at the pitch `mad` wrote at, and the destination follows the tile's runtime rows so `TStoreAccNz2nd`'s `validRow == gShape3` precondition holds:

```mlir
%acc2d__tile = pto.alloc_tile ... valid_row = %18 ...
    !pto.tile_buf<loc=acc, rows=64, cols=256, blayout=col_major, slayout=row_major, fractal=1024, compact=1>
pto.tstore ins(%acc2d__tile : ...compact=1) outs(%y__ssa_v0_pview : !pto.partition_tensor_view<?x256xi32>)
```

- **11 new UTs** (`tests/ut/ir/transforms/test_narrow_loop_carry_valid_shape.py`): both seed spellings repaired in their own pass, the re-declared form, the full-height and Vec carries that must stay untouched, the whole Default pipeline with verification on for both spellings, the emitted `pto.tstore`, and the two declined shapes — a `[16, N]` accumulator (which also compiles through to PTO codegen, where the first push of this PR reproduced CI's `cannot materialize symbol` failure verbatim) and a loop-local extent.
- **1 new device case** in `tests/st/runtime/cross_core/test_c2v_narrowed_acc_epilogue.py` — the hand-written carry, alongside that file's existing #2510 and #2470 readers.
- Every one of them was confirmed against a build with the repair disabled: the transform UTs fail on the type mismatch, and the ST case does not compile at all (`AccCompactValid`).
- `tests/ut`: **10490 passed**, 1 pre-existing environment failure (`test_symlinked_import_path_still_names_the_caller`, whose subprocess is redirected to the main checkout by this machine's editable install; it fails on an unmodified tree too).
- All `tests/lint` checks pass.

## Reviewer notes

- **The device case ran on a2a3 in CI and passed**, alongside the two this file already had:

  ```
  test_c2v_narrowed_acc_epilogue.py::TestNarrowedAccEpilogue::test_gm_stored_accumulator_carried_by_a_hand_written_loop[a2a3] PASSED
  ```

  It could not be run from my checkout: this environment's `simpler` predates the runtime bump in #2530 (`ImportError: cannot import name 'DeviceMemoryInfo' from '_task_interface'`), which blocks every ST test under `tests/st/runtime` here, including the two pre-existing ones. Locally it was compiled through the full pipeline instead, with its cube `pto.tstore` verified to be `compact=1` into a `16x128` view.
- The `acc_init` extraction preserves `AutoTileMatmulL0`'s behaviour exactly, including the static-full-rectangle short-circuit that keeps the historical single-`tile.create` form byte-for-byte.
- With this and #2531, the `MM_ROW_TILE` workaround in pypto-lib's `models/deepseek_v4_flash_mtp/expert_routed.py` should no longer be needed for either shape.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60. InitMemRef
materializes missing compiler-owned scratch for tile.ci / narrowing cast /
sort32, preserves caller tmp on sel/sels/prelu, gates TSEL lhs/rhs no-alias
to A2/A3, and adds static-view bridges so level-3 PTOAS accepts explicit-tmp
forms.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60. InitMemRef
materializes missing compiler-owned scratch for tile.ci / narrowing cast /
sort32, preserves caller tmp on sel/sels/prelu, gates TSEL lhs/rhs no-alias
to A2/A3, and adds static-view bridges so level-3 PTOAS accepts explicit-tmp
forms.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60. InitMemRef
materializes missing compiler-owned scratch for tile.ci / narrowing cast /
sort32, preserves caller tmp on sel/sels/prelu, gates TSEL lhs/rhs no-alias
to A2/A3, and adds static-view bridges so level-3 PTOAS accepts explicit-tmp
forms.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60.

InitMemRef materializes missing compiler-owned level-3 scratch for tile.ci,
narrowing tile.cast, and tile.sort32 under PyPTO/DSA-RP planners;
explicit caller tmp on tile.sel / tile.sels / tile.prelu is preserved.
Document FP16->INT4 exclusion from TcvtNeedsLevel3Scratch (no PTOAS tmp).

Codegen adds static-view bridges (ci/tcvt/col_sum/sort32) so level-3 PTOAS
accepts explicit-tmp forms with static valid_shape. Revert incorrect MemoryReuse
A2/A3 tile.sel lhs/rhs no-alias; registry keeps forbid_output_alias(mask, tmp)
only. TSEL tmp geometry UINT32[1,16] on level3 backends via
BackendHandler::RequiresLevel3TmpScratch(); A5 keeps UINT8[1,32] in lowering.

Review follow-ups: named tcvt/ci constants; tcvt branch UT; ci/tcvt/col_sum
codegen UT; sort32 keyword-only tmp; strengthened ci alias UT.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60.

InitMemRef materializes missing compiler-owned level-3 scratch for tile.ci,
narrowing tile.cast, and tile.sort32 under PyPTO/DSA-RP planners;
explicit caller tmp on tile.sel / tile.sels / tile.prelu is preserved.
Document FP16->INT4 exclusion from TcvtNeedsLevel3Scratch (no PTOAS tmp).

Codegen adds static-view bridges (ci/tcvt/col_sum/sort32) so level-3 PTOAS
accepts explicit-tmp forms with static valid_shape. Revert incorrect MemoryReuse
A2/A3 tile.sel lhs/rhs no-alias; registry keeps forbid_output_alias(mask, tmp)
only. TSEL tmp geometry UINT32[1,16] on level3 backends via
BackendHandler::RequiresLevel3TmpScratch(); A5 keeps UINT8[1,32] in lowering.

Review follow-ups: named tcvt/ci constants; tcvt branch UT; ci/tcvt/col_sum
codegen UT; sort32 keyword-only tmp; strengthened ci alias UT.

Co-authored-by: Cursor <cursoragent@cursor.com>
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60.

InitMemRef materializes missing compiler-owned level-3 scratch for tile.ci,
narrowing tile.cast, and tile.sort32 under PyPTO/DSA-RP planners;
explicit caller tmp on tile.sel / tile.sels / tile.prelu is preserved.
Document FP16->INT4 exclusion from TcvtNeedsLevel3Scratch (no PTOAS tmp).

Codegen adds static-view bridges (ci/tcvt/col_sum/sort32) so level-3 PTOAS
accepts explicit-tmp forms with static valid_shape. Revert incorrect MemoryReuse
A2/A3 tile.sel lhs/rhs no-alias; registry keeps forbid_output_alias(mask, tmp)
only. TSEL tmp geometry UINT32[1,16] on level3 backends via
BackendHandler::RequiresLevel3TmpScratch(); A5 keeps UINT8[1,32] in lowering.

Review follow-ups: named tcvt/ci constants; tcvt branch UT; ci/tcvt/col_sum
codegen UT; sort32 keyword-only tmp; strengthened ci alias UT.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60.

InitMemRef materializes missing compiler-owned level-3 scratch for tile.ci,
narrowing tile.cast, and tile.sort32 under PyPTO/DSA-RP planners;
explicit caller tmp on tile.sel / tile.sels / tile.prelu is preserved.
Document FP16->INT4 exclusion from TcvtNeedsLevel3Scratch (no PTOAS tmp).

Codegen adds static-view bridges (ci/tcvt/col_sum/sort32) so level-3 PTOAS
accepts explicit-tmp forms with static valid_shape. Revert incorrect MemoryReuse
A2/A3 tile.sel lhs/rhs no-alias; registry keeps forbid_output_alias(mask, tmp)
only. TSEL tmp geometry UINT32[1,16] on level3 backends via
BackendHandler::RequiresLevel3TmpScratch(); A5 keeps UINT8[1,32] in lowering.

Review follow-ups: named tcvt/ci constants; tcvt branch UT; ci/tcvt/col_sum
codegen UT; sort32 keyword-only tmp; strengthened ci alias UT.
yanghaoran29 added a commit to yanghaoran29/pypto that referenced this pull request Aug 27, 2026
Rebased onto latest main (includes hw-native-sys#2530). Pin runtime to simpler 0659e29
(merged hw-native-sys#2016, pto-isa be5ccb76). Bump toolchain PTOAS to v0.60.

InitMemRef materializes missing compiler-owned level-3 scratch for tile.ci,
narrowing tile.cast, and tile.sort32 under PyPTO/DSA-RP planners;
explicit caller tmp on tile.sel / tile.sels / tile.prelu is preserved.
Document FP16->INT4 exclusion from TcvtNeedsLevel3Scratch (no PTOAS tmp).

Codegen adds static-view bridges (ci/tcvt/col_sum/sort32) so level-3 PTOAS
accepts explicit-tmp forms with static valid_shape. Revert incorrect MemoryReuse
A2/A3 tile.sel lhs/rhs no-alias; registry keeps forbid_output_alias(mask, tmp)
only. TSEL tmp geometry UINT32[1,16] on level3 backends via
BackendHandler::RequiresLevel3TmpScratch(); A5 keeps UINT8[1,32] in lowering.

Review follow-ups: named tcvt/ci constants; tcvt branch UT; ci/tcvt/col_sum
codegen UT; sort32 keyword-only tmp; strengthened ci alias UT; reverted
AppendCastHop in LegalizeTileCast to inline hop loop.
YunjiQin pushed a commit that referenced this pull request Aug 28, 2026
## Summary

Rebased onto latest `main` (includes #2530). This PR upgrades PyPTO to
**PTOAS v0.60** and pins the **runtime** submodule to simpler
**0659e29** (merged #2016; pto-isa **be5ccb76**).

### Toolchain coupling (not independently revertible)

Rolling back only `toolchain/versions.env` will break codegen/planning.
The following are bound to v0.60 together:

- A2/A3 **level-3 explicit tmp** forms for `pto.tci`, narrowing
`pto.tcvt`, `pto.tsort32`
- **Static valid_shape** verification on explicit-tmp codegen paths
(ci/tcvt/col_sum/sort32 static-view bridges)
- **TSEL tmp geometry** UINT32 `[1, 16]` on A2/A3 (A5 retains ABI
operand but does not read tmp)
- Soft **syncall** ABI / **tfillpad** rename and related codegen
adjustments in this PR

Revert toolchain and codegen changes as one unit.

### InitMemRef (A2/A3 level-3 scratch)

Under `MemoryPlanner.PYPTO` or `DSA_RP` on A2/A3 only:

| Op | Behavior |
| --- | --- |
| `tile.ci` | Append FP32 scratch when tmp missing (width 192/448 by dst
dtype) |
| Narrowing `tile.cast` | Append i8 scratch sized by PTOAS v0.60
`makeTCvtTmpType` (FP32→INT16, FP16→INT16/INT8/UINT8) |
| `tile.sort32` | Append scratch when required by valid width/dtype |
| `tile.sel` / `tile.sels` / `tile.prelu` | **Preserve** explicit caller
tmp; InitMemRef does not replace |
| FP16→INT4 | **Excluded** from scratch set (native vconv path, no
level-3 tcvt tmp) |

PTOAS planner and A5 unchanged for compiler-owned scratch insertion.

### MemoryReuse

- `tile.ci`: `.forbid_output_alias(2)` — output must not alias compiler
scratch
- `tile.sel`: registry `forbid_output_alias(0,3)` only (mask + tmp);
**dead lhs/rhs may be reused** on A2/A3 and A5
- Reverted incorrect A2/A3-only lhs/rhs forbid in `ForbidAliasCollector`

### A2/A3 vs A5 — PTOAS constraints (summary)

See inline block comments at every arch branch in this PR. Highlights:

| Area | A2/A3 (level3) | A5 |
| --- | --- | --- |
| InitMemRef scratch | Materializes ci / narrowing cast / sort32 tmp |
Unchanged (PTOAS planner) |
| `tile.ci` | 3-arg + FP32 tmp; forbid dst alias tmp | 2-arg, no scratch
insert |
| Narrowing `tile.cast` | Explicit i8 tmp + static views | 1-arg tcvt |
| `tile.sort32` | Explicit tmp + static views when required | 2-arg
typical |
| `tile.sel` tmp | UINT32 [1,16] read as cmpmask scratch | ABI operand,
unread |
| `tile.sels` tmp | Written for scalar; no overlap mask/src | Unread;
may alias |
| `tile.prelu` tmp | UINT8 scratch, static view, active input | ABI
unread; dst may alias tmp |
| `tile.col_sum` binary | tmp + static view + isBinary | No static-view
bridge |

---

- Drop Flatten/Cast legalization scratch duplication
- Simplify `tensor.scatter` flat-index lowering (UINT32 `[1,16]` sel tmp
in scatter paths)
- Docs: `32-init_memref.md`, `34-memory_reuse.md` aligned with above

## Review responses (YunjiQin)

- **Blocking docs:** revert lhs/rhs MemoryReuse logic; docs already
correct at mask/tmp only
- **FP16→INT4:** excluded with comment + negative UT
- **UINT32[1,16] on A5:** verified unread ABI; docstrings clarified
- **Non-blocking:** named constants, tcvt branch UT, ci/tcvt/col_sum
codegen UT, sort32 `*, tmp=`, ci alias UT strengthened
- **Deferred:** legalize_tile_cast refactor revert, DRY EmitInsOuts,
sort32 FP16 ST

## Test plan

- [x] `tests/ut/ir/transforms/test_init_memref.py` — scratch matrix,
FP16→INT4 exclusion, tcvt head/tail/rows>255
- [x]
`tests/ut/ir/transforms/test_memory_reuse.py::TestForbidOutputAlias` —
ci/sel/sels/prelu alias guards
- [x] `tests/ut/codegen/test_pto_codegen_ops.py` — tsels/tprelu/tsort32
+ ci/tcvt/col_sum static-view
- [x] pre-commit (local, touched files)
- [x] pypto-lib model CI (local a2a3): prefill/decode csa·hca·swa + moe
- [ ] upstream CI

## Dependencies

- Runtime: simpler **0659e29** on top of #2530 API surface
- PTOAS: **v0.60** via `toolchain/versions.env`
YunjiQin pushed a commit that referenced this pull request Aug 28, 2026
…nCore composite (#2280)

## Summary

Replaces the **pull-model** engine of the ring allreduce on **both
rails** with a **TPUT push model** (remote write), enabling O(1)
`NeighborBarrier` on the HOST builtin and eliminating the pull-model NPU
memory-ordering gap.

- **HOST builtin** (`builtin.tensor.allreduce_ring`): reduce-scatter +
allgather converted from `TLOAD`/`TSTORE` pull to `pto::comm::TPUT` push
— `TPUT<AtomicAdd>` remote-accumulate for RS, non-atomic `TPUT` for AG.
Ordering is `pipe_barrier(PIPE_ALL)` around every transfer +
`dsb(DSB_DDR)` before `TNOTIFY` (mirrors the in-tree
allgather/all_to_all host builtins; not a GM fence). The O(P²)
`RoundBarrier` is replaced by the O(1) `NeighborBarrier` (notify/wait
the two ring neighbours only), which is NPU-safe because the TPUT write
pipeline orders the data ahead of the signal — the pull model could not
provide that.
- **InCore composite** (`LowerTensorRingAllReduceRule`): replaces
`pld.tile.remote_load` pulls with `pld.tile.put` pushes (non-atomic TPUT
+ local reduce, **preserving Sum/Max/Min/Prod**). Race-free per-subchunk
protocol: own-value read → ready barrier → push to right neighbour →
push-done barrier → local read+reduce+store; barrier credits stay 2 per
subchunk (signal shape unchanged). Ragged/arbitrary lengths and FP16 are
preserved via balanced segments + valid shapes, with the shared VEC
staging tile narrowed per transfer via `tile.set_validshape`.

## Requires PTOAS >= v0.55 (pypto pins v0.57)

**This PR depends on [PTOAS
v0.55](https://github.com/hw-native-sys/PTOAS/releases/tag/v0.55)**
(release:
[hw-native-sys/PTOAS#1069](hw-native-sys/PTOAS#1069),
fixed in [PR #1079](hw-native-sys/PTOAS#1079)).

The InCore composite's `pld.tile.put` transfers carry the **exact ragged
`valid_cols`** as the partition-view extent. PTOAS ≤ v0.54 rejects
dynamic partition-view shapes for `pto.comm.tput` (`'pto.comm.tput' op
expects dst to have a positive static shape`), so the pure push model
cannot compile below v0.55. The HOST builtin does not depend on this
(its kernel is hand-written), but the composite rail does.

The requirement is satisfied by the current pin: pypto now pins **PTOAS
v0.57** (via #2291). The PR is rebased onto current `main` (2026-08-26,
was 76 commits behind; re-rebased twice 2026-08-27 — first onto the
#2530 runtime bump adopting the `ChipTensor`→`TaskTensor` kernel rename,
then onto #2542 adopting the `42-lower_host_tensor_collectives` → `43-…`
docs rename, with the PR's ring-doc edits re-homed) and merges cleanly.
The UT tests pin the push structure (`pld.tile.put` + `tile.create`
staging tile instead of `pld.tile.remote_load`).

## Rebased — merge-order with #2279 (self-clearing signals) resolved

The rebase picked up #2279's self-clearing signal epilogue, which was
written for the **pull-model `RoundBarrier`** (reset every peer's cell
with `TNOTIFY(-1)` per round). That credit pattern does **not** match
the push model's `NeighborBarrier`:

- `NeighborBarrier` credits only the **two ring neighbours** per round —
a single cell when `nranks == 2`, where both neighbours are the same
peer and the cell carries two +1s.
- The #2279 loop would corrupt the unused cells to −1 and, for `nranks
== 2`, leave +1 stale credit in the one used cell — reintroducing the
exact stale-credit barrier failure #2279 fixed.

The epilogue now branches on `kUseNeighborBarrier`: it restores only the
two neighbour cells per used row with `TNOTIFY(-1, AtomicAdd)` (twice on
the shared cell when `nranks == 2`), keeping the all-peer reset for the
`RoundBarrier` fallback. The ring builtin is therefore **self-clearing
and signal-reuse-safe** across back-to-back calls, matching the other
host builtins (#2279). The ring signal-reuse ST
(`test_l3_host_tensor_allreduce_ring.py` reuse leg) is the NPU gate for
the adapted epilogue.

## Issues this PR addresses

- **#2242 (ring unaligned-data handling)**: the pull-model dcci-flush
tail gap (item 1) is **moot** — the push model needs no cacheline flush
(the receiver reads data the sender wrote remotely via TPUT, never a
locally-TSTORE'd line). The 32-byte transfer-alignment concern (item 2)
is handled by narrowing the staging tile's column mask
(`ColMaskInternal` / `tile.set_validshape`) to the exact (possibly
ragged) transfer extent, so partial tails transfer exactly and never
over-read/overwrite adjacent slots.
- **#2213 (PTOAS dynamic partition-view)**: closed as superseded by
#2524; the `>= v0.55` dependency it describes is satisfied by the v0.57
pin.

## Verification (NPU silicon, 910B2, PTOAS v0.55)

All on real NPUs (8x 910B2), P=2 and P=4:

- `tests/st/distributed/test_l3_host_tensor_allreduce_ring.py` — HOST
ring, P=2/4 ✅ (with `NeighborBarrier` enabled)
-
`tests/st/distributed/collectives/test_l3_tensor_allreduce_ring_intrinsic.py`
— InCore ring, P=2/4, sizes {1, 17, 4097, 65537} (ragged + >UB),
Sum/Max/Min/Prod, FP16 ✅
- `tests/st/distributed/collectives/test_l3_allreduce_ring.py` +
`test_l3_ring_sizing_prewarm.py` — no regression ✅
- UTs: `test_lower_host_tensor_collectives.py`,
`test_host_orch_distributed.py`, `test_lower_composite_ops.py` (+
numerical) all green ✅

**Total: 25/25 ST + 190 UT passed** (pre-rebase). The 2026-08-26 rebase
+ epilogue adaptation re-ran the ring UTs (173/174, the one failure is a
pre-existing parser `TileView(pad=…)` roundtrip gap on main, unrelated
to this PR); the 2026-08-27 re-rebases (onto the #2530 runtime bump and
the #2542 docs rename) each re-ran the same 173/174. NPU ST should be
re-confirmed for the signal-reuse leg.

## Trade-off note (ReduceOp)

The HOST builtin is `ReduceOp::kSum` only by construction, so its
`TPUT<AtomicAdd>` RS is fine. The composite keeps non-atomic push +
local reduce to preserve Sum/Max/Min/Prod; only a remote-atomic
`TPUT<AtomicAdd>` variant would be Sum-only (`AtomicType` has no
`AtomicMax/Min`).

## Follow-ups (not in this PR)

- **#2310** — lift the HOST-rail in-loop `pld.tensor.allreduce`
restriction via shared-signal synthesis (the other half of the #2279
review).
- **TPUT_ASYNC** (pto-isa) for an overlapped / IBing forward phase —
optional perf follow-on (simpler #1383 / plan 50).

## Review notes

- Addresses CodeRabbit feedback: the allgather ready-barrier rationale
is corrected (counters are per-round; the real guarantee is the previous
round's push-done barrier every rank passes before round k), and the
`nranks == 2` `NeighborBarrier` behaviour is documented.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant