feat(cosim): live signal/video streaming tap#182
Closed
robtaylor wants to merge 4 commits into
Closed
Conversation
Design note for an observe-only streaming tap that samples a bundle of chip output pins per-tick and streams them out a UNIX socket to an external renderer (first use: live C64 video debug view). Reuses the existing per-edge vcd_snapshot ring (no GPU code); adds a socket sink beside the output-VCD writer in the cosim drain loop. Records the three trigger modes (strobe / clock+divider / every-N) and why strobe-gating dissolves the multi-clock sampling problem, plus the verified post-PnR net names for the C64 case (enablepixel strobe, bidir_CORE2PAD[n] pad values, bidir_CORE2PAD_OE[n] for later CIA work). Rejects QEMU virtio/vhost for this use (untimed, wrong granularity). Co-developed-by: Claude Code v2.1.203 (claude-opus-4-8[1m])
Adds a live streaming tap to `jacquard cosim`: sample a configured bundle of design output nets per triggered edge and stream packed bytes out a UNIX-domain socket to an external process (first use: a live C64 video debug view of colorIndex[3:0] + hsync/vsync). Reuses the existing per-edge vcd_snapshot ring — no GPU code — and drives nothing, so it imposes no batch=1 penalty; latency is one batch, with drop-on-backpressure. Trigger modes: `strobe` (gate on a design net's rising edge, correct under any clock topology) and `every: N` (count scheduler edges). A domain-relative `clock`/`divider` mode is left as a documented follow-up. - testbench: SignalStreamConfig + StreamTrigger enum + signal_streams field - signal_stream.rs: Sampler (trigger + LSB-first packing) behind a socket front end; reuses EdgeDetector for the strobe; packs in place (no per-edge alloc); documented wire format - jacquard.rs: tap bundle signals registered as observables pre-partition - mod.rs: taps built/resolved, ring enabled, per-edge sample + per-batch flush in the shared drain loop Design: docs/spikes/video-streaming-tap.md. Co-developed-by: Claude Code v2.1.203 (claude-opus-4-8[1m])
Spike artifacts for the cosim signal-streaming tap, runnable end-to-end: - video-streaming-tap/c64_video_renderer.py — live pygame renderer (uv PEP 723 script); reads the tap socket, frames on hsync/vsync, applies the C64 palette, auto-reconnects on backpressure drop - video-streaming-tap/example-signal-streams.json — signal_streams block for the C64 cocotb/sim_config.json, using the verified post-PnR net names (enablepixel strobe, bidir_CORE2PAD[1..6] video pads) - video-streaming-tap/README.md — run steps + the colorIndex bit-order open question C64-specific; will move to the c64-tapeout project. Kept here for now so the spike is runnable. Co-developed-by: Claude Code v2.1.203 (claude-opus-4-8[1m])
Self-contained pickup instructions for a fresh session: build the feature branch, resolve-check the C64 net names, merge the config fragment, run cosim + renderer, and troubleshoot (bit order, black window, unresolved nets). Also documents the unit-test commands and the manual e2e step. Co-developed-by: Claude Code v2.1.203 (claude-opus-4-8[1m])
d3e34a1 to
1516336
Compare
Contributor
Author
robtaylor
added a commit
that referenced
this pull request
Jul 9, 2026
The README's PR reference was stale after the branch was retargeted to main (superseding the auto-closed #182). Co-developed-by: Claude Code v2.1.203 (claude-opus-4-8[1m])
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
Adds an observe-only streaming tap to
jacquard cosim: sample a configured bundle of chip output pins per-tick and stream them out a UNIX-domain socket to an external process (first use: a live C64 video debug view ofcolorIndex[3:0]+hsync/vsync).Design note:
docs/spikes/video-streaming-tap.md.Why
Cosim can already surface internal nets per-tick via
--trace-signals(GPU ring buffer), but only to a VCD file. This exposes the same per-tick capture as a live stream so a separate renderer can visualise output pins in near-real-time. The driving case is C64 video: the chip emits a 4-bit palette index + H/V sync, and an external renderer does the palette lookup + display.QEMU virtio/vhost was considered and rejected for this use (untimed, wrong granularity) — see the spike.
Approach
vcd_snapshotring; no GPU code.run_cosim_generic,src/sim/cosim/mod.rs).batch=1penalty; latency is one batch, drop-on-backpressure.strobe(gate on a design net, dissolves multi-clock) /every: N.The generic feature lands here; the C64-specific config + Python renderer live in the c64-tapeout project.
Wire format
Per batch that produced samples:
[u64 first_tick LE][u32 sample_count LE][sample_count × ceil(n_signals/8) bytes], each sample packed LSB-first in config order. Thefirst_tickheader lets a renderer resync after a dropped batch.Status
Draft — feature implemented, built (
--features metal) and unit-tested; end-to-end render pending (lands with the c64 renderer).SignalStreamConfig+StreamTriggerenum) + parse testssignal_stream.rs) + trigger/packing unit testsresolve_to_state_posobservable path)strobe+every/simplifypass (reuseEdgeDetector, in-place packing, flatten resolve loop)clock+dividertrigger mode