debugger: trigger-based VCD waveform export (logic analyser for GTKWave)#198
Merged
Conversation
Record internal hardware signals -- beam counters, chip-bus owner per colour clock, CPU chip-bus accesses, Copper PC/state, blitter pipeline slots and pointers, custom-register writes, IPL/INTREQ/INTENA, and audio DMA grants -- into a VCD file for GTKWave, like a logic analyser probing the chip bus. A capture arms with an output path, a trigger (now, pc=ADDR, beam=VPOS[:HPOS], reg=OFF, time=SECS), a bounded duration (cck, frames, ms, s; default one frame, capped at 10 emulated seconds), and a signal group selection. It is exposed three ways: --waveform/--wave-trigger/ --wave-duration/--wave-signals on the CLI (works headless), a WAVE START/STOP console command, and a new Wave tab in the debugger window. The sampler joins the existing gated instrumentation sinks at the chip-bus arbitration point in advance_one_chip_bus_quantum_limited; register writes and CPU grants tap their existing choke points. Every tap sits behind a plain wave_on bool, so the hot path costs a single branch while nothing is armed, and a capture observes without changing timing (the golden probe renders are unaffected). One VCD time unit is one colour clock, so GTKWave cursor deltas read directly in cck. The hand-rolled change-only VCD writer lives in src/waveform.rs with the trigger/duration/signal parsing and capture state machine; the bus-side taps live in src/bus/wave.rs. Documented in docs/debugger/waveform.md.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds a trigger-based waveform capture facility that records internal chipset activity into a bounded VCD file for viewing in GTKWave, exposed consistently across CLI, console, and the debugger UI.
Changes:
- Introduces a VCD writer + trigger/duration/signal parsing + capture state machine (
src/waveform.rs) and bus-side sampling/trigger taps (src/bus/wave.rs). - Adds new user-facing surfaces: CLI flags (
--waveform,--wave-trigger,--wave-duration,--wave-signals), consoleWAVEcommand, and a new debugger Wave tab with Arm/Stop. - Adds tests and documentation covering parsing, bus-level behavior, console lifecycle, and UI rendering.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/waveform.rs | New waveform capture core: options parsing, VCD writer, capture state machine, and unit tests. |
| src/bus/wave.rs | New bus-side waveform hooks: arming/stopping, trigger checks, and per-quantum sampling. |
| src/bus.rs | Adds bus fields for waveform capture state and wires the new wave module. |
| src/bus/dma_slots.rs | Calls per-quantum sampler from the chip-bus arbitration hot path when armed/capturing. |
| src/bus/custom_regs.rs | Hooks custom-register writes for reg= trigger and register-write sampling. |
| src/cpu.rs | Adds UI-facing wave start/stop/status APIs and a per-instruction PC-trigger tap gate. |
| src/chipset/copper.rs | Exposes a stable copper state label string for waveform export. |
| src/main.rs | Adds CLI parsing + help text for waveform capture flags and arms capture at startup. |
| src/lib.rs | Exposes the new waveform module publicly. |
| src/video/window/console.rs | Adds WAVE console command and shared waveform status line formatting. |
| src/video/window.rs | Hooks Wave tab Arm/Stop controls into the debugger dispatch and view rendering. |
| src/video/ui.rs | Adds the Wave tab, UI controls, button layout/rendering, and entry-box character allowance tweaks. |
| src/video/window/tests.rs | Adds integration-style tests for Wave tab dispatch and console WAVE lifecycle. |
| src/bus/tests.rs | Adds bus-level waveform capture tests for sampling and triggers. |
| docs/debugger/waveform.md | New documentation chapter for waveform export usage and reference. |
| docs/debugger/console.md | Documents the new console WAVE command. |
| docs/debugger/window.md | Documents the new debugger Wave tab behavior and entry syntax. |
| docs/debugger/workflows.md | Adds a workflow recipe for using waveform capture to analyze bus interleaving. |
| docs/guide/headless.md | Adds a headless waveform capture mention and example. |
| docs/myst.yml | Adds the waveform chapter to the docs navigation. |
| README.md | Mentions waveform export as part of the tooling feature set. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Reject odd reg= trigger offsets instead of silently rounding them down to the neighbouring word register. - Latch VCD write errors in the writer: a failed writer emits nothing further, the capture aborts at its next expiry check (instead of running on while silently truncating the file), the status reports "failed (write error)", and the finish path logs a warning. - Allow backslash in the debugger entry box so Windows paths can be typed on the Waveform tab.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Records Copperline's internal hardware signals into a VCD file for GTKWave (or any VCD viewer), like a logic analyser probing the chip bus -- plus internal state no real probe could reach:
Captures are trigger-based and bounded so files stay small: arm, wait for
now/pc=ADDR/beam=VPOS[:HPOS]/reg=OFF/time=SECS, record for a fixed window (cck/frames/ms/s, default one frame, hard-capped), finish the file. Signal groups are selectable.Surfaces
--waveform out.vcd --wave-trigger pc=0x00C033C2 --wave-duration 20000cck --wave-signals cpu,bus,copper,blitterWAVE START [PATH] [TRIGGER] [DURATION] [SIGNALS],WAVE STOP,WAVE-- arguments order-free, all optionalHow
The per-cck sampler joins the four existing gated instrumentation sinks at the chip-bus arbitration point (
advance_one_chip_bus_quantum_limited); register writes and CPU grants tap their existing choke points. Every tap sits behind a plainwave_onbool: the hot path costs a single branch while nothing is armed, and a capture observes without changing emulated timing. One VCD time unit = one colour clock (declared$timescale 1 us, the closest legal unit), so GTKWave cursor deltas read directly in cck. Timestamps are relative to the trigger.The hand-rolled change-only VCD writer, parsers, and capture state machine live in
src/waveform.rs(no new dependencies); the bus-side taps insrc/bus/wave.rs. Capture state is host-side observer state -- serde-skipped, noSTATE_VERSIONbump. FST output is documented via GTKWave's bundledvcd2fstrather than linking a C library.Tests
reg=trigger firing on the matching write; early stop + re-arm with a beam triggerpc=trigger firing on a stepped machinepanels_render_into_their_rects(preview PNG below), Arm/Stop through the full control dispatchcargo test --lib(1447),clippy --all-targets,fmt --check, and the release golden-probe suite all clean -- the golden renders confirm no timing changeVerified end-to-end
Booting
timing-test/ddfprobe.adfwith--wave-trigger time=45 --wave-duration 2fproduces a structurally valid VCD (monotonic stamps, exact window) showing bitplane DMA slots, per-frame Copper wait/run cycling, and the Copper's writes to BPLCONx, DIW/DDF, bitplane pointers, and COLORxx.Docs
New chapter
docs/debugger/waveform.md; command row inconsole.md; Wave tab inwindow.md; a workflows recipe; a pointer from the headless guide; README feature line.