Skip to content

Arm the resident DFX collectors under the execution claim - #2163

Open
ChaoWao wants to merge 1 commit into
hw-native-sys:mainfrom
ChaoWao:dfx-arm-in-claim
Open

Arm the resident DFX collectors under the execution claim#2163
ChaoWao wants to merge 1 commit into
hw-native-sys:mainfrom
ChaoWao:dfx-arm-in-claim

Conversation

@ChaoWao

@ChaoWao ChaoWao commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

The DFX collectors are resident objects that serve every run, so opening a run's collection window is destructive: begin_run() drops the previous run's records and counters and republishes the level the device reads. That ran during prepare_execution, which on onboard can run for a successor while a predecessor is still executing.

This moves it to launch, where the run holds the execution claim and is the only run touching those collectors — and carries the run's own DFX configuration through launch and drain instead of reading the runner's members.

Part of #2078.

What changed

begin_run() × 5 collectors × 4 runners start_shared_collectors_for_run() on each base, beside the start() it belongs with
initialize() for chip-swimlane / args-dump takes the level as an argument, instead of reading what begin_run() latched
launch / drain / the two bracket helpers read PreparedExecution::dfx, not runner members
6 runner members dead as a result, removed with their setters
a5's PMU degradation dfx.pmu_enabled = false — a per-run value, no longer a runner-wide write

initialize() could not move with begin_run(): chip-swimlane sizes its orch phase pool from the level and args-dump writes it into DumpDataHeader, and its device pointers must be in kernel_args before that uploads at the end of prepare. Passing the level in removes the ordering constraint between two calls that no longer share state.

PreparedExecution already carried the run's CallConfig by value, so carrying DfxRunConfig needed no new plumbing.

Why the dead members go in this commit

enable_chip_swimlane_, enable_dump_args_, enable_pmu_, enable_scope_stats_, pmu_event_type_ and capture_clock_anchors_ are now write-only — every remaining occurrence is a declaration or a setter assignment, which is what let the compiler confirm the removal. A write-only enable_pmu_ on the runner is the exact shape of the defect this change is about: it reads as the source of truth and is not one. chip_swimlane_level_ stays (a device-context query answers from it) and output_prefix_ stays (host_phase_pool_arm() reads it).

What this does not do

The diagnostics depth-one gate stays. What remains behind it is pool construction, not per-run arming: a prepare whose collector shape differs from the resident one calls finalize_collectors(), which frees device memory the predecessor is using. That is a much narrower condition than "any diagnostic is on", and turning the gate into it is the next change on this line.

Sim takes the same shape but not the same fix. It acquires the execution claim at the top of simpler_prepare_run, so it never prepares a successor against a live predecessor. Keeping the two runner shapes identical is the point — see #2162.

Testing

Verified per DFX channel in the shapes _st-sim-{a2a3,a5}.yml uses. A bare sweep enables no channel and so cannot fail on a collector defect.

  • 12 channel runs, 23 cases, green on both sim platforms
  • Negative control fires on the relocated code: with begin_run() omitted from start_shared_collectors_for_run(), all 5 a5sim swimlane cases fail
  • Full sim sweeps green: 33 (a2a3sim) and 29 (a5sim) cases
  • pyut 2216 passed / 7 skipped
  • cpput 135/135 from a cleared build dir — which is what caught the three test call sites of the changed initialize()
  • a2a3 onboard smokes green under task-submit across PMU, chip_swimlane + dep_gen, hbg dep_gen and args_dump: 11 cases

Related: #2078, #2162

The collectors are resident objects that serve every run, so opening a
run's collection window is destructive: begin_run() drops the previous
run's records and counters and republishes the level the device reads.
That ran during prepare_execution, which on onboard can run for a
successor while a predecessor is still executing — it would have reset
the collectors out from under the live run.

Move it to launch, where the run holds the execution claim and is
therefore the only run touching those collectors. begin_run() now sits
beside the start() it belongs with, in start_shared_collectors_for_run()
on both bases, which collapses five per-runner copies into one per
platform. The level cannot move with it: chip-swimlane sizes its orch
phase pool from the level and args-dump writes it into DumpDataHeader,
and both happen in initialize(), which must stay in prepare because its
device pointers go into kernel_args before it uploads. So initialize()
takes the level as an argument instead of reading what begin_run()
latched, which also removes an ordering constraint between two calls
that no longer share state.

Launch and drain read the run's configuration from its own
PreparedExecution rather than from the runner, which needs no new
plumbing: PreparedExecution already carried the run's CallConfig by
value, so it now resolves DfxRunConfig from it at construction. The two
shared-collector bracket helpers and the host-phase-records writer take
it as an argument.

Six runner members are dead as a result — enable_chip_swimlane_,
enable_dump_args_, enable_pmu_, enable_scope_stats_, pmu_event_type_,
capture_clock_anchors_ — with every remaining occurrence a declaration
or a setter assignment. They are removed with their setters. Leaving a
write-only enable_pmu_ on the runner is the exact shape of the defect
this change is about: it reads as the source of truth and is not one.
chip_swimlane_level_ stays because a device-context query answers from
it, and output_prefix_ because host_phase_pool_arm() reads it.

