chore(runtime)!: bump simpler to 799640e6; adopt its renamed and removed API - #2530
Conversation
|
Important Review skippedToo 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 configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (125)
You can disable this status message by setting the 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. Comment |
…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.
af4d37a to
80d32ca
Compare
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.
…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.
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.
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.
#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
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.
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.
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.
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.
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.
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.
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.
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.
…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.
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.
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.
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.
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.
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>
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.
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.
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.
## 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`
…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.
Summary
Bumps the
runtimesubmodule93adc386→799640e6(69 commits) and adaptspypto to the four pypto-facing changes in that range: simpler finished retiring
the
PTO2naming, renamed two headers pypto#includes from generated code,split
ChipTensorinto a boundary type and a per-runtime working type, andremoved
TensorCreateInfo::set_initial_value.runtime/pto_isa.pinisunchanged 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 nowraises
ValueErrornaming its replacement.Changes
runtime: submodule gitlink93adc386→799640e6.src/codegen/orchestration/,src/ir/,python/pypto/: adopt the retirednames —
PTO2TaskId→TaskId,PTO2_SCOPE→SIMPLER_SCOPE,PTO2ScopeMode→ScopeMode,PTO2OrchestrationConfig→OrchestrationConfig,PTO2_ERROR_ASYNC_*→SIMPLER_ERROR_ASYNC_*(simplerbuild: 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_SCOPEand the errorcodes take
SIMPLER_because a bareSCOPE(would expand too eagerly and thestatus 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: emitorchestration_api.handasync_kernel_api.h, which simpler build: use cmake.version instead of removed cmake.minimum-version #1963 renamedfrom their
pto_-prefixed spellings.src/codegen/,python/pypto/backend/,python/pypto/runtime/builtins/collectives/*/templates/: generatedorchestration and kernels name
TaskTensorinstead ofChipTensor. simplerrefactor(codegen): dedup and split pto_ops_common by op category #1974 split the fused type: the 72-byte
ChipTensoris now only the argumentas it arrives at the boundary, while the 128-byte descriptor — the old
ChipTensorfield-for-field — is each runtime's ownsimpler::tmr::Tensor/simpler::hbg::Tensor.orch_args.tensor(i).ref()andTaskOutputTensors::get_ref()return that type, and the payload a kernelreads holds it.
TaskTensoris the alias each runtime'stensor.hshimdefines for its own type; pypto compiles against both runtime flavours, so
naming
simpler::tmr::Tensoroutright would breakhost_build_graph.Orchestration gains
#include "tensor.h"because the shim sits first on thatinclude path and
orchestration_api.hdoes not reach it. The host-side Pythonboundary (
task_interface.py,tensor_arg.py,device_tensor.py) keepsChipTensor, 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_valueontensor.createis 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_graphlost it in feat(backend): enable bf16 atomic-add on A2/A3, broaden atomic dtype tests #1930, so all four variants now agree), and noorchestration-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>isdropped from the op schema so the parser, the
.ptodeserializer, andC++-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_POOLare retired by [RFC] Pluggable DSA Memory-Planning Solver + PyPTO Adapter #1980 — the runtime warns once per bind if one isexported. The documented fallback chain loses that tier, so
RunConfigoverrides now fall straight through to the compile-time default.
docs/**/02-error-handling.md: the "user-supplied kwarg value" example movedfrom the removed
tensor.createinit_valuetotensor.assemble'satomic.Migration
pl.create_tensor(shape, dtype, init_value=v)has no drop-in replacement. Seedthe buffer with a kernel that writes it, then order every reader after that
kernel with an explicit dependency (
pl.submit(..., deps=[seed_tid])orpl.at(..., deps=[seed_tid])) — the pattern simpler #1922 established for theDeepSeek-V4 decode buffers.
pl.fullis unaffected and remains the supportedway 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
PTO2finds the identifiers but not the renamed headers,which are plain
#includestring literals; extracting every#includeandevery
.member(pypto emits and checking each against the new runtime treefinds those, and shows
rt_orch_profile_now/rt_orch_profile_add_dynamic_dep_vectorare absent from simpler — though theywere absent at the old pin too, so they are pre-existing and out of scope here.
But
ChipTensor,add_inputandadd_outputall still exist; only the typerelationship 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 payloadelement still compiles in a kernel and reads
owner_task_id's bytes asstart_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-onlyagainst all fourruntime × arch include paths, and reverting
TaskTensortoChipTensorreproduces this PR's earlier CI error verbatim. That is the evidence behind the
adaptation being complete, not the greps.
ScopeMode's enumerators, theTaskOutputTensors/ChipTaskArgs/TensorCreateInfoshapes, 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. ThesimplerPythonsurface pypto imports is intact;
task_interface.pyonly gainsDeviceMemoryInfoandTaskHandle.Verification
pytest tests/ut/— 10377 passed, 8 skipped, 2 xfailed. Run inside the pushtransaction, 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 skippedctest— 1/1 passedg++-15 -fsyntax-onlyagainst{tensormap_and_ringbuffer,host_build_graph}×{a2a3,a5}— all four cleantests/lint/check_*.py(all twelve) — cleanruff check+ruff format --check+pyrighton 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.
test_symlinked_import_path_still_names_the_callerspawns a subprocess with areplaced
PYTHONPATH, which drops the shim this linked worktree needs tobypass an editable install pointing at the main checkout. It resolves the main
checkout's
pyptorather than this branch's and does not reproduce in CI.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-modelis red and stays red on re-run — deterministically, on twodifferent devices, at the same task boundary (
completed=15/285) and the samefaulting
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:That header still exists after this bump, so the shim keeps selecting
ChipTensor— which simpler #1974 redefined from the 128-byte payloaddescriptor to the 72-byte boundary argument. The kernel then reads
owner_task_id's bytes asstart_offsetand garbage asshapes/strides,which surfaces on device as
fftsplus aivector errorfollowed bysub_class=S1:running-stalled. This is the silent half of theChipTensorsplit: the kernel path still compiles, so nothing catches it before the card.
The fix belongs in pypto-lib — select
TaskTensor, the alias each runtime'stensor.hshim defines for its own 128-byte type. hw-native-sys/pypto-lib#1052does that, and must land before this pin can go green. Every other check on this
PR passes, including all four other device suites.