tenstorrent/tt-emule

implement-mock

Workflow for adding a faithful mock of a silicon API to tt-emule.

Ver código-fonte

Como usar

  1. Copie o comando e verifique o pacote antes de instalar no seu ambiente de agente.
  2. Consulte no original as ferramentas, credenciais e ambientes necessários.
  3. Descreva os dados de entrada e a entrega esperada; confira a saída com as fontes.
npx skills add https://github.com/tenstorrent/tt-emule --skill implement-mock

Antes de começar

  • A instalação não inclui assinatura de modelo, franquia API ou acesso aos seus arquivos.
  • Estrelas e instalações indicam atividade, não um teste independente de qualidade ou segurança.
Documento original do Skill

Renderizado do repositório de origem, preservando títulos, exemplos, código, tabelas, links e imagens.

/implement-mock — Add a faithful mock to tt-emule

You've identified a silicon API that tt-emule needs to mock (or a mock that's diverging from silicon). This skill walks the end-to-end workflow.

Usage

/implement-mock <silicon_function_or_concept>
/implement-mock noc_async_write_tile
/implement-mock llk_unpack_AB_matmul
/implement-mock TensorAccessor::get_noc_addr

Step 1 — Look up the HW spec

Run /arch-lookup "<silicon_function>" first. The arch-lookup skill gives you the authoritative HW behavior across wormhole / blackhole (and quasar if asked), AND a starting recommendation for the mock.

Read the sage output's "Emule mapping" + "Recommendation" sections carefully — they may already point at the right strategy.

Step 2 — Pick a strategy

A mock sits at one of three rungs of the kernel API stack (see `docs/kernel-api-layers.md` for the layer-1 / 1.5 / 2 / 3 vocabulary). Pick the strategy that matches the layer the silicon API bottoms out at:

StrategyKernel-API layerWhen
A — stub in `include/jit_hw/`layer-1 (PoR tile-op)The silicon API is generic enough that one emule-side body works for every kernel that calls it.
B — per-op `#ifdef __EMULE_JIT_MODE` patch in the consumer's op headerlayer-1.5 / layer-2 mixThe API can't be generically stubbed (takes a constexpr L1 firmware address, calls a small set of LLKs) but the consuming op can route through an emule-friendly equivalent.
C — semantic rewrite under `__EMULE_JIT_MODE`layer-2 / layer-3 reframingThe op's TRISC body is deeply LLK / sfpi / TTI_*-bound (>5 LLK template errors on first compile). Re-express the op at a higher layer rather than stub every header below it.

Strategy A — stub in include/jit_hw/

Default for layer-1 lifts: new compute primitives, dataflow helpers, generic API surface. Example: noc_async_write, mul_tiles, recip_tile, pack_tile.

  • Add the function to the appropriate header under jit_hw/
  • If it operates on DST: use __emule_dst[idst][i] row-major float32
  • If it operates on a CB tile: use __emule_compute::cb_read_ptr_at /

