Skip to content

Waveform GUI: Tywaves‐rs and Surfer

Raffaele Meloni edited this page Jun 24, 2024 · 4 revisions

Table of Contents

Waveform GUI

The waveform visualization covers a significant role in the project since it represents the part of interaction with the user. There exist several open-source waveform viewers on the market, as explained in the software architecture section, Surfer was chosen as visualizer for the project since, unlike GTKWave, it is built with a focus on extensibility, providing a more straightforward way to add new features.

In the following sections, I present a library for tywaves which Surfer can use to read and manipulate the debug information emitted by the Chisel compiltion, and the changes in Surfer to support typed visualizations.

Tywaves-rs

Surfer is written in Rust, so I implemented Tywaves-rs, a Rust library to support the tywaves project. The library implements internally 3 submodules:

  • hgldd: an api to parse multiple HGLDD files and convert them into a well-defined data structure in Rust using serde. As an additional contribution, I tried to document HGLDD more clearly with rust doc.
  • tyvcd: an internal IR to represent a full hierchical circuit with typed signals linked with the values from a trace file, with a more efficient, more generic and more stable representation than HGLDD. It also contains a trait for creating TyVcd from other data structures (tyvcd::builder::GenericBuilder).
  • vcd_rewrite: implements a VCD re-writer basing on the original hierarchical representation of the circtui. It converts a VCD file with flattened signals into a new file with their values concatenated in a single signal following the hierarchy of the original circuit stored in TyVcd.

Tyvcd and Tyvcd builder

The HGLDD format is neither under my direct control nor under the control of the surfer development team nor a stable standard (yet). Therefore, if surfer uses that representation directly, a change on it may break the viewer entirely, likely requiring significant changes. Having a more efficient, multithreaded intermediate representation is a better choice. Doing so allows decoupling Surfer from HGLDD, such that a change in HGLDD will not require significant changes in Surfer nor Tyvcd but only in the parser and builder of tywaves-rs.

The builder system offers a common trait (GenericBuilder) and a struct with generics (TyVcdBuilder<T>) to build tyvcd from multiple data structures. This supports the extension to future new input formats, not only HGLDD, while keeping the Surfer side unchanged.

/// Trait for a generic TyVcd builder.
pub trait GenericBuilder {
  fn build(&mut self) -> Result<()>;
  fn get_ref(&self) -> Option<&TyVcd>;
  fn get_copy(&self) -> Option<TyVcd>;
}

/// A concrete builder for the TyVcd object.
pub struct TyVcdBuilder<T> {
  // The input list of objects from which the TyVcd object will be built
  origin_list: Vec<T>,
  // The target TyVcd object
  tyvcd: Option<TyVcd>,
}

impl GenericBuilder for TyVcdBuilder<Hgldd> {
  // ... 
}

Hgldd documentation

The HGLDD file format does not have a formal specification yet rather than the comments in the source code. Thus, this library tried to extract the information from the code and document it more clearly with rust doc. The documentation is available through documenting the Hgldd struct itself. Here, an example of it:

hgldd-doc

It is not published in crates.io yet, but it can be compiled locally:

git clone https://github.com/rameloni/tywaves-rs.git
cd tywaves-rs
cargo doc --open

Vcd rewrite

The 3rd submodule in the library implements a VCD re-writer which concatenates all the flattened fields of an aggregate signal from the source VCD into a single value.

For example, given the following aggregate in hgldd the resulting VCD file will be rewritten as follows:

{
  "var_name": "io",
  "value": {
    "opcode": "'{",
    "operands": [
      {"sig_name":"io_a"},
      {"sig_name":"io_b"},
      {"sig_name":"io_c"}
    ]
  },
}
Original VCD Rewritten VCD
 $var wire 4 # io_a $end
$var wire 4 ! io_b $end
$var wire 1 & io_c $end

#0
b0010 #
b1100 !
1&
 $var wire 9 # io $end

#0
b001011001 #

Reasons for a separate library

Changes in Surfer

Thanks to tywaves-rs the changes in Surfer are minimal. They imply only:

  • The creation of a new translator TywavesTranslator implementing the Translator trait.
  • The addition of a new CLI option to specify an hgldd path (both a file and a dir containing multiple hgldds).