Wavedisp

Description

Wavedisp is a set of python classes to help you in creating waveform files used by HDL simulator or VCD viewers. It allows to select which signals from the design hierarchy you want to plot. It is easy to provide a wave file per HDL modules, include all of them in the same way you instantiated your components and produce a tcl script that will load all selected signals in your viewer.

Wavedisp python module provides nodes to describe the design hierarchy, grouping signals (in a foldable way), dividers and display signals. It can generate tcl scripts for GTKWave, Modelsim and RivieraPro (soon).

License

Wavedisp is distributed under the GPLv3, the complete license description can be found here.

Installation

Proceed as follow to install the package:


$ pip3 install [--user] wavedisp # --user for a local installation

How to describe a wave file

Write a first wave file

Usually, HDL projects provide multiple module/sub-modules and test benches. Let's suppose we have designed a dual clock FIFO that use two modules to encode and decode gray codes from/to binary codes.

The instance tree looks like to this:


dclkfifolut_tb (testbench)
 ├── dclkfifolut (Main component)
      ├── gray2bin
      ├── bin2gray

Moreover gray2bin and bin2gray modules also have test benches and we propose to describe the wave files for those modules.

Here after an example for the gray2bin wave file gray2bin.wave.py:


from wavedisp.ast import *

def generator():
    blk = Block()
    blk.add(Disp('gray', radix='hexadecimal'))
    blk.add(Disp('bin', radix='hexadecimal'))
    return blk

We notice that a wave file must import the Wavedisp abstract syntax tree (AST) classes and provides a generator function that returns the AST entry point.

The Disp node allows to plot signals with the desired radix. A radix is a property, two other properties exist: color and height. The Block node will not be directly reflected in the generated file, it provides only a way to force unset properties of its children with its own properties. All nodes able to hold children have the same behavior than the Block node regarding the properties inheritance.

The associated test bench gray2bin_tb.wave.py of the gray2bin module:


from wavedisp.ast import *

def generator():
    hier = Hierarchy('/gray2bin_tb')
    inst = hier.add(Hierarchy('gray2bin_inst'))
    inst.include('gray2bin_wave.py')
    return hier

In the test bench wave file, we declared the instance hierarchy with the Hierarchy node and we included the wave file of the tested component.

Note: It is recommended to always separate the wave file for the module from the wave file for the test bench, thus to reuse the module wave file in larger designs.

We can now call the wavedisp command line to generate our wavefile with the GTKWave target:


$ wavedisp -t gtkwave -o wave.tcl gray2bin_tb.wave.py

We obtained the following script that can be loaded with the "-T" option of gtkwave:


# Wavedisp generated gtkwave file
gtkwave::/Edit/Set_Trace_Max_Hier 0

gtkwave::addSignalsFromList [list {gray2bin_tb.gray2bin_inst.gray}]
gtkwave::/Edit/Data_Format/Hex {gray2bin_tb.gray2bin_inst.gray}
gtkwave::addSignalsFromList [list {gray2bin_tb.gray2bin_inst.bin}]
gtkwave::/Edit/Data_Format/Hex {gray2bin_tb.gray2bin_inst.bin}

gtkwave::/Edit/Set_Trace_Max_Hier 1

The wavedisp program can also generate a Graphviz diagram (dot) of the AST.


$ wavedisp -t dot -o wave.dot

Hereafter the generated wave.dot rendered with Graphviz (with the dot command line).

Responsive image

Include multiple wave files in a larger design

Let's suppose that we described one wave file per component, we can now proceed to the description of the wave file of our dual clock FIFO main module.

Here after the wave file dclkfifolut.wave.py:


from wavedisp.ast import *