cb_write_ptr_at + __emule_nfaces::rowmajor_to_nfaces[] permute

  • If it's pipeline state (UNPACK/MATH/PACK config): no-op stub
  • No __EMULE_JIT_MODE guard needed (jit_hw/ is inside -I ahead

of tt-metal's hw/inc)

For LLK compute shims (functions like <op>_tile / <op>_tile_init under include/jit_hw/api/compute/), use /compute-llk-bringup directly — it specializes Strategy A with the shim-pattern catalog, sfpu_split_includes.h wiring, op→test-file mapping, polynomial-port recipe, and PCC triage flow for that scope.

Strategy B — per-op #ifdef __EMULE_JIT_MODE patch

Edit the consumer's op.hpp (or equivalent header) directly under __EMULE_JIT_MODE. Most common shape (constexpr L1 firmware address cast routed through __emule_local_l1_to_ptr):

cpp
volatile tt_l1_ptr T* p =
#ifdef __EMULE_JIT_MODE
    reinterpret_cast<volatile tt_l1_ptr T*>(__emule_local_l1_to_ptr(L1_ADDR));
#else
    reinterpret_cast<volatile tt_l1_ptr T*>(L1_ADDR);
#endif

Strategy C — semantic rewrite under __EMULE_JIT_MODE

  • Gate off the entire silicon #include block AND the operator()

body under #ifdef __EMULE_JIT_MODE

  • Reimplement the op directly with CB read/write + __emule_dst[] math
  • Validated 4× to date: RMSNorm, clampedsilu, Mcast, eltwisemul

If unsure: default to A (stub in jit_hw/) if generic, B (per-op patch) if a single op uses it, C (semantic rewrite) if the LLK / sfpi chain is too deep.

Step 3 — Wire it in

Common scaffolding tasks:

  1. Allowlist the op (if the consumer uses an __EMULE_JIT_MODE

aggregator header): add the op to the #else/emule branch — append, don't reorder existing entries.

  1. Wipe the JIT cache before testing:
bash
   rm -rf /tmp/tt_emule_jit_* /tmp/tt_emule_src_*

If the persistent cache at /tmp/tt_emule_jit_cache_* doesn't hash the aggregator/op headers, wipe it too; otherwise per-test temp dirs at /tmp/tt_emule_jit_*/ are enough.

  1. Run the test that exercises the new mock.
  1. Verify the sentinel test still passes (your smallest end-to-end

emule test, used to catch broad collateral damage).

Step 4 — Verify

Pass bar:

  • Target test: 100% parametrizations passing (or PCC > test's threshold)
  • Sentinel test: still passes (your mock changes may have

collateral damage on existing tests)

  • tt-metal regression: totals must match the last known good

baseline (no previously-passing test now failing):

bash
  # default arch is wormhole n150; use the per-arch script (also
  # run_regression_blackhole.sh / run_regression_quasar.sh as needed)
  TT_METAL_DIR=<tt-metal-checkout> bash scripts/run_regression_wormhole.sh 2>&1 | tee regression-wormhole.log

If any of the above slips, see "Recovery" below.

Step 5 — Document

  • If the mock is faithful to silicon: short comment at the impl site

noting the HW behavior + reference (DeepWiki page, Confluence page, or LLK file:line).

  • If the mock is intentionally simplified (no UNPACK/MATH/PACK

pipeline state, no fabric, no real sfpi:: SIMD): note the simplification.

  • If you discover a new pattern (e.g. a fresh instance of the semantic

rewrite, or a brand-new strategy), add it to .claude/references/emule-mapping.md.

Batch mode

For sweeps (≥4 similar mocks at once), see /parallel-mock-implementation for the Workflow-tool dispatch pattern: one sub-agent per file, structured DONE/STUCK output, orchestrator handles centralized wiring afterward.

Step 6 — Time-box

Set a budget (e.g., 30 min for a non-trivial mock, 15 min for a sweep). If you're past the time-box and not converging, mark BLOCKED with a precise triage note + the deepest error message, and move on.

Recovery / rollback

  • If a primitive change breaks the sentinel:
bash
  git checkout <file>

and move on with the next primitive.

  • If an op's allowlist add poisons all kernels (sentinel breaks),

remove the allowlist entry and move on.

  • If tt-metal regression slips, bisect by reverting hunks; worst case,

restore from a pre-change snapshot.

Anti-patterns

These cause more harm than good — avoid:

  1. Stubbing without consulting the HW spec. A no-op stub may

compile but produce wrong output, and that's harder to debug than a missing-symbol error.

  1. **Adding an op to the allowlist before verifying its op.hpp

parses under TRISC.** Sentinel breaks; everyone else also breaks.

  1. Blanket `rm -rf /tmp/tt_emule_jit_` while other workers run.**

Wave-1 swarm hit this. Sequential work is fine.

  1. **Implementing real sfpi:: SIMD math just to get one test to

pass.** The shim provides types only; for an op that needs real SIMD, use the semantic rewrite pattern instead.

  1. **Editing the silicon path in a consumer's aggregator header's

#ifndef __EMULE_JIT_MODE branch.** That branch isn't ours; keep edits under #else (or #ifdef __EMULE_JIT_MODE).

Related references

  • docs/kernel-api-layers.md — layer-1 / 1.5 / 2 / 3 vocabulary the

Step 2 strategies map onto

  • .claude/references/emule-mapping.md — HW concept → emule mock

catalog (§§1–6 + out-of-scope table)

  • docs/api-injection-points.md — where in the pipeline emule injects
  • CLAUDE.md — project conventions (clang-20, slow dispatch, always run

regressions)

  • BUILD_GUIDE.md — TT_METAL_DIR, regression scripts

Relacionados por tarefa

do mesmo repositório

Mais Skills

Todos os Skills
tenstorrent
Comunidade

index-based-ops

Bring up or debug index-based compute ops (TopK, Sort, Argmax) in tt-emule — ops that return values + indices, where ties make the index choice non-unique. Use when implementing one of these ops or triaging its value/index test failures.

instalações
1
GitHub Stars
5
Atualizado
16 de out.
tenstorrent
Comunidade

memory-debug

Diagnose data-corruption failures in tt-emule operations (wrong values, partial zeros, off-by-N row/col writes). Use when a regression test reports ATOL 1e-3 on otherwise-functional kernel paths.

instalações
1
GitHub Stars
5
Atualizado
16 de out.
tenstorrent
Comunidade

verify-mock

Verification checklist to walk before declaring a tt-emule mock complete. Use after implementing a stub (typically at the end of /implement-mock or /compute-llk-bringup) to catch the recurring failure modes — signature drift, no-op math, missing format dispatch, JIT-cache staleness, regression baseline drift.

instalações
1
GitHub Stars
5
Atualizado
16 de out.
tenstorrent
Comunidade

workarounds

Registry of deliberate, non-ideal workarounds currently live in tt-emule (hacks we accepted to make something pass, NOT normal development practice). Read this before adding any new workaround, and when touching code that carries one — each entry records what the hack is, why it is not the right fix, the real root cause, and the path to removing it.

instalações
1
GitHub Stars
5
Atualizado
16 de out.