Skip to content

Refactor: a2a3 swimlane AICore-self-identifying records (level=1 bypasses complete_task)#974

Open
hw-native-sys-bot wants to merge 5 commits into
hw-native-sys:mainfrom
hw-native-sys-bot:swimlane-aicore-self-id
Open

Refactor: a2a3 swimlane AICore-self-identifying records (level=1 bypasses complete_task)#974
hw-native-sys-bot wants to merge 5 commits into
hw-native-sys:mainfrom
hw-native-sys-bot:swimlane-aicore-self-id

Conversation

@hw-native-sys-bot
Copy link
Copy Markdown
Collaborator

Summary

Refactor a2a3 swimlane so AICORE_TIMING (level=1) skips the AICPU complete_task hot path entirely. The AICore record self-identifies via the full PTO2 task_token_raw (read from the dispatch payload's LocalContext.async_ctx.task_token — already in AICore cache), AICore buffer rotation is decoupled from complete_task via a dedicated signal channel + scheduler-loop poll, and dep_gen + host derivation cover the remaining identity gaps (func_id, core_type).

a2a3-only. a5's staging-ring model is different; out of scope here.

Commits

  1. Add: dep_gen captures per-subtask kernel_ids — extends DepGenRecord with int32_t kernel_id[3] (steals from _pad0[32]; sizeof and tensors[] offset unchanged). Orchestrator passes {aic, aiv0, aiv1}_kernel_id to dep_gen_aicpu_record_submit; replay emits kernel_ids in deps.json.

  2. Refactor: AICore buffer rotation via self-signal — Adds L2SwimlaneAicoreSignal 64B cacheline to L2SwimlaneAicoreTaskPool (pool 192B → 256B). AICore writes buf_full_seq when emitting last slot; scheduler calls new l2_swimlane_aicpu_poll_aicore_rotation once per main loop. Removes the piggy-back trigger in complete_task. Separate cacheline avoids false sharing with AICPU's per-task stats writes.

  3. Refactor: AICore record self-identifies + level=1 bypassL2SwimlaneAicoreTaskRecord replaces 32-bit task_id with 64-bit task_token_raw (still 32B half-cacheline). scheduler_completion + host_build_graph aicpu_executor gate entry into complete_task on level >= AICPU_TIMING. Host join key moves from per-core reg_task_id to full PTO2 task id (cleaner, runtime-agnostic).

  4. Add: level=1 host emit path (AICore-only synthesis)set_core_types() on collector + sim device_runner wiring. AICPU flush falls back to full-buffer count at level=1. export_swimlane_json synthesizes tasks[] from AICore records when collected_perf_records_ is empty and level == AICORE_TIMING; func_id emitted as -1 and joined from deps.json by swimlane_converter.py at post-process time (same model fanout already uses).

  5. Doc updatesprofiling_levels.md + docs/dfx/dep_gen.md.

Test plan

  • a2a3sim full dfx regression — pytest tests/st/a2a3/tensormap_and_ringbuffer/dfx --platform a2a3sim 7/7 pass
  • a2a3sim level=1 JSON inspection — 5 tasks for 5-task vector_example, each with full PTO2 task_id, derived ring_id, correct core_type (aiv), valid timing, func_id=-1 (to be joined from deps.json)
  • a2a3sim level=4 default — passes; task_id is full PTO2, ring_id decoded, all fields populated
  • a2a3 onboard — attempted via task-submit --device auto --device-num 2; both attempts hit halMemCtl rc=13 (EACCES) during register init before swimlane code is reached (device contention, npu-smi info shows all devices near 100% from other users). Reviewers should re-run when devices free up.

Related

🤖 Generated with Claude Code

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 06592bdf-00b5-468d-8e63-d5b2b26db7d8

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

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR refactors L2 swimlane profiling to encode full task tokens instead of low-word task IDs in AICore records, decouple buffer rotation from completion paths via explicit signaling and scheduler-loop polling, extend dependency records with per-subslot kernel IDs, and add host-side core-type mapping with a fallback JSON export path for minimal profiling levels.

Changes

Swimlane Task Identity, Signaling, and Rotation Refactor

Layer / File(s) Summary
Shared-memory data layout updates
src/a2a3/platform/include/common/dep_gen.h, src/a2a3/platform/include/common/l2_swimlane_profiling.h
DepGenRecord gains kernel_id[3] array with adjusted padding; L2SwimlaneAicoreTaskRecord stores task_token_raw (64-bit) replacing task_id (32-bit); new L2SwimlaneAicoreSignal cacheline struct introduced; L2SwimlaneAicoreTaskPool layout reorganized to place aicore_sig between head and free_queue, moving offsets and increasing total size.
AICore task recording with token and buffer-full signal
src/a2a3/platform/include/aicore/l2_swimlane_collector_aicore.h
Function signature updated to accept task_token_raw (64-bit) instead of task_id; record write path now publishes buffer-full rotation signal to dedicated L2SwimlaneAicoreSignal cacheline when buffer reaches last slot via dcci+dsb instruction sequence.
Dependency record kernel ID capture
src/a2a3/platform/include/aicpu/dep_gen_collector_aicpu.h, src/a2a3/platform/shared/aicpu/dep_gen_collector_aicpu.cpp, docs/dfx/dep_gen.md
dep_gen_aicpu_record_submit extended with kernel_ids[3] parameter (AIC/AIV0/AIV1 subslot identifiers); record path writes kernel IDs to output record or -1 for inactive subslots; documentation clarifies kernel-ID inclusion for post-processing task-to-kernel mapping.
Buffer rotation polling decoupled from completion
src/a2a3/platform/include/aicpu/l2_swimlane_collector_aicpu.h, src/a2a3/platform/shared/aicpu/l2_swimlane_collector_aicpu.cpp
New l2_swimlane_aicpu_poll_aicore_rotation() function polls per-core buf_full_seq advances and triggers rotations independently; per-core observed-sequence cache tracks last seen value; complete_task no longer triggers rotation, only increments head counter; flush count calculation becomes level-dependent (formula-based at AICPU_TIMING, constant otherwise).
Host-side record joining and JSON export
src/a2a3/platform/include/host/l2_swimlane_collector.h, src/a2a3/platform/shared/host/l2_swimlane_collector.cpp, src/a2a3/platform/sim/host/device_runner.cpp
New set_core_types() API publishes per-core type table; join_aicore_records() join key changed from reg_task_id to task_token_raw hashmap; export validation extended to treat collected_aicore_records_ as sufficient data at AICORE_TIMING level; fallback export path synthesizes tasks[] directly from AICore records when perf records are absent, using core_types_ for metadata.
Scheduler loop level gating and polling
src/a2a3/runtime/tensormap_and_ringbuffer/runtime/scheduler/scheduler_dispatch.cpp, src/a2a3/runtime/tensormap_and_ringbuffer/runtime/scheduler/scheduler_completion.cpp, src/a2a3/runtime/host_build_graph/aicpu/aicpu_executor.cpp, src/a2a3/runtime/tensormap_and_ringbuffer/aicore/aicore_executor.cpp, src/a2a3/runtime/host_build_graph/aicore/aicore_executor.cpp
Scheduler dispatch loop adds polling call to l2_swimlane_aicpu_poll_aicore_rotation() once per iteration; AICPU completion recording across multiple executor contexts gated on l2_swimlane_level >= AICPU_TIMING instead of just enabled flag, making Level 1 bypass complete_task entirely; AICore recording calls now pass full task_token_raw extracted from dispatch context.
Documentation and runtime call-site updates
src/a2a3/runtime/tensormap_and_ringbuffer/docs/profiling_levels.md, src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.cpp, src/a2a3/runtime/tensormap_and_ringbuffer/host/dep_gen_replay.cpp
Profiling levels documentation updated to reflect Level 1 AICore-only timing with task_token_raw, host-side field derivation, and polling-based buffer rotation; weak stub and submit_task_common call site updated to capture and forward kernel IDs; dep_gen_replay extended to populate and emit kernel_ids JSON field.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • hw-native-sys/simpler#939: Both PRs modify the L2 swimlane AICore/AICPU profiling structures and buffer-rotation mechanisms; this PR's task-identity and buffer-full signaling builds on that PR's ActiveHead pool unification.
  • hw-native-sys/simpler#942: This PR's AICore swimlane task-recording signature and buffer-rotation refactoring build on that PR's earlier swimlane "rotation→active head" refactor that also modified l2_swimlane_aicore_record_task.

Poem

🐰 Task tokens grow to sixty-four bits wide,
Signal cachelines guide the rotation tide,
Scheduler polls while AICore writes far,
Kernel IDs map each subslot by char—
Host-side synthesis brings clarity's light,
One level cleaner, profiling done right! 🎯

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly identifies the main refactoring work: decoupling AICore buffer rotation from complete_task and enabling level=1 to bypass AICPU processing entirely via self-identifying AICore records.
Description check ✅ Passed The PR description is comprehensive and directly related to the changeset, covering the rationale, commit structure, test results, and follow-up work for the swimlane refactoring across multiple files and subsystems.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request optimizes and decouples the L2 swimlane profiling mechanism, particularly for AICORE_TIMING (level 1). It introduces a direct buffer-rotation signaling mechanism (L2SwimlaneAicoreSignal) from AICore to AICPU, allowing level 1 profiling to bypass the expensive AICPU complete_task hot path. It also updates schemas to carry the full 64-bit task_token_raw so that host-side post-processing can resolve task-to-kernel mappings. The reviewer identified two critical issues: a static array (s_observed_aicore_buf_full_seq) is not reset during initialization, which can cause incorrect buffer rotations on subsequent runs, and base_time_cycles remains uninitialized at level 1, leading to timestamp underflow and broken timeline alignments in the exported JSON.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/a2a3/platform/shared/aicpu/l2_swimlane_collector_aicpu.cpp
Comment thread src/a2a3/platform/shared/host/l2_swimlane_collector.cpp
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/a2a3/runtime/host_build_graph/aicpu/aicpu_executor.cpp (1)

745-781: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Add AICore rotation polling to host_build_graph at AICORE_TIMING (level=1)

At L2SwimlaneLevel::AICPU_TIMING gating blocks in src/a2a3/runtime/host_build_graph/aicpu/aicpu_executor.cpp (~745-781, ~853-872, ~899-915), l2_swimlane_aicpu_complete_task is skipped when l2_swimlane_level < AICPU_TIMING (so level=1 bypasses it). However, AICore-side buffer rotation is decoupled from l2_swimlane_aicpu_complete_task and is driven by l2_swimlane_aicpu_poll_aicore_rotation (reads aicore_sig.buf_full_seq and calls aicore_rotate; aicore_rotate is only called from that poll). That poll is called from the tensormap_and_ringbuffer scheduler (scheduler_dispatch.cpp), but there is no call to it anywhere in src/a2a3/runtime/host_build_graph/, so rotations won’t happen during the run—only the end-of-run l2_swimlane_aicpu_flush enqueues the current AICore buffer (capacity PLATFORM_AICORE_BUFFER_SIZE = 1024).
Add l2_swimlane_aicpu_poll_aicore_rotation(...) to the host_build_graph executor’s main loop so level=1 still rotates buffers as AICore fills them.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/a2a3/runtime/host_build_graph/aicpu/aicpu_executor.cpp` around lines 745
- 781, The host_build_graph AICPU executor loop is not calling
l2_swimlane_aicpu_poll_aicore_rotation, so AICore buffer rotations never occur
at L2SwimlaneLevel::AICPU_TIMING (level=1); add a call to
l2_swimlane_aicpu_poll_aicore_rotation(...) inside the executor main loop (near
the existing l2_swimlane_aicpu_complete_task calls in the AICPU handling blocks)
guarded by l2_swimlane_level >= L2SwimlaneLevel::AICPU_TIMING so rotations are
polled each iteration (use the same core_id/thread_idx/dispatch timestamp
context as the surrounding code and ensure dispatch_timestamps_ semantics are
preserved).
🧹 Nitpick comments (1)
src/a2a3/platform/include/aicore/l2_swimlane_collector_aicore.h (1)

138-144: 💤 Low value

Consider replacing magic number with sizeof(L2SwimlaneActiveHead).

The + 64 offset is correct per the static_assert ABI lock, but using sizeof(L2SwimlaneActiveHead) would make the relationship explicit and self-documenting if the struct ever changes (the static_assert would catch any mismatch).

♻️ Optional refactor
         __gm__ L2SwimlaneAicoreSignal *sig =
-            reinterpret_cast<__gm__ L2SwimlaneAicoreSignal *>(reinterpret_cast<__gm__ uint8_t *>(head) + 64);
+            reinterpret_cast<__gm__ L2SwimlaneAicoreSignal *>(reinterpret_cast<__gm__ uint8_t *>(head) + sizeof(L2SwimlaneActiveHead));
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/a2a3/platform/include/aicore/l2_swimlane_collector_aicore.h` around lines
138 - 144, The code uses a magic offset "+ 64" to compute the
L2SwimlaneAicoreSignal pointer from head; replace that hard-coded 64 with
sizeof(L2SwimlaneActiveHead) to document the ABI relationship and keep the
static_assert meaningful—update the expression that builds sig (the
reinterpret_cast sequence referencing head) to add sizeof(L2SwimlaneActiveHead)
instead of 64, ensure L2SwimlaneActiveHead is visible/forward-declared in this
header so sizeof is available, and leave the existing static_assert and
assignment to sig->buf_full_seq (and subsequent dcci/dsb calls) unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/a2a3/platform/shared/host/l2_swimlane_collector.cpp`:
- Around line 900-935: The base_time_cycles fallback causes underflow because
collected AICore records aren't considered when l2_swimlane_level_ ==
L2SwimlaneLevel::AICORE_TIMING; update the base_time_cycles computation to also
scan collected_aicore_records_ and take the minimum start_time (same min logic
used for tagged_records/phase records) when in that mode. Specifically, after
the phase-record base_time calculation (the block that currently computes
base_time_cycles from tagged_records and phase records), add a loop over
collected_aicore_records_ (iterating core_id 0..num_aicore_-1 and each r in
collected_aicore_records_[core_id]) that skips r.start_time==0 and sets
base_time_cycles = std::min(base_time_cycles, r.start_time); this ensures
cycles_to_us(r.start_time - base_time_cycles) cannot underflow in the
AICORE_TIMING fallback.

---

Outside diff comments:
In `@src/a2a3/runtime/host_build_graph/aicpu/aicpu_executor.cpp`:
- Around line 745-781: The host_build_graph AICPU executor loop is not calling
l2_swimlane_aicpu_poll_aicore_rotation, so AICore buffer rotations never occur
at L2SwimlaneLevel::AICPU_TIMING (level=1); add a call to
l2_swimlane_aicpu_poll_aicore_rotation(...) inside the executor main loop (near
the existing l2_swimlane_aicpu_complete_task calls in the AICPU handling blocks)
guarded by l2_swimlane_level >= L2SwimlaneLevel::AICPU_TIMING so rotations are
polled each iteration (use the same core_id/thread_idx/dispatch timestamp
context as the surrounding code and ensure dispatch_timestamps_ semantics are
preserved).

---

Nitpick comments:
In `@src/a2a3/platform/include/aicore/l2_swimlane_collector_aicore.h`:
- Around line 138-144: The code uses a magic offset "+ 64" to compute the
L2SwimlaneAicoreSignal pointer from head; replace that hard-coded 64 with
sizeof(L2SwimlaneActiveHead) to document the ABI relationship and keep the
static_assert meaningful—update the expression that builds sig (the
reinterpret_cast sequence referencing head) to add sizeof(L2SwimlaneActiveHead)
instead of 64, ensure L2SwimlaneActiveHead is visible/forward-declared in this
header so sizeof is available, and leave the existing static_assert and
assignment to sig->buf_full_seq (and subsequent dcci/dsb calls) unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5f4fb728-77e3-424a-b130-7e41019a25f3

📥 Commits

Reviewing files that changed from the base of the PR and between d61dee4 and 8a19d8a.

📒 Files selected for processing (19)
  • docs/dfx/dep_gen.md
  • src/a2a3/platform/include/aicore/l2_swimlane_collector_aicore.h
  • src/a2a3/platform/include/aicpu/dep_gen_collector_aicpu.h
  • src/a2a3/platform/include/aicpu/l2_swimlane_collector_aicpu.h
  • src/a2a3/platform/include/common/dep_gen.h
  • src/a2a3/platform/include/common/l2_swimlane_profiling.h
  • src/a2a3/platform/include/host/l2_swimlane_collector.h
  • src/a2a3/platform/shared/aicpu/dep_gen_collector_aicpu.cpp
  • src/a2a3/platform/shared/aicpu/l2_swimlane_collector_aicpu.cpp
  • src/a2a3/platform/shared/host/l2_swimlane_collector.cpp
  • src/a2a3/platform/sim/host/device_runner.cpp
  • src/a2a3/runtime/host_build_graph/aicore/aicore_executor.cpp
  • src/a2a3/runtime/host_build_graph/aicpu/aicpu_executor.cpp
  • src/a2a3/runtime/tensormap_and_ringbuffer/aicore/aicore_executor.cpp
  • src/a2a3/runtime/tensormap_and_ringbuffer/docs/profiling_levels.md
  • src/a2a3/runtime/tensormap_and_ringbuffer/host/dep_gen_replay.cpp
  • src/a2a3/runtime/tensormap_and_ringbuffer/runtime/pto_orchestrator.cpp
  • src/a2a3/runtime/tensormap_and_ringbuffer/runtime/scheduler/scheduler_completion.cpp
  • src/a2a3/runtime/tensormap_and_ringbuffer/runtime/scheduler/scheduler_dispatch.cpp

Comment thread src/a2a3/platform/shared/host/l2_swimlane_collector.cpp
Threads the orchestrator-side kernel_id triple into each DepGenRecord so
the host post-processor can resolve (task_id -> kernel) offline. This is
the identity-side groundwork for the upcoming swimlane refactor that
moves AICore self-identification out of the AICPU complete_task hot path
-- the AICore record will carry only timing + task_token_raw, and the
viewer will join func_id from deps.json the same way fanout already does.

Schema change is in-place: 12B kernel_id[3] steals from _pad0[32], so
sizeof(DepGenRecord) stays 2624B and tensors[] stays cache-line aligned
at offset 576 (static_asserts unchanged). Replay emits kernel_ids in
the JSON tasks[] entries; INVALID_KERNEL_ID (-1) marks inactive subslots.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hw-native-sys-bot hw-native-sys-bot force-pushed the swimlane-aicore-self-id branch from 8a19d8a to b5c0eac Compare June 3, 2026 00:40
ChaoWao and others added 2 commits June 3, 2026 09:00
Decouple AICore buffer rotation from the AICPU complete_task hot path.
Previously every complete_task bumped ac_state->head.total_record_count
and, every PLATFORM_AICORE_BUFFER_SIZE-th completion, called aicore_rotate.
This trigger required complete_task to run on every FIN, blocking the
upcoming AICORE_TIMING (level=1) bypass.

New mechanism: AICore writes a fresh seq into a dedicated 64B signal
cache line (L2SwimlaneAicoreSignal, sitting between head and free_queue
in L2SwimlaneAicoreTaskPool) the moment it emits the last slot of its
current buffer. The scheduler main loop calls
l2_swimlane_aicpu_poll_aicore_rotation once per iteration -- one rmb +
per-owned-core compare -- and rotates whenever the observed seq advances.
Separate cache line keeps AICore's dcci CACHELINE_OUT from clobbering
AICPU's per-task stats writes to head under software-managed coherence.

Side effects:
- Pool size 192B -> 256B (head 64 + aicore_sig 64 + free_queue 128);
  static_asserts updated. Host allocator uses sizeof() so it picks
  the new size automatically.
- AICPU stats counter (total_record_count) still bumps in complete_task
  so host reconciliation (total == collected + dropped) keeps reporting
  per-AICore-pool counts at level >= 2. At level=1 (future Phase 2) it
  will stop bumping; host will surface the gap as silent_loss = 0 if
  reconcile uses the AICore-pool counter instead, or as the existing
  AICPU-pool counter otherwise.
- Closes the dispatch-boundary race the counter-based trigger had under
  sub-µs kernels (AICore now signals from the slot write itself, not
  from a monotonic FIN counter that could fall behind AICore's fill).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…es complete_task

Two coupled changes:

1) AICore record schema (L2SwimlaneAicoreTaskRecord) replaces the 32-bit
   `task_id` (low bits of the per-core reg dispatch token) with a 64-bit
   `task_token_raw` carrying the full PTO2 encoding (ring_id << 32 |
   local_id) for tensormap_and_ringbuffer, or the zero-extended task index
   for host_build_graph. Record stays 32B half-cache-line. The AICore
   helper reads `task_token` straight from
   `exec_payload->local_context.async_ctx.task_token.raw` -- already in
   AICore cache from the just-completed task, so the new identity comes
   at no extra GM load. Layout invariants (sizeof == 32) hold.

2) scheduler_completion + host_build_graph aicpu_executor: gate the entry
   into `l2_swimlane_aicpu_complete_task` on
   `l2_swimlane_level >= AICPU_TIMING`. At AICORE_TIMING (level=1) the
   AICore record alone carries identity; AICPU adds nothing useful and
   the per-completion hot path (counter inc, ring lookup, identity store,
   wmb) is elided entirely. Phase 3's signal-based AICore rotation makes
   this safe -- rotations no longer piggy-back on complete_task.

Host collector: join key moves from per-core `reg_task_id` (low 32) to
the full PTO2 `task_id`. AICore record's `task_token_raw` matches the
AICPU record's `task_id`; both are 64-bit, both are the canonical
identity. The kDirectIndexCap vector fast path goes away -- PTO2 task ids
are sparse high values, so unordered_map is the right structure.

Known follow-up (next commit in this PR): at level=1 there are no AICPU
records, so the host emit loop currently produces zero tasks[] entries.
The Phase 4 commit adds an AICore-records-only path that synthesizes
JSON entries from {task_token_raw, start, end} + dep_gen kernel_ids[]
+ host-side core_id -> core_type derivation, making level=1 useful
end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hw-native-sys-bot hw-native-sys-bot force-pushed the swimlane-aicore-self-id branch from b5c0eac to 74587da Compare June 3, 2026 01:02
ChaoWao and others added 2 commits June 3, 2026 10:41
Make AICORE_TIMING (level=1) useful end-to-end by synthesizing JSON
tasks[] entries from the AICore record stream alone -- no AICPU records
exist at this level because complete_task is bypassed by Phase 1+2.

Three pieces:

1. set_core_types(types, n) on L2SwimlaneCollector + sim device_runner
   call. Sim populates from runtime.workers[i].core_type. Onboard not
   wired in this commit (its workers[].core_type is established via
   AICore handshake which races with init_l2_swimlane); the existing
   level>=2 path on onboard still works because AICPU records carry
   core_type directly. Onboard level=1 wiring is a follow-up.

2. AICPU flush path falls back to enqueueing the full buffer
   (count=PLATFORM_AICORE_BUFFER_SIZE) at level=1 instead of the
   total_record_count-based live count, since complete_task -- where
   total_record_count is bumped -- is bypassed at level=1. The host
   copy_aicore_buffer already skips trailing slots with start_time==0,
   so over-stating count costs only a scan pass, not spurious records.

3. export_swimlane_json: when collected_perf_records_ is empty AND level
   == AICORE_TIMING, synthesize one task[] entry per AICore record from
   {task_token_raw, start, end} + the published core_types_ table for
   core_type. func_id is emitted as -1; swimlane_converter.py joins it
   from deps.json by task_id (same pattern fanout already uses).

Verified: at level=1 the JSON has 5 tasks for the 5-task vector_example,
each with the full PTO2 task_id, derived ring_id, correct core_type
("aiv"), and valid timing. level>=2 paths unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ctor

- profiling_levels.md: level 1 row now says "AICore timing only,
  complete_task bypassed"; new paragraph on how host derives
  func_id (deps.json kernel_ids[]) and core_type
  (L2SwimlaneCollector::set_core_types) at level 1; describes the
  buf_full_seq + scheduler poll rotation mechanism.

- dep_gen.md: capture call site row notes the new a2a3-only
  kernel_id[3] field and its role as the swimlane identity bridge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hw-native-sys-bot hw-native-sys-bot force-pushed the swimlane-aicore-self-id branch from 74587da to 20ba6a2 Compare June 3, 2026 02:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants