Open-source project
emsec/hal avatar
emsec/hal

HAL: a netlist reverse engineering framework for FPGA and ASIC research

HAL – The Hardware Analyzer

838 stars102 forksC++MIT

At a glance

What is it?
HAL parses netlists into a graph representation and gives analysts traversal and analysis tools over the gates and nets, with a C++ core, Python bindings and a plugin system. It targets hardware security researchers who need reproducible analysis of gate-level designs, and it earns that partly by leaving netlist parsing to plugins and the research setup to the analyst.
Who is it for?
HAL is worth adopting for hardware security teams that repeat netlist analysis across many gate-level designs, and it is a poor fit for a single netlist inspection or for teams without a C++ and Python toolchain.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly C++, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

HAL turns a gate-level netlist into a graph you can traverse

The premise of HAL is that research on netlist analysis almost always works from a graph representation of the design, and that a lot of effort goes into producing that representation before any interesting analysis starts. HAL takes on that parsing step. The README describes it as a framework to parse netlists of arbitrary sources, for example FPGAs or ASICs, into a graph-based netlist representation, and to provide the built-in tools for traversal and analysis of the included gates and nets.

The stated goal is to become, for hardware reverse engineering, the equivalent of tools like IDA or Ghidra. The comparison is about the position in the workflow: such tools establish a common baseline, abstract away recurring basic tasks such as netlist parsing, and let researchers improve the reproducibility of results instead of rewriting the loader for every new design format. That framing matters if you are writing papers on hardware attacks, because two labs running the same analysis should be looking at the same object model.

HAL is developed by the Embedded Security group of the Max Planck Institute for Security and Privacy, and it is used in the university lecture Einführung ins Hardware Reverse Engineering at Ruhr University Bochum. A separate repository holds benchmark circuits for evaluating netlist reverse engineering techniques. The project is under active development, and the last push to the repository was on 2026-10-20.

A C++ core with Python bindings and a plugin system

The architecture is split along three lines. Performance comes from an optimized C++ core, flexibility from built-in Python bindings, and modularity from a C++ plugin system. Stability is handled by a test suite that runs through CI on Ubuntu 22.04, Ubuntu 24.04 and macOS, with a separate workflow for deploying the documentation.

The top-level layout explains the plugin model in practical terms. There are top-level directories for app, src, include, plugins, tests, cmake, deps, tools, packaging, documentation and examples, plus CMakeLists.txt, a Dockerfile, a docker-compose.yml, install_dependencies.sh, requirements.txt and FindHal.cmake for consumers building against an installed HAL. The plugin directory is where format support lives, which is why a new netlist format or a new gate library can be added without touching the core.

The Python side has its own packaging requirements in requirements.txt, which lists jedi, sphinx, sphinx-rtd-theme and python-dateutil. jedi is what makes the limited autocomplete in the integrated Python shell and the Python script window work, and sphinx builds the API documentation. Both the C++ API and the Python API have generated reference documentation hosted under the project pages.

The plugin set covers parsing, analysis, simulation and writing

The shipped plugins show what the graph model is meant to support. A GUI plugin offers visual netlist inspection, native integration of a Python shell with access to the HAL Python bindings, isolation of specific gates or modules for clutter-free inspection, interactive traversal of netlists and detail widgets for the inspected netlist. A netlist simulator plugin simulates arbitrary parts of a loaded netlist. A clock tree extractor recovers clock trees from an unstructured gate-level netlist, and a dataflow analysis plugin named DANA recovers high-level registers in an unstructured netlist. A graph algorithms plugin integrates igraph for direct access to common graph-theory algorithms.

Input and output formats are plugins too. VHDL and Verilog parsers add those files as netlist input formats, a Liberty parser adds arbitrary gate libraries in the standard liberty format, and VHDL and Verilog writers serialize a modified netlist back to synthesizable files. A Python shell plugin spawns a command line shell preloaded with the Python bindings, which is handy for scripting batch analysis outside the GUI. Gate library plugins add support for the XILINX Unisim and Simprim libraries.

The practical consequence is that the input and output surface is wide but the list is not unbounded. There is a plugin for VHDL and Verilog and Liberty, and nothing in the README promises support for other vendor formats. Check the plugin list before planning a pipeline around a format you happen to own.

Building HAL through the container image

The README does not give build steps inline. It points to a dedicated Building-HAL page in the project wiki, so a first build means following that page rather than guessing at commands. The repository does contain the pieces a containerised build uses, and the Dockerfile shows the shape of the build.

dockerfile
FROM ubuntu:22.04

ARG CMAKE_OPTIONS
ARG MAKE_OPTIONS

ENV hal_path=/hal
RUN mkdir -p $hal_path
WORKDIR $hal_path

RUN apt-get update -y && \
    apt-get install -y lsb-release

COPY . .
RUN HAL_DOCKER=1 ./install_dependencies.sh

RUN mkdir build
WORKDIR ${hal_path}/build/
RUN cmake .. ${CMAKE_OPTIONS}
RUN make ${MAKE_OPTIONS}

VOLUME [ "/projects" ]

CMD ["./bin/hal", "-g"]

The image is Ubuntu 22.04, installs dependencies through install_dependencies.sh with the HAL_DOCKER environment variable set, configures with CMake and builds with make. CMake and make options can be passed through as arguments. The declared volume /projects is where a mounted netlist or project would live, and the default command starts the GUI. A compose file is provided as well:

