Skip to content

feat(cosim): live signal/video streaming tap#182

Closed
robtaylor wants to merge 4 commits into
fix/qspi-shared-bus-dinfrom
feat/cosim-signal-stream-tap
Closed

feat(cosim): live signal/video streaming tap#182
robtaylor wants to merge 4 commits into
fix/qspi-shared-bus-dinfrom
feat/cosim-signal-stream-tap

Conversation

@robtaylor

@robtaylor robtaylor commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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 of colorIndex[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

  • Reuse the existing per-edge vcd_snapshot ring; no GPU code.
  • Add a socket sink beside the output-VCD writer in the shared drain loop (run_cosim_generic, src/sim/cosim/mod.rs).
  • Observe-only ⇒ no batch=1 penalty; latency is one batch, drop-on-backpressure.
  • Trigger modes: 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. The first_tick header 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).

  • Design spike
  • Config surface (SignalStreamConfig + StreamTrigger enum) + parse tests
  • Socket sink module (signal_stream.rs) + trigger/packing unit tests
  • Drain-loop wiring + signal resolution (reuses resolve_to_state_pos observable path)
  • Trigger modes: strobe + every
  • /simplify pass (reuse EdgeDetector, in-place packing, flatten resolve loop)
  • End-to-end: real cosim run streaming to a renderer (with the c64 config)
  • Follow-up: domain-relative clock + divider trigger mode

robtaylor added 4 commits July 9, 2026 15:38
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])
@robtaylor robtaylor force-pushed the feat/cosim-signal-stream-tap branch from d3e34a1 to 1516336 Compare July 9, 2026 14:40
@robtaylor robtaylor changed the base branch from main to fix/qspi-shared-bus-din July 9, 2026 14:40
@robtaylor robtaylor deleted the branch fix/qspi-shared-bus-din July 9, 2026 14:40
@robtaylor robtaylor closed this Jul 9, 2026
@robtaylor

Copy link
Copy Markdown
Contributor Author

Superseded by #184 — same branch, retargeted to main after #183 (the QSPI shared-bus fix it was stacked on) merged. GitHub auto-closed this when the base branch was deleted and wouldn't reopen cleanly.

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])
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