-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Motivation
VCD files are ASCII text and grow very large for non-trivial simulations. FST (Fast Signal Trace) is a binary format that achieves ~50x compression over VCD while supporting the same signal types.
Currently crun/circt-sim support --vcd <file>. Adding --fst <file> would make waveform dumps practical for larger designs.
Format comparison
| VCD | FST | SHM (Xcelium) | |
|---|---|---|---|
| Format | ASCII text | Binary (LZ4/gzip) | Proprietary binary |
| Compression vs VCD | 1x (baseline) | ~50x smaller | ~20-50x smaller |
| Open spec | Yes (IEEE 1364) | Yes (community) | No (Cadence proprietary) |
| Viewers | Everything | GTKWave, Surfer, VaporView | SimVision only |
| Write library | Trivial | Drop-in C lib | Cadence PLI/VPI only |
| 4-state support | Yes | Yes | Yes |
| Real/string types | Limited | Yes | Yes |
| Random access | No (sequential) | Yes (block index) | Yes |
FST and SHM are roughly comparable in compression. FST's advantage is that it's open and has random access (seek to any time without reading from the start). SHM's advantage is tight SimVision integration and streaming during simulation.
For our use case, FST is the clear choice — it's the open-source standard that all the modern viewers support. Users who need SimVision would use --vcd and convert, or run on Xcelium directly.
FST ecosystem
Viewers that support FST:
- GTKWave (originator of the format)
- Surfer (modern Rust-based viewer)
- VaporView (VSCode extension)
Simulators that dump FST:
- Verilator (native)
- Icarus Verilog
- GHDL
- NVC
NOT supported by commercial tools — Verdi uses FSDB, SimVision uses SHM, DVE uses VPD. Users of those tools would continue using --vcd and converting.
Compression
Typical 50x reduction over VCD (delta encoding + LZ4/gzip). Concrete data point: 2GB VCD → 20-50MB FST (from Verilator issue #3168).
Implementation
FST has a self-contained C library: fstapi.h + fstapi.c + fastlz.c (~4K lines total). Drop-in, no external dependencies.
Write-side API:
void *ctx = fstWriterCreate("output.fst", 1);
fstWriterSetTimescale(ctx, -9); // 1ns
fstHandle h = fstWriterCreateVar(ctx, FST_VT_VCD_WIRE, FST_VD_OUTPUT, width, "name", 0);
fstWriterEmitTimeChange(ctx, time);
fstWriterEmitValueChange(ctx, h, "10110100");
fstWriterClose(ctx);Integration points
- Register signals during
SimulationContext::initialize()(same as VCD) - Emit value changes in the signal-drive path (same as VCD)
- Add
--fst <file>cl::opt alongside existing--vcd - Estimated effort: ~200-300 lines of glue code
References
- Format spec: https://blog.timhutt.co.uk/fst_spec/
- GTKWave source:
gtkwave/src/helpers/fst/fstapi.c - Verilator wrapper:
verilated_fst_c.h