yaml
---
version: '3'
services:
  hal-build:
    build: .
    volumes:
      - .:/home/src/:rw
      - ./deployment/build-output/:/home/build-output/:rw
      - ./deployment/build-output/.ccache/:/root/.ccache/:rw
...

The compose file mounts the source tree, a build output directory and a ccache directory, which is how repeated builds avoid recompiling everything.

Starting the GUI and opening a bundled example

Once HAL is installed or built, the README's quickstart is short. Start the GUI with the hal command and the -g option, and list all available options with the help flag.

bash
hal -g
bash
hal [--help|-h]

The examples directory ships several ready-made projects: crypto_trojan.zip, fsm.zip, simple_alu.zip, toy_cipher.zip and uart.zip. A project is imported through Import Project from the main menu, or by dropping the zipped file into the OPEN PROJECT area of the Welcome Screen. HAL then asks for a directory it can write to, creates the project directory there and uncompresses the files. The documentation is emphatic that you should not uncompress the archive yourself with an external tool, because adjustments are made during import so that the netlist and gate library are found the next time the project is opened. Breaking that step produces a project that opens with missing libraries.

For a netlist of your own, the entry point is Import Netlist instead. That path only works if a matching gate library sits in plugins/gate_libraries/definitions, or if you provide the gate library manually. The wiki covers creating your own gate library.

Inspecting gates from the Python shell

Both the integrated Python shell and the Python script window expose the bindings, and both offer limited autocomplete. The README's worked example refers to the fsm example and walks the netlist gates, printing the name, id and type of every gate whose type name contains LUT, then printing the Boolean function of each of its inputs.

python
for gate in netlist.get_gates():
    if "LUT" in gate.type.name:
        print("{} (id {}, type {})".format(gate.name, gate.id, gate.type.name))
        print("  {}-to-{} LUT".format(len(gate.type.input_pins), len(gate.type.output_pins)))
        boolean_functions = gate.boolean_functions
        for name in boolean_functions:
            print("  {}: {}".format(name, boolean_functions[name]))
        print("")

The example output for the netlist fsm.vhd lists state register instances of type LUT6 as 6-to-1 LUTs, followed by the Boolean expression for their O output in a minterm notation such as (!I1 & !I2 & I3 & !I4 & I5) | (I0 & !I2). That output is the point of the whole pipeline: a machine-generated description of what a chunk of logic computes, derived from the netlist rather than from source code.

One caveat is worth stating plainly. The example is a single script over a single netlist. Nothing in the README documents a stable scripting API for batch analysis, a plugin SDK guide, or a rollback path, so scripted pipelines will need to track the C++ and Python API documentation and the CHANGELOG.md for breaking changes.

Where HAL stops being the right tool

HAL is a research framework for gate-level netlists, and several boundaries follow from that. It does not reverse engineer source code from a bitstream, and it does not operate on RTL without a synthesis step, since the object it models is a gate-level netlist. For a quick look at a small Verilog file, the parser plugins plus a text editor are quicker than a CMake build.

The build cost is real. A C++ core, a plugin tree, CMake configuration, Python dependencies and a documentation toolchain are more moving parts than a script. The README routes every build question to a wiki page rather than describing the steps, so a new user inherits that dependency on external documentation.

The licence is MIT, which is permissive and lets you embed the framework in commercial tooling without copyleft obligations, though you must keep the licence text and copyright notice. The maintenance picture is healthy on the source side, with the last push on 2026-10-20, but the latest tagged release is v4.5.0 from 2025-09-23, with v4.4.1 from 2024-07-29 and v4.4.0 from 2024-07-19 before it. Anyone tracking master is ahead of the last tag.

Editorial conclusion

HAL is worth adopting for hardware security teams that repeat netlist analysis across many gate-level designs, and it is a poor fit for a single netlist inspection or for teams without a C++ and Python toolchain. Before adopting, check that your gate libraries exist as plugins in the gate_libraries definitions directory or that you can supply your own, confirm the build steps in the Building-HAL wiki page match your platform, and read the CHANGELOG.md entries between the tagged v4.4.1 and the current source to see what an upgrade changes.

Frequently asked questions

How do I build HAL from source?

The README does not list build commands inline and instead points to the Building-HAL page in the project wiki. The repository ships a Dockerfile and a docker-compose.yml that show the same flow: run install_dependencies.sh, configure with cmake and build with make.

How do I start the HAL GUI and load an example netlist?

Run hal -g to start the GUI, then import a bundled project from the examples directory through Import Project, or by dropping the zipped file into the OPEN PROJECT area of the Welcome Screen. Do not uncompress the archive with an external tool, because HAL adjusts the files during import.

What netlist formats and gate libraries does HAL support?

Shipped plugins add VHDL and Verilog parsing, Liberty gate library parsing, and support for the XILINX Unisim and Simprim libraries. Importing your own Verilog or VHDL requires a matching gate library in plugins/gate_libraries/definitions or one you supply manually.

Can I script HAL instead of using the GUI?

Yes. There is a Python shell plugin that spawns a command line shell preloaded with the Python bindings, and the GUI has an integrated Python shell and a script window, both with limited autocomplete. Example scripts using the bindings are shown in the README.

What licence is HAL released under?

HAL is released under the MIT licence. The repository contains a LICENSE file along with a LICENSE.header, and the licence permits reuse and modification with the notice retained.

Official sources

  1. emsec/hal on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/emsec-hal.svg)](https://hysenlabs.com/projects/emsec-hal)

Was this useful?