def generator():
    block = Block()

    block.add(Disp('rclk', radix='binary'))
    block.add(Disp('rsrst', radix='binary'))
    block.add(Disp('ren', radix='binary'))
    block.add(Disp('rdata', radix='hexadecimal'))
    block.add(Disp('rlevel', radix='hexadecimal'))
    block.add(Disp('rempty', radix='binary'))
    block.add(Disp('wclk', radix='binary'))
    block.add(Disp('wsrst', radix='binary'))
    block.add(Disp('wen', radix='binary'))
    block.add(Disp('wdata', radix='hexadecimal'))
    block.add(Disp('wlevel', radix='hexadecimal'))
    block.add(Disp('wfull', radix='binary'))

    read_ptr_gray = block.add(Hierarchy('read_ptr_gray')).add(Group('read_ptr_gray'))
    read_ptr_gray.include('../../bin2gray/project/bin2gray_wave.py')

    write_ptr_gray = block.add(Hierarchy('write_ptr_gray')).add(Group('write_ptr_gray'))
    write_ptr_gray.include('../../bin2gray/project/bin2gray_wave.py')

    read_ptr_bin = block.add(Hierarchy('read_ptr_bin')).add(Group('read_ptr_bin'))
    read_ptr_bin.include('../../gray2bin/project/gray2bin_wave.py')

    write_ptr_bin = block.add(Hierarchy('write_ptr_bin')).add(Group('write_ptr_bin'))
    write_ptr_bin.include('../../gray2bin/project/gray2bin_wave.py')

    return block

And the wave file dclkfifolut_tb.wave.py for the dual clock FIFO test bench:


from wavedisp.ast import *

def generator():
    hier = Hierarchy('/dclkfifolut_tb', color='blue')
    inst = hier.add(Hierarchy('DUT'))
    inst.include('dclkfifolut_wave.py')

    return hier

We chose now to generate a wavefile for modelsim:


$ wavedisp -t modelsim -o wave.tcl

# Wavedisp generated modelsim file

onerror {resume}
add wave -radix binary -color #0000ff {/dclkfifolut_tb/DUT/rclk}
add wave -radix binary -color #0000ff {/dclkfifolut_tb/DUT/rsrst}
add wave -radix binary -color #0000ff {/dclkfifolut_tb/DUT/ren}
add wave -radix hex -color #0000ff {/dclkfifolut_tb/DUT/rdata}
add wave -radix hex -color #0000ff {/dclkfifolut_tb/DUT/rlevel}
add wave -radix binary -color #0000ff {/dclkfifolut_tb/DUT/rempty}
add wave -radix binary -color #0000ff {/dclkfifolut_tb/DUT/wclk}
add wave -radix binary -color #0000ff {/dclkfifolut_tb/DUT/wsrst}
add wave -radix binary -color #0000ff {/dclkfifolut_tb/DUT/wen}
add wave -radix hex -color #0000ff {/dclkfifolut_tb/DUT/wdata}
add wave -radix hex -color #0000ff {/dclkfifolut_tb/DUT/wlevel}
add wave -radix binary -color #0000ff {/dclkfifolut_tb/DUT/wfull}
add wave -radix hex -color #0000ff -group {read_ptr_gray} {/dclkfifolut_tb/DUT/read_ptr_gray/bin}
add wave -radix hex -color #0000ff -group {read_ptr_gray} {/dclkfifolut_tb/DUT/read_ptr_gray/gray}
add wave -radix hex -color #0000ff -group {write_ptr_gray} {/dclkfifolut_tb/DUT/write_ptr_gray/bin}
add wave -radix hex -color #0000ff -group {write_ptr_gray} {/dclkfifolut_tb/DUT/write_ptr_gray/gray}
add wave -radix hex -color #0000ff -group {read_ptr_bin} {/dclkfifolut_tb/DUT/read_ptr_bin/gray}
add wave -radix hex -color #0000ff -group {read_ptr_bin} {/dclkfifolut_tb/DUT/read_ptr_bin/bin}
add wave -radix hex -color #0000ff -group {write_ptr_bin} {/dclkfifolut_tb/DUT/write_ptr_bin/gray}
add wave -radix hex -color #0000ff -group {write_ptr_bin} {/dclkfifolut_tb/DUT/write_ptr_bin/bin}

update