a5's PMU degradation becomes a per-run value. When init_pmu fails, a5
disables PMU for that run rather than failing it; that flag was the one
DFX value prepare still wrote runner-wide, and it now lands on the run's
own dfx, which its arming and its teardown both read. a2a3 fails the
whole run on the same error — an undocumented arch divergence, filed as
part of hw-native-sys#2162 and left alone here.

This does not remove the diagnostics depth-one gate. What remains behind
it is pool construction, not per-run arming: a prepare whose collector
shape differs from the resident one calls finalize_collectors(), which
frees device memory the predecessor is using. That is a narrower
condition than "any diagnostic is on" and is the next change on this
line.

Sim takes the same shape but not the same fix: it acquires the execution
claim at the top of simpler_prepare_run, so it never prepares a
successor against a live predecessor. Keeping the two runner shapes
identical is the point — see hw-native-sys#2162.

Verified per DFX channel in the shapes _st-sim-{a2a3,a5}.yml uses; a bare
sweep enables no channel and cannot fail on a collector defect. 12
channel runs, 23 cases, green on both sim platforms. The negative control
fires on the relocated code: with begin_run() omitted from
start_shared_collectors_for_run(), all 5 a5sim swimlane cases fail.

Full sim sweeps green on both platforms (33 and 29 cases), pyut 2216
passed / 7 skipped, cpput 135/135 from a cleared build dir — which is
what caught the three test call sites of the changed initialize() — and
a2a3 onboard smokes green under task-submit across PMU, chip_swimlane +
dep_gen, hbg dep_gen and args_dump: 11 cases.
@coderabbitai

coderabbitai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: dc70e793-cad6-4872-b9f0-b2c9778c666b

📥 Commits

Reviewing files that changed from the base of the PR and between f7f4766 and 8aca858.

📒 Files selected for processing (18)
  • src/a2a3/platform/onboard/host/device_runner.cpp
  • src/a2a3/platform/onboard/host/device_runner.h
  • src/a2a3/platform/sim/host/device_runner.cpp
  • src/a2a3/platform/sim/host/device_runner.h
  • src/a5/platform/onboard/host/device_runner.cpp
  • src/a5/platform/onboard/host/device_runner.h
  • src/a5/platform/sim/host/device_runner.cpp
  • src/a5/platform/sim/host/device_runner.h
  • src/common/platform/include/host/args_dump_collector.h
  • src/common/platform/include/host/chip_swimlane_collector.h
  • src/common/platform/onboard/host/c_api_shared.cpp
  • src/common/platform/onboard/host/device_runner_base.cpp
  • src/common/platform/onboard/host/device_runner_base.h
  • src/common/platform/shared/host/args_dump_collector.cpp
  • src/common/platform/shared/host/chip_swimlane_collector.cpp
  • src/common/platform/sim/host/device_runner_base.cpp
  • src/common/platform/sim/host/device_runner_base.h
  • tests/ut/cpp/common/test_args_dump_collector.cpp

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

DFX configuration now lives on each PreparedExecution. Shared collectors use that configuration for initialization, launch, artifact output, and teardown across onboard and simulation runners. Collector initialization signatures now receive fixed diagnostic levels directly.

Changes

Per-run DFX lifecycle

Layer / File(s) Summary
Prepared execution DFX state
src/common/platform/**/host/device_runner_base.*, src/common/platform/onboard/host/c_api_shared.cpp
PreparedExecution stores DfxRunConfig. Shared collector start, teardown, and artifact methods now use per-run configuration.
Collector initialization contracts
src/common/platform/include/host/*collector.h, src/common/platform/shared/host/*collector.cpp, tests/ut/cpp/common/test_args_dump_collector.cpp
Args dump and chip swimlane levels move into initialization. Tests pass the new args dump level parameter.
Onboard runner integration
src/a2a3/platform/onboard/host/device_runner.*, src/a5/platform/onboard/host/device_runner.*
Onboard runners use prepared DFX flags for collector arming, dep_gen handling, output paths, and teardown.
Simulation runner integration
src/a2a3/platform/sim/host/device_runner.*, src/a5/platform/sim/host/device_runner.*
Simulation runners read DFX state from active prepared executions and use it during launch and drain.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Merge Risk: 🟡 Moderate · up to 8aca8

Runs that change chip-swimlane diagnostic level may continue using the prior run’s collector level, producing incomplete or incorrect diagnostics. This should be corrected before merge.

Sequence Diagram(s)

sequenceDiagram
  participant CallConfig
  participant PreparedExecution
  participant DeviceRunner
  participant Collectors
  CallConfig->>PreparedExecution: create DfxRunConfig
  PreparedExecution->>DeviceRunner: provide prepared.dfx
  DeviceRunner->>Collectors: begin_run and start
  DeviceRunner->>Collectors: teardown with dfx
  Collectors-->>DeviceRunner: write configured artifacts
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.51% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 82 functions across 18 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: moving resident DFX collector arming under the execution claim.
Description check ✅ Passed The description is directly related to the changeset. It explains the collector lifecycle change, per-run DFX configuration, removed runner state, and validation results.
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.
  • Fix all pre-merge checks with AI

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

A rabbit reads each line,
The patch grows clear beneath the moon,
Small changes hop in place,
Tests guard the garden path,
Reviews bloom before the dawn.

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

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.

1 participant