Skip to main content
= vcdvcd
:idprefix:
:idseparator: -
:sectanchors:
:sectlinks:
:sectnumlevels: 6
:sectnums:
:toc: macro
:toclevels: 6
:toc-title:

Python Verilog value change dump (VCD) parser library + the nifty <<vcdcat>> VCD command line pretty printer.

toc::[]

== Installation

Since Ubuntu 23.04 you https://stackoverflow.com/questions/75608323/how-do-i-solve-error-externally-managed-environment-every-time-i-use-pip-3[need to use pipx] as:

....
pipx install vcdvcd
....

Previously it was instead:

....
python -m pip install --user 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 <<vcdcat>> directly from a clone with:

....
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 2 3 4 5
===========
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 1 2
=====
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:

* at time `0`
* the signal `counter_tb.top.out[1:0]`
* changed to value `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!

* https://github.com/cirosantilli/china-dictatorship
* https://cirosantilli.com/china-dictatorship/mirrors
* https://mastodon.social/@cirosantilli/111384334603801231
* https://x.com/cirosantilli/status/1722831661253988424

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 as also viewable at link:example_small.py[]:

....
from vcdvcd import VCDVCD

# Do the parsing.
vcd = VCDVCD('counter_tb.vcd')

# List all human readable signal names.
print(vcd.references_to_ids.keys())

# View all signal data.
print(vcd.data)

# Get a signal by human readable name.
signal = vcd['counter_tb.top.out[1:0]']

# tv is a list of Time/Value delta pairs for this signal.
tv = signal.tv
assert(tv[0] == (0, 'x'))
assert(tv[1] == (2, '0'))
assert(tv[2] == (6, '1'))
assert(tv[3] == (8, '10'))
assert(tv[4] == (10, '11'))
assert(tv[5] == (12, '0'))

# Random access value of the signal at a given time.
# Note how it works for times between deltas as well.
assert(signal[0] == 'x')
assert(signal[1] == 'x')
assert(signal[2] == '0')
assert(signal[3] == '0')
assert(signal[4] == '0')
assert(signal[5] == '0')
assert(signal[6] == '1')
assert(signal[7] == '1')
assert(signal[8] == '10')
assert(signal[9] == '10')
assert(signal[10] == '11')
assert(signal[11] == '11')
assert(signal[12] == '0')
assert(signal[13] == '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 <<vcdcat>>, but other features ended up being added (basically because by people are now able to conveniently communicate with the project on GitHub), e.g. convenient random access as mentioned at <<api-usage>> and basic tests at link:test.py[].

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
....

== Backlinks

* https://arxiv.org/html/2506.03590v1 VCDiag: Classifying Erroneous Waveforms for Failure Triage Acceleration

Metadata

Release files for vcdvcd 2.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vcdvcd 2.6.0
File Size Uploaded Provenance Actions
vcdvcd-2.6.0.tar.gz 14.0 kB Without provenance Details for vcdvcd-2.6.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for vcdvcd 2.6.0
File Interpreter ABI Platform Actions
vcdvcd-2.6.0-py3-none-any.whl Python 3 none any Details for vcdvcd-2.6.0-py3-none-any.whl

Total release size: 26.1 kB

Release files / vcdvcd-2.6.0.tar.gz

Download URL vcdvcd-2.6.0.tar.gz
Size 14.0 kB
Tags Source
SHA-256 checksum
How to use checksums
96d8ce491729e8c8ad7034a5093601409d8a3f4a34023d0be3db28650ecbb128
BLAKE2b-256 checksum
How to use checksums
58da1f33971ea8db20650bce491015d46df50668a3f2564818ddb04fd1cbaad0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Release files / vcdvcd-2.6.0-py3-none-any.whl

Download URL vcdvcd-2.6.0-py3-none-any.whl
Size 12.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d78a81bb7015f7c2564553624fd059c876fa4aca26ff1646e752a1fa06b18000
BLAKE2b-256 checksum
How to use checksums
9ac48deea995921806aab923d543342031d8704231347a83d31259b666bb8a73
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.3

Security for vcdvcd 2.6.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page