Fast Signal Trace reader/writer for Ruby
This gem is a Ruby binding to the fstapi library designed by the GTKWave authors. It allows to read and write Fast Signal Trace (FST) format waveforms from Ruby.
FST is an open format for dumpfiles generated by EDA logic simulation tools such as GHDL, nvc or Icarus Verilog. It was created by the author of GTKWave in 2014 as an alternative to the VCD (Value Change Dump) file format. Unlike VCD, FST is a compressed binary format designed for very fast sequential and random access.
Although the FST format and library are widely used, there is unfortunately no documentation for the libfst library API (more details on this: FST API documentation · Issue #70 · gtkwave/gtkwave · GitHub). However, an unofficial specification of the format can be found at this address: https://blog.timhutt.co.uk/fst_spec/.
A similar binding for Python can be found here.
Examples
Write an FST file from Ruby
require 'libfst'
fst = LibFST::Writer.new 'out.fst'
fst.set_date_string 'Wed Apr 17 21:40:39 2024'
fst.set_version_string __FILE__
fst.set_comment 'This is a comment'
fst.set_file_type :vhdl
fst.set_time_scale :ns
fst.set_scope(:vcd_module, name: 'testbench')
clk = fst.create_variable('clk', type: :sv_logic)
fst.set_scope(:vcd_module, name: 'uart')
rx = fst.create_variable('rx', type: :sv_logic, direction: :input)
data = fst.create_variable('data', type: :sv_logic, direction: :output, length: 8)
cnt = fst.create_variable('cnt', type: :vcd_integer)
fst.set_upscope
fst.set_scope(:vcd_module, name: 'analog')
ch0 = fst.create_variable('ch0', type: :vcd_real)
fst.set_upscope
fst.set_upscope
= 'Hello, world!'.bytes
clk_period = 1000
time = 0
fst.emit_time_change(time)
clock = 0
clk.value = clock
rx.value = 1
cnt.value = 0
counter = 0
byte = nil
bit_cnt = -2
loop do
time += clk_period
fst.emit_time_change(time)
ch0.value = 1.65 + 1.25*(Math.sin(2*Math::PI*4*time/1400000) + 0.5*(rand()-0.5))
clock ^= 1
clk.value = clock
counter += 1
if counter >= 10 then
counter = 0
bit_cnt += 1
if bit_cnt == -1 then # start bit
rx.value = 0
byte = .shift
elsif bit_cnt < 8 then
break if byte.nil?
rx.value = byte[bit_cnt]
elsif bit_cnt == 8 then # stop bit 1
rx.value = 1
data.value = byte
else # stop bit 2
bit_cnt = -2
end
end
cnt.value = counter
end
fst.close # finalize the output file
# The writer instance should not be used after it has been closed
Opening the output file out.fst with GTKWave gives something like this:

Read an FST file from Ruby
Install
LibFST can be installed from rubygems.org:
gem install libfst
Build from sources
Package the gem file and install it:
git clone https://gitlab.ensta-bretagne.fr/bollenth/libfst.rb.git
cd libfst.rb
gem build libfst.gemspec
gem install --local ./libfst-*.gem
Build the documentation:
# Install Yard if you don't have it already
gem install yard
# Generate the documentation
cd libfst.rb
yard
# View the doc
firefox doc/index.html