Waveform Tracing

Overview

(Bad) example here.

You can open a VCD for a Verilated model using the .open_vcd function, which takes in anything that can turn into a Path. The .dump and other functions are bridged directly to the Verilator functions and, as such, will behave as you expect (but through a safe Rust API).

The VCD is automatically closed and deallocated when out of scope. Lifetimes enforce that you cannot use the VCD past the scope of the runtime whence the model you created the VCD came.

Until https://github.com/verilator/verilator/issues/5813 gets fixed, .open_vcd will panic if you call it more than once.

You can consult the reference documentation for VCDs here.

Tips

You might find yourself wanting to write a function on your model (let's say you declared it as struct Top) to simulate a clock cycle. You will need to remember to update the VCD. For instance:

impl Top<'_> {
    fn tick(&mut self, vcd: &mut Vcd<'_>, timestamp: &mut u64) {
        self.clk = 0;
        self.eval();
        *timestamp += 1;
        vcd.dump(*timestamp);
        self.clk = 1;
        self.eval();
        *timestamp += 1;
        vcd.dump(*timestamp);
    }
}

You could also wrap the Vcd in another struct:

pub struct GoodVcd<'a> {
    inner: Vcd<'a>,
    timestamp: u64,
}

impl<'a> From<Vcd<'a>> for GoodVcd<'a> {
    fn from(vcd: Vcd<'a>) -> Self {
        Self {
            inner: vcd,
            timestamp: 0,
        }
    }
}