feat(tenstorrent): land BACKEND-TENSTORRENT W0 skeleton - kMatmul on real HW - #197
feat(tenstorrent): land BACKEND-TENSTORRENT W0 skeleton - kMatmul on real HW#197lu-zero wants to merge 0 commit into
Conversation
Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude-Code:claude-sonnet-5 [Claude Code]
FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude-Code:claude-sonnet-5 [Claude Code]
6d0e676 to
b88a62d
Compare
…ensix Proposes DeviceType::kTENSTORRENT (not kBLACKHOLE - collides with this codebase's pervasive NVIDIA Blackwell/GB10 references) as a thin vt::Backend adapter over ttnn's existing C++ op library, mirroring the Metal/MLX decision (E1) rather than hand-written kernels. Maps the three backend.md seams onto concrete tt_metal primitives: trace capture -> BeginCapture/EndCaptureGraph/ Replay, UnifiedMemory()=false and its consequence (op_provider's CPU reference tier is gated off - no partial-backend safety net). Confirmed read-only against a local tt-metal checkout: TT-NN's CMake package export is real and external-consumable (TTNN::TTNN imported target), matmul()'s C++ signature, and which ttnn ops already exist for a minimal decode-only model (paged_cache in particular, which de-risks vLLM's block-table attention). Identifies the one actual open risk: vt::Tensor is a bare device-pointer view, ttnn::Tensor has no equivalent "attach to a pointer I already own" constructor - names the resolution path and the concrete hands-on spike that must prove it before any code lands in src/vt/. Registers BACKEND-TENSTORRENT as a new INVENTORIED row in backend-matrix.md (Owner CLAIM-BACKEND-TENSTORRENT-SPIKE) and item 15 in porting-inventory.md §9 (Extension platforms, alongside Metal/Vulkan item 8); bumps the pinned BACKEND row count in check-agent-record.py 79 -> 80; records the active claim in coordination.md (isolated worktree, row/BACKEND-TENSTORRENT branch; draft PR mudler#197 is the claim, pushed with explicit developer authorization since no developer-preferences.md exists for this session and the safe default is ask-first for push/PR); adds a BENCHMARKS.md row (NOT APPLICABLE - no number measured, claimed or owed; no Tenstorrent hardware here), a FEATURES.md row, and a one-line STATUS.md mention; refreshes NOW.md's live-claims table within its 6000-char budget. STATUS.md ratchet: rebased-main measures 244102 chars (Python len(), not bytes - the checker's own metric), 24 under the 244126 pin. The one-line addition here is +120 chars, so the ratchet moves 244126 -> 244222 in the same change, dated and justified in check-public-doc-tables.py's STATUS_RATCHET comment, matching the existing convention for every prior number on that constant. No existing narrative was collapsed this pass. DRAFT: spec content written outside scripts/agent-start.py / role declaration / the policy.csv gates in an earlier pass of this session, then brought into the proper claim protocol (worktree, branch, role, coordination entry, doc pairing) per the developer's request. Not READY, not ACTIVE, no code. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude-Code:claude-sonnet-5 [Claude Code]
b88a62d to
6fc3371
Compare
…ensix Proposes DeviceType::kTENSTORRENT (not kBLACKHOLE - collides with this codebase's pervasive NVIDIA Blackwell/GB10 references) as a thin vt::Backend adapter over ttnn's existing C++ op library, mirroring the Metal/MLX decision (E1) rather than hand-written kernels. Maps the three backend.md seams onto concrete tt_metal primitives: trace capture -> BeginCapture/EndCaptureGraph/ Replay, UnifiedMemory()=false and its consequence (op_provider's CPU reference tier is gated off - no partial-backend safety net). Confirmed read-only against a local tt-metal checkout: TT-NN's CMake package export is real and external-consumable (TTNN::TTNN imported target), matmul()'s C++ signature, and which ttnn ops already exist for a minimal decode-only model (paged_cache in particular, which de-risks vLLM's block-table attention). Identifies the one actual open risk: vt::Tensor is a bare device-pointer view, ttnn::Tensor has no equivalent "attach to a pointer I already own" constructor - names the resolution path and the concrete hands-on spike that must prove it before any code lands in src/vt/. Registers BACKEND-TENSTORRENT as a new INVENTORIED row in backend-matrix.md (Owner CLAIM-BACKEND-TENSTORRENT-SPIKE) and item 15 in porting-inventory.md §9 (Extension platforms, alongside Metal/Vulkan item 8); bumps the pinned BACKEND row count in check-agent-record.py 79 -> 80; records the active claim in coordination.md (isolated worktree, row/BACKEND-TENSTORRENT branch; draft PR mudler#197 is the claim, pushed with explicit developer authorization since no developer-preferences.md exists for this session and the safe default is ask-first for push/PR); adds a BENCHMARKS.md row (NOT APPLICABLE - no number measured, claimed or owed; no Tenstorrent hardware here), a FEATURES.md row, and a one-line STATUS.md mention; refreshes NOW.md's live-claims table within its 6000-char budget. STATUS.md ratchet: rebased-main measures 244102 chars (Python len(), not bytes - the checker's own metric), 24 under the 244126 pin. The one-line addition here is +120 chars, so the ratchet moves 244126 -> 244222 in the same change, dated and justified in check-public-doc-tables.py's STATUS_RATCHET comment, matching the existing convention for every prior number on that constant. No existing narrative was collapsed this pass. DRAFT: spec content written outside scripts/agent-start.py / role declaration / the policy.csv gates in an earlier pass of this session, then brought into the proper claim protocol (worktree, branch, role, coordination entry, doc pairing) per the developer's request. Not READY, not ACTIVE, no code. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude-Code:claude-sonnet-5 [Claude Code]
e241d64 to
e887f8c
Compare
…ensix Proposes DeviceType::kTENSTORRENT (not kBLACKHOLE - collides with this codebase's pervasive NVIDIA Blackwell/GB10 references) as a thin vt::Backend adapter over ttnn's existing C++ op library, mirroring the Metal/MLX decision (E1) rather than hand-written kernels. Maps the three backend.md seams onto concrete tt_metal primitives: trace capture -> BeginCapture/EndCaptureGraph/ Replay, UnifiedMemory()=false and its consequence (op_provider's CPU reference tier is gated off - no partial-backend safety net). Confirmed read-only against a local tt-metal checkout: TT-NN's CMake package export is real and external-consumable (TTNN::TTNN imported target), matmul()'s C++ signature, and which ttnn ops already exist for a minimal decode-only model (paged_cache in particular, which de-risks vLLM's block-table attention). Identifies the one actual open risk: vt::Tensor is a bare device-pointer view, ttnn::Tensor has no equivalent "attach to a pointer I already own" constructor - names the resolution path and the concrete hands-on spike that must prove it before any code lands in src/vt/. Registers BACKEND-TENSTORRENT as a new INVENTORIED row in backend-matrix.md (Owner CLAIM-BACKEND-TENSTORRENT-SPIKE) and item 15 in porting-inventory.md §9 (Extension platforms, alongside Metal/Vulkan item 8); bumps the pinned BACKEND row count in check-agent-record.py 79 -> 80; records the active claim in coordination.md (isolated worktree, row/BACKEND-TENSTORRENT branch; draft PR mudler#197 is the claim, pushed with explicit developer authorization since no developer-preferences.md exists for this session and the safe default is ask-first for push/PR); adds a BENCHMARKS.md row (NOT APPLICABLE - no number measured, claimed or owed; no Tenstorrent hardware here), a FEATURES.md row, and a one-line STATUS.md mention; refreshes NOW.md's live-claims table within its 6000-char budget. STATUS.md ratchet: rebased-main measures 244102 chars (Python len(), not bytes - the checker's own metric), 24 under the 244126 pin. The one-line addition here is +120 chars, so the ratchet moves 244126 -> 244222 in the same change, dated and justified in check-public-doc-tables.py's STATUS_RATCHET comment, matching the existing convention for every prior number on that constant. No existing narrative was collapsed this pass. DRAFT: spec content written outside scripts/agent-start.py / role declaration / the policy.csv gates in an earlier pass of this session, then brought into the proper claim protocol (worktree, branch, role, coordination entry, doc pairing) per the developer's request. Not READY, not ACTIVE, no code. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude-Code:claude-sonnet-5 [Claude Code]
1404db3 to
bee3dce
Compare
|
Reviewed the shape. The structure is right — this is the additive form the policy asks for, and the naming rationale is the correct call. Two things block a merge, neither of them design. What's good, specificallyThe shared-layer footprint is three files and all three mirror an existing idiom rather than inventing one:
Choosing Adapting ttnn rather than hand-writing Tensix kernels is also the precedent-consistent call (the Metal/MLX E1 decision), and "3/3 cases, 8/8 assertions on real Blackhole" is the right bar for a W0 skeleton. Two blockers
What I'll do once it's rebasedI can't test Blackhole, but I can run the check that actually matters for an additive backend — does adding this device slot disturb anyone else. Say the word after the rebase and I'll build the full CUDA stack on GB10 and run the SACRED gates ( |
…sted-by `check-commit-trailers.py` imports the shared `exact_waiver` from `waivers.py` at line 16 and then SHADOWS it with a local copy that reads `waiver.rule_id`. `Waiver` has no such field — it is `checker` — so the moment the lookup runs the checker dies with `AttributeError: 'Waiver' object has no attribute 'rule_id'`. The lookup only runs for a commit that ALREADY failed validation, which is why this survived: a clean range never reaches it, and neither does an empty one. So the checker worked on every branch that had nothing to report and crashed on exactly the branches that needed its output. On PR #197 it produced a Python traceback instead of naming six commits with a malformed `Assisted-by`. The fix is deletion, not repair: the local duplicate is removed so the imported shared helper is used, which is what the file already asked for. Nothing about what the checker accepts or rejects changes. Red before, green after, same command and range: before: AttributeError: 'Waiver' object has no attribute 'rule_id' after: commit trailer check FAILED: - e3b7529c7eb8: [attribution] malformed Assisted-by value 'Grok-Code [Grok Build]' (and five more, one per offending commit) `tests/scripts/test_check_commit_trailers.py` 16/16. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude:claude-opus-5 [ClaudeCode]
…ensix Proposes DeviceType::kTENSTORRENT (not kBLACKHOLE - collides with this codebase's pervasive NVIDIA Blackwell/GB10 references) as a thin vt::Backend adapter over ttnn's existing C++ op library, mirroring the Metal/MLX decision (E1) rather than hand-written kernels. Maps the three backend.md seams onto concrete tt_metal primitives: trace capture -> BeginCapture/EndCaptureGraph/ Replay, UnifiedMemory()=false and its consequence (op_provider's CPU reference tier is gated off - no partial-backend safety net). Confirmed read-only against a local tt-metal checkout: TT-NN's CMake package export is real and external-consumable (TTNN::TTNN imported target), matmul()'s C++ signature, and which ttnn ops already exist for a minimal decode-only model (paged_cache in particular, which de-risks vLLM's block-table attention). Identifies the one actual open risk: vt::Tensor is a bare device-pointer view, ttnn::Tensor has no equivalent "attach to a pointer I already own" constructor - names the resolution path and the concrete hands-on spike that must prove it before any code lands in src/vt/. Registers BACKEND-TENSTORRENT as a new INVENTORIED row in backend-matrix.md (Owner CLAIM-BACKEND-TENSTORRENT-SPIKE) and item 15 in porting-inventory.md §9 (Extension platforms, alongside Metal/Vulkan item 8); bumps the pinned BACKEND row count in check-agent-record.py 79 -> 80; records the active claim in coordination.md (isolated worktree, row/BACKEND-TENSTORRENT branch; draft PR mudler#197 is the claim, pushed with explicit developer authorization since no developer-preferences.md exists for this session and the safe default is ask-first for push/PR); adds a BENCHMARKS.md row (NOT APPLICABLE - no number measured, claimed or owed; no Tenstorrent hardware here), a FEATURES.md row, and a one-line STATUS.md mention; refreshes NOW.md's live-claims table within its 6000-char budget. STATUS.md ratchet: rebased-main measures 244102 chars (Python len(), not bytes - the checker's own metric), 24 under the 244126 pin. The one-line addition here is +120 chars, so the ratchet moves 244126 -> 244222 in the same change, dated and justified in check-public-doc-tables.py's STATUS_RATCHET comment, matching the existing convention for every prior number on that constant. No existing narrative was collapsed this pass. DRAFT: spec content written outside scripts/agent-start.py / role declaration / the policy.csv gates in an earlier pass of this session, then brought into the proper claim protocol (worktree, branch, role, coordination entry, doc pairing) per the developer's request. Not READY, not ACTIVE, no code. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude-Code:claude-sonnet-5 [Claude Code]
Maintainer edit on top of mudler#197, so the contributor does not have to fight the shrink-only ratchet to land a backend. `docs/STATUS.md` may only shrink, so the new `BACKEND-TENSTORRENT` line has to be paid for. It now carries the binding result (W2, OPT-125m e2e STRICT token-exact on Blackhole, ttnn adapter, 9 ops) plus a pointer, with the per-op detail left where it belongs in `.agents/backend-matrix.md` and the spec. The remaining cost is covered by collapsing superseded narrative in the GGUF row: a "REPORTED, not gated" preamble, a "superseding the gap recorded here" aside, and three restatements of what the same sentence already says. No measured number, gate result or binding claim is touched. Ratchet re-pinned to the measured 243598 in the same change. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude:claude-opus-5 [ClaudeCode]
bee3dce to
2be30f6
Compare
…ensix Proposes DeviceType::kTENSTORRENT (not kBLACKHOLE - collides with this codebase's pervasive NVIDIA Blackwell/GB10 references) as a thin vt::Backend adapter over ttnn's existing C++ op library, mirroring the Metal/MLX decision (E1) rather than hand-written kernels. Maps the three backend.md seams onto concrete tt_metal primitives: trace capture -> BeginCapture/EndCaptureGraph/ Replay, UnifiedMemory()=false and its consequence (op_provider's CPU reference tier is gated off - no partial-backend safety net). Confirmed read-only against a local tt-metal checkout: TT-NN's CMake package export is real and external-consumable (TTNN::TTNN imported target), matmul()'s C++ signature, and which ttnn ops already exist for a minimal decode-only model (paged_cache in particular, which de-risks vLLM's block-table attention). Identifies the one actual open risk: vt::Tensor is a bare device-pointer view, ttnn::Tensor has no equivalent "attach to a pointer I already own" constructor - names the resolution path and the concrete hands-on spike that must prove it before any code lands in src/vt/. Registers BACKEND-TENSTORRENT as a new INVENTORIED row in backend-matrix.md (Owner CLAIM-BACKEND-TENSTORRENT-SPIKE) and item 15 in porting-inventory.md §9 (Extension platforms, alongside Metal/Vulkan item 8); bumps the pinned BACKEND row count in check-agent-record.py 79 -> 80; records the active claim in coordination.md (isolated worktree, row/BACKEND-TENSTORRENT branch; draft PR #197 is the claim, pushed with explicit developer authorization since no developer-preferences.md exists for this session and the safe default is ask-first for push/PR); adds a BENCHMARKS.md row (NOT APPLICABLE - no number measured, claimed or owed; no Tenstorrent hardware here), a FEATURES.md row, and a one-line STATUS.md mention; refreshes NOW.md's live-claims table within its 6000-char budget. STATUS.md ratchet: rebased-main measures 244102 chars (Python len(), not bytes - the checker's own metric), 24 under the 244126 pin. The one-line addition here is +120 chars, so the ratchet moves 244126 -> 244222 in the same change, dated and justified in check-public-doc-tables.py's STATUS_RATCHET comment, matching the existing convention for every prior number on that constant. No existing narrative was collapsed this pass. DRAFT: spec content written outside scripts/agent-start.py / role declaration / the policy.csv gates in an earlier pass of this session, then brought into the proper claim protocol (worktree, branch, role, coordination entry, doc pairing) per the developer's request. Not READY, not ACTIVE, no code. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude-Code:claude-sonnet-5 [Claude Code]
Maintainer edit on top of #197, so the contributor does not have to fight the shrink-only ratchet to land a backend. `docs/STATUS.md` may only shrink, so the new `BACKEND-TENSTORRENT` line has to be paid for. It now carries the binding result (W2, OPT-125m e2e STRICT token-exact on Blackhole, ttnn adapter, 9 ops) plus a pointer, with the per-op detail left where it belongs in `.agents/backend-matrix.md` and the spec. The remaining cost is covered by collapsing superseded narrative in the GGUF row: a "REPORTED, not gated" preamble, a "superseding the gap recorded here" aside, and three restatements of what the same sentence already says. No measured number, gate result or binding claim is touched. Ratchet re-pinned to the measured 243598 in the same change. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude:claude-opus-5 [ClaudeCode]
…witch) Maintainer fix on top of #197. Adding `DeviceType::kTENSTORRENT` widened an enum that `tests/vt/test_backend_cross_device.cpp:54` switches over exhaustively, and the build is `-Werror=switch`: tests/vt/test_backend_cross_device.cpp:54:10: error: enumeration value 'kTENSTORRENT' not handled in switch [-Werror=switch] So the whole test suite failed to compile and no test binary was produced. This is the one site in the tree that needed it: every other `case DeviceType::kROCM` switch already handles the new value. Worth recording how this nearly slipped through. The build wrapper ran `cmake --build ... 2>&1 | tail -25` and then echoed `BUILD_OK` unconditionally, so the pipeline's exit status was `tail`'s and a hard compile error still reported success. The missing binaries, not the build log, are what exposed it. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude:claude-opus-5 [ClaudeCode]
feat(tenstorrent): BACKEND-TENSTORRENT — ttnn adapter, OPT-125m e2e on Blackhole A new accelerator backend as an additive `vt::Backend` adapter over Tenstorrent's ttnn C++ tensor-op library, mirroring the Metal/MLX decision rather than hand-writing Tensix kernels. It is no longer a skeleton: `DeviceType::kTENSTORRENT` plus nine registered ops carry OPT-125m end to end, STRICT token-exact, on real Blackhole hardware. The shared footprint is three small changes, each mirroring an existing idiom: a `device.h` enum slot, one `AttentionBackendRegistrar` built like the `kCUDA`/`kCPU` entries, and a priority-walk insertion placing Tenstorrent LAST among accelerators so a machine without one falls straight through to CPU. Because the risk of this change is not Tenstorrent but everyone else, the widening was verified inert on CUDA (GB10, sm_121a, production build): test_qwen27_paged_engine 235/235 (SACRED) test_qwen36_paged_engine 315/315 (SACRED) test_opt_paged_engine 63/63 test_backend_cross_device 132/132 That last one is the reason to run them. Widening `DeviceType` broke an exhaustive switch in `test_backend_cross_device.cpp` under `-Werror=switch`, so the whole test suite failed to compile and no binary was produced. It is fixed here, and it was the only such site in the tree. Maintainer commits on top of the contributor's ten, authorship preserved: the `-Werror=switch` case, and fitting the new `docs/STATUS.md` line inside the shrink-only ratchet by collapsing superseded GGUF narrative. The malformed `Assisted-by` trailers were normalised in place. A checker bug this exposed — `check-commit-trailers.py` crashing instead of reporting — landed separately as 04069bd. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude:claude-opus-5 [ClaudeCode]
2be30f6 to
cc48858
Compare
|
Landed on Thanks for this — the shape was right and it made the review easy: additive files, three small shared-layer touches each mirroring an existing idiom, and the priority walk placing Tenstorrent last among accelerators so a machine without one falls straight through to CPU. What I fixed on top, so you know what changed
Verification, since the risk here is everyone elseThe point of a new device slot is whether it disturbs the backends that already work, so I built the full CUDA stack on GB10 (sm_121a, CUTLASS + FA2 + vendored Triton-AOT):
One thing your PR exposed that was our bug, not yours: |
feat(tenstorrent): Qwen3-dense ops, device residency, and paged-KV decode Follow-on to #197. Grows the Blackhole adapter from host-round-trip OPT ops into a Qwen3-dense path: kRmsNorm / kSiluAndMul / Cast + NeoX RoPE providers, device-resident shadows so the matmul chain skips the host download between ops, hybrid RoPE (device at T*H >= 64), and a dual-layout paged KV path for decode. Scope is tight — 9 files, all Tenstorrent-local except the Qwen3 gate and one analysis script — so the only real review question is whether it disturbs the devices that already work. It does not, on CUDA (GB10, sm_121a): test_qwen3_paged_engine 184/184 test_qwen27_paged_engine 235/235 (SACRED) That first one is the one that mattered. The gate's op-list assertion changes from kRopeCosSinCache + kRopeFromCache to kRopeNeox, which is an assertion about what the CUDA path runs, not just the Tenstorrent one. It passes, so the default CUDA path genuinely takes kRopeNeox with the cache off and the edit is a correction rather than a loosening. The Metal special-case generalises cleanly to : each partial accelerator is gated against ITS OWN oracle-backed golden with identical anchor+band logic, which is the right shape for a model whose 0.6B greedy stream is a genuine near-tie. Maintainer fix on top, authorship preserved: one commit carried no trailer block and two carried a malformed Assisted-by. Worth noting the missing block was REPORTED rather than crashing the checker, because 04069bd fixed that shadowed exact_waiver earlier today. FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude:claude-opus-5 [ClaudeCode]
Developer decision, on measured grounds rather than feel. Over the last 22 merged PRs the 900-line `product` budget was exceeded by 9 of them (41%): 71 76 78 129 178 182 237 338 340 479 596 605 895 | 1272 1306 1510 2261 2843 3224 4098 5282 6480 A gate that fires on four changes in ten is not a budget, it is noise that teaches people to waive it. Worse, tests are a third to a half of every large diff here (#211 909/2261, #197 684/1510, #240 931/2843, #196 2319/4098), so the budget charged RED-first mutation tests against the same allowance as kernel code, penalising exactly the discipline the rest of AGENTS.md demands. Size is now a review judgement: split a change when a reviewer would be better served by parts, not when a counter says so. WHAT IS NOT RETIRED, because dropping a size gate is not licence to drop the rules that shared its file: explicit path classification (no blanket directory exemptions), the fail-closed binary guard, the checker-change mutation-evidence contract, and the role check that keeps product paths on a PR. A new test pins all three so they cannot be deleted quietly alongside a constant. Evidence for this being a real checker-semantics change, per the contract this checker itself enforces: `test_no_line_budget_is_enforced_for_any_class` is RED against the pre-change checker (which exported PATH_CLASS_BUDGETS and rejected a 100k-line product change) and green after; the companion regression test is green on BOTH sides and asserts on the error, not its wording, so it is not coupled to a message the retirement reworded. Suite: 33 passed, 101 subtests. The `pr-size` CI job keeps its name because it is a required check; its comment and step name now say what it actually enforces. Re-running it over PR #211, the 2261-line change that prompted this, leaves exactly one error: the genuine missing mutation evidence for a checker edit. Following-Agents-Protocol: true AI-Assisted: true Assisted-by: Claude Code:claude-opus-5 [Claude Code]
Summary
Proposes and lands
DeviceType::kTENSTORRENT(deliberately notkBLACKHOLE— collides with this codebase's pervasive NVIDIA Blackwell/GB10 references) as a thinvt::Backendadapter over Tenstorrent's own ttnn C++ tensor-op library, rather than hand-written Tensix kernels — mirroring the Metal/MLX decision (E1 inbackends.md).W0 skeleton, real code, real hardware — not just a proposal anymore:
DeviceType::kTENSTORRENT+kCurrentPrioritymembershipvt::tenstorrent::Backend— host-staged (Blackhole is genuinely discrete, unlike Vulkan's W0 here which is unified on GB10),UnifiedMemory()=falsevt::tenstorrent::TenstorrentPlatform, mirroringvulkan.cpp's registrar idiomkMatmul(F32, rank-2 only):Tensor::from_vectoruploads,ttnn::operations::matmul::matmulruns on-device,to_vectorreads backtests/vt/test_tenstorrent_backend.cpp, through the publicvt::/vllm::platforms::API only — 3/3 test cases, 8/8 assertions, PASS on real Blackhole hardware (registration, Platform/Backend mirror, kMatmul vs a host F32 reference within bf16 tolerance:max_abs_diff=0.03375vsmax_ref_mag=4.14)Two real bugs found and fixed while landing this, both documented in place:
tenstorrent_ops.cpptransitively pulls in tt-metal'stt_stl/reflection.hpp, which properly includes the full<nlohmann/json.hpp>. vllm.cpp also vendors its own different-versioned nlohmann-json on the same include path project-wide; nlohmann's ABI-versioned inline namespace turns that into a loud ambiguous-basic_jsoncompile error (by design — the alternative would be a silent ODR violation). Fixed by isolatingtenstorrent_ops.cppas its ownOBJECTlibrary with its own include set — the same isolation patternvllm_rocm_platform_syntax_checkalready uses. The actual root-cause fix, if ever wanted, is on vllm.cpp's side (find_package(nlohmann_json)instead of a private vendored copy) — a cross-cutting build decision noted for the maintainer, out of scope here.static shared_ptr<MeshDevice>reproducibly segfaulted at process exit insideMeshDevice's own teardown chain — a cross-libtt_metal.sostatic destruction ordering hazard. Fixed by deliberately leaking the device so its destructor never runs at process exit; documented intenstorrent_device.cpp/.h, not a silent workaround.Updates
backend-matrix.md(State →ACTIVE),porting-inventory.md§9 item 15, the spec (now with the formal Scope/Upstream chain/Our baseline/Port map/Tests to port/Gates/Dependencies/Work breakdown/Risks-decisions structure this repo's spike gate requires), and matchingSTATUS.md/BENCHMARKS.md/FEATURES.md/NOW.md/README.md/USAGE.mdentries.Status:
ACTIVEmeans a gated skeleton, not a supported backend — same caveat Metal/Vulkan's ownACTIVEstatus carries. No model runs; one op only; every call pays a host round-trip (documented, deliberate W0 scope, not an oversight). Not yet reviewed by a maintainer.agent-preflight.shpasses clean (record gates, mutation suites, doc-checkpoint range, commit-trailers).Test plan
scripts/agent-preflight.sh— all gates greentests/vt/test_tenstorrent_backend.cpp— 3/3 cases, 8/8 assertions, PASS on real Blackhole (P150) hardwareTensorwrap (see spec's Risks/decisions cuda: add bf16 triton gdn chunk path #3)🤖 Generated with Claude Code