= vcdvcd :idprefix: :idseparator: - :sectanchors: :sectlinks: :sectnumlevels: 6 :sectnums: :toc: macro :toclevels: 6 :toc-title:
Python Verilog value change dump (VCD) parser library + the nifty <
toc::[]
== Installation
Install the latest release:
.... python -m pip install --user vcdvcd ....
On Ubuntu 23.04 you need instead https://stackoverflow.com/questions/75608323/how-do-i-solve-error-externally-managed-environment-every-time-i-use-pip-3[]:
.... pipx install vcdvcd ....
Install master directly from this repository for development with --editable
:
.... git clone https://github.com/cirosantilli/vcdvcd cd vcdvcd virtualenv -p python3 .venv . .venv/bin/activate python -m pip install --editable . ....
This allows you to direcly edit the source code here and see updates to importers from anywhere as shown at: https://stackoverflow.com/questions/35064426/when-would-the-e-editable-option-be-useful-with-pip-install/63353319#63353319[].
You can also use <
.... git clone https://github.com/cirosantilli/vcdvcd python -m pip install --user ./vcdvcd vcdvcd/vcdcat vcdvcd/counter_tb.vcd ....
== vcdcat
Nifty terminal CLI VCD pretty printer:
.... vcdcat -h ....
Dump all signal values:
.... vcdcat counter_tb.vcd ....
Output:
.... 0 time 1 counter_tb.clock 2 counter_tb.enable 3 counter_tb.out[1:0] 4 counter_tb.reset 5 counter_tb.top.out[1:0]
0 1 0 x 0 x 1 0 0 x 1 x 2 1 0 0 1 0 3 0 0 0 0 0 4 1 0 0 0 0 5 0 1 0 0 0 6 1 1 1 0 1 7 0 1 1 0 1 8 1 1 2 0 2 9 0 1 2 0 2 10 1 1 3 0 3 11 0 1 3 0 3 12 1 1 0 0 0 13 0 1 0 0 0 14 1 1 1 0 1 15 0 1 1 0 1 16 1 1 2 0 2 17 0 1 2 0 2 18 1 1 3 0 3 19 0 1 3 0 3 20 1 1 0 0 0 21 0 1 0 0 0 22 1 1 1 0 1 23 0 1 1 0 1 24 1 1 2 0 2 25 0 0 2 0 2 26 1 0 2 0 2 ....
Dump only selected signals:
.... vcdcat counter_tb.vcd top.enable top.reset ....
Output:
.... 0 time 1 counter_tb.top.enable 2 counter_tb.top.reset
0 0 0 1 0 1 3 0 0 5 1 0 25 0 0 ....
Note how only times for which at least one selected signal changed are shown.
=== vcdcat --deltas
Only print the signals that changed for each time.
If no signals changed at a given time, don't print anything for that time.
This will potentially make the output much much smaller for large VCD files.
Example:
.... vcdcat -d counter_tb.vcd ....
Output excerpt:
.... 0 x counter_tb.top.out[1:0] 0 0 counter_tb.reset 0 0 counter_tb.enable 0 1 counter_tb.clock 0 x counter_tb.out[1:0] 1 0 counter_tb.clock 1 1 counter_tb.reset 2 0 counter_tb.out[1:0] 2 0 counter_tb.top.out[1:0] 2 1 counter_tb.clock 3 0 counter_tb.clock 3 0 counter_tb.reset 4 1 counter_tb.clock ....
Where for example the line:
.... 0 x counter_tb.top.out[1:0] ....
means that:
0
counter_tb.top.out[1:0]
x
As without --deltas
, we can also view deltas only for selected signals, e.g.:
.... vcdcat -d counter_tb.vcd 'counter_tb.top.out[1:0]' ....
outputs:
.... 0 x counter_tb.top.out[1:0] 2 0 counter_tb.top.out[1:0] 6 1 counter_tb.top.out[1:0] 8 2 counter_tb.top.out[1:0] 10 3 counter_tb.top.out[1:0] 12 0 counter_tb.top.out[1:0] 14 1 counter_tb.top.out[1:0] 16 2 counter_tb.top.out[1:0] 18 3 counter_tb.top.out[1:0] 20 0 counter_tb.top.out[1:0] 22 1 counter_tb.top.out[1:0] 24 2 counter_tb.top.out[1:0] ....
=== vcdcat --china
vcdcat's most important option!
TODO: this option is now broken because Pypi deleted the package https://pypi.org/project/china-dictatorship/ without any notification. Cowards!
When it was working you could:
.... vcdcat --china > index.html firefox index.html ....
See also: https://cirosantilli.com/china-dictatorship/#mirrors
== API usage
Library usage examples can be seen at link:examples.py[] and run with:
.... ./examples.py ....
Other examples are also being added to link:test.py[] which can be run with:
.... ./test.py ....
or to run just one example do:
.... ./test.py Test.test_simple_timescale_values ....
By default, data is parsed at once into a per-signal format that allows for efficient random access, for example:
.... from vcdvcd import VCDVCD
vcd = VCDVCD('counter_tb.vcd')
print(vcd.references_to_ids.keys())
print(vcd.data)
signal = vcd['counter_tb.top.out[1:0]']
tv = signal.tv assert(tv[0] == (0, 'x')) assert(tv[1] == (2, '0')) assert(tv[2] == (6, '1'))
assert(signal[0] == 'x') assert(signal[1] == 'x') assert(signal[2] == '0') assert(signal[3] == '0') ....
But you can also use this library in a purely stream callback fashion as shown in the examples by doing something like:
.... class MyStreamParserCallbacks(vcdvcd.StreamParserCallbacks): def value( self, vcd, time, value, identifier_code, cur_sig_vals, ): print('{} {} {}'.format(time, value, identifier_code)) vcd = VCDVCD('counter_tb.vcd', callbacks=MyStreamParserCallbacks(), store_tvs=False) ....
store_tvs=False
instructs the library to not store all the signal value change data, which would likely just take up useless space in your streaming application. Only signal metadata is stored in that case.
== About this repository
The VCD format is defined by the Verilog standard, and can be generated with $dumpvars
.
This repo was originally forked from Sameer Gauria's version, which is currently only hosted on PyPI with email patches and no public bug tracking: https://pypi.python.org/pypi/Verilog_VCD[].
There is also a read-only mirror at: https://github.com/zylin/Verilog_VCD[].
The initial purpose of this fork was <
Another stream implementation can be found at: https://github.com/GordonMcGregor/vcd_parser[].
== Release procedure
Ensure that basic tests don't blow up:
.... ./examples.py ./test.py ./vcdcat counter_tb.vcd ./vcdcat -d counter_tb.vcd ....
Update the version
field in setup.py
:
.... vim setup.py ....
Create a tag and push it:
.... v=v2.3.4 git add setup.py git commit -m $v git tag -a $v -m $v git push --follow-tags ....
Push to PyPi:
.... pipx install twine python3 setup.py sdist bdist_wheel twine upload dist/ rm -rf build dist .egg-info ....