Skip to content

Carlos-Jr/thermalbits

Repository files navigation

ThermalBits

ThermalBits logo

ThermalBits is a Python library for inspecting combinational digital circuits from Verilog netlists, transforming them as editable DAGs, and estimating their information loss through Shannon entropy.

In practice, it lets you:

  • Parse a Verilog netlist into a simple internal representation (pi, po, node) that you can inspect and edit directly.
  • Measure size, depth and Landauer-related entropy, using a bundled Rust simulator for the entropy runs.
  • Transform circuits with energy-oriented (EO) and depth-oriented (DO) passes, external ABC scripts, or your own passes chained in a pipeline.
  • Compare the original and optimized versions of a circuit, side by side or in batch over a directory of netlists (CSV report).
  • Export results as versioned JSON, reconstructed Verilog, or DAG images.

Everything is available both as a Python API and as an installed thermalbits command-line tool.

Start guide

You need python3 (3.10+) and cargo (Rust) installed.

1. Install. From the repository root, run the setup script — it installs the Python package with its dependencies and builds the two bundled Rust binaries:

./fast_start.sh

2. Check the environment.

thermalbits doctor

3. Analyze your first circuit.

thermalbits analyze tests/fixtures/half_adder.v

Or from Python:

from thermalbits import ENERGY_ORIENTED, ThermalBits

tb = ThermalBits("tests/fixtures/half_adder.v")  # parse the netlist
tb.update_entropy()                              # run the entropy simulation
optimized = tb.copy().apply(ENERGY_ORIENTED)     # apply an EO pass on a copy
tb.to_json("half_adder.json")                    # export as versioned JSON

Other useful CLI commands:

thermalbits compare original.v optimized.v            # side-by-side metrics
thermalbits optimize circuit.v --method eo -o out.json
thermalbits optimize circuit.aig --backend abc --script "balance; rewrite"
thermalbits batch benchmarks/ -o results.csv          # CSV report for a directory
thermalbits visualize circuit.v --metric energy       # render the DAG

See the CLI documentation for all options.

The repository only ships the minimal fixtures used by the tests; the full benchmark collections (EDGE, EPFL, BCGEN adders) are kept in a dedicated repository, verilog-benchmarks:

git clone https://github.com/Carlos-Jr/verilog-benchmarks.git
thermalbits batch verilog-benchmarks/EDGE -o results.csv

Manual installation

If you prefer not to use fast_start.sh, install the package with pip. Dependencies are declared only in pyproject.toml, as extras:

python -m pip install -e ".[viz]"     # runtime + DAG rendering
python -m pip install -e ".[dev]"     # development (viz + test + docs + tooling)
Extra Contents
viz matplotlib, networkx
test pytest, pytest-cov, hypothesis
docs mkdocs-material
dev viz + test + docs + ruff, mypy, build, twine

Then build the two Rust binaries once:

# Entropy simulator, used by update_entropy()
cd thermalbits/iron_circuit_sim && RUSTFLAGS="-C target-cpu=native" cargo build --release && cd ../..

# EO/DO transformer, used by apply()
cd thermalbits/eo_do_rs && RUSTFLAGS="-C target-cpu=native" cargo build --release && cd ../..

RUSTFLAGS="-C target-cpu=native" enables CPU-specific optimizations and produces a noticeably faster binary on the machine that compiled it; omit it if you need a binary portable across different CPUs. fast_start.sh accepts the same trade-off via flags: --dev, --docs, --no-native, --help.

If the EO/DO binary is missing, apply() falls back to the Python reference implementation and emits a RuntimeWarning. Environment variables:

Variable Effect
THERMALBITS_EODO_BACKEND=rust Turn a missing binary into an error.
THERMALBITS_EODO_BACKEND=python Force the Python implementation.
THERMALBITS_EODO_BIN=/path/to/eo_do_rs Override the binary location.

Inspecting entropy per gate

To inspect the local entropic contribution of a gate, keep chunk partials during the entropy run and query them afterward:

tb.update_entropy(chunks=8, save_entropy=True)
gate_energy = tb.energy_in(42)

Here "energy" means the local entropy difference H(input_joint) - H(output_joint) in bits. energy_in() requires saved partials from update_entropy(..., save_entropy=True) and does not run a new simulation.

Full documentation

The complete documentation is in documentation/docs. Start with:

To serve the documentation locally:

python -m pip install -e ".[docs]"
mkdocs serve -f documentation/mkdocs.yml

Contributing, citing and security

  • CONTRIBUTING.md — development setup, quality checks and the release process.
  • CHANGELOG.md — notable changes per release.
  • CITATION.cff — citation metadata (GitHub renders a "Cite this repository" box from it).
  • SECURITY.md — how to report vulnerabilities.

About

A library for inspecting combinational digital circuits from Verilog netlists, focusing on exploring energy limits based on Landauer's principle.

Topics

Resources

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages