Naja is an open source EDA framework for loading, elaborating, analyzing, optimizing, and transforming hardware designs from SystemVerilog and VHDL RTL through structural netlists. It is usable from Python or C++.
- SV/Verilog frontend — parse Verilog and elaborate SystemVerilog RTL into a browsable design model
- VHDL frontend (Beta) — parse and elaborate supported VHDL RTL into the same design model
- Netlist analysis — hierarchy, connectivity, equipotentials
- Logic optimization — dead logic elimination, constant propagation
- ECO transformations — direct netlist editing
- Serialization — SNL interchange format (Cap'n Proto) and Verilog output
The diagram below shows how formats, frontends, APIs, and companion tools integrate around Naja's C++ netlist engine:
- Design inputs — SystemVerilog is parsed and elaborated through
slang; VHDL is parsed and elaborated through the naja-vhdl frontend (Beta); gate-level Verilog can be loaded and emitted; and Liberty plus the Python primitive libraries provide cell and primitive models. - Core and interchange — Naja represents hierarchy, buses, bit-level nets
and terms, connectivity, and primitive functional models. The
naja-ifCap'n Proto format provides a logical-view interchange path. - APIs and tools —
najaedaexposes the engine through Python. Companion projects build on Naja directly or through that API:kepler-formal,naja-schematic, andnaja-scope.
---
config:
layout: dagre
theme: base
themeVariables:
fontFamily: ''
fontSize: 14px
primaryTextColor: '#172033'
lineColor: '#64748b'
clusterBkg: '#f8fafc'
clusterBorder: '#cbd5e1'
---
flowchart LR
sv["`**SystemVerilog**`"] ==> slang(["`**slang**<br>SystemVerilog Frontend`"])
vhdl["`**VHDL**`"] ==> naja-vhdl["`**naja-vhdl**<br> VHDL Frontend (Beta)`"]
verilog["`**gate-level verilog**`"] ==> naja-verilog["`**naja-verilog**<br>gate verilog Parser`"]
naja-verilog ==> naja["`**naja C++ · netlist engine**<br><br>hierarchy · buses<br>bit-level nets & terms · connectivity<br>Primitive Functional Models`"]
naja-vhdl =="`**Elaboration**`"==> naja
najaif@{ label: "**naja-if**<br>Logical View Interchange Format<br>Cap'n Proto" } <==> naja
slang =="`**Elaboration**`"==> naja
naja <==> najaeda["`**najaeda**<br>Python API`"]
naja ==> kf("`**kepler-formal**<br>Formal Comparison`") & ns("`**naja-schematic**<br>Schematic Viewer`")
najaeda ==> scope("`**naja-scope**<br>najaeda MCP server`")
kf ==> kfm("`**kepler-formal-mcp**<br>kepler-formal MCP server`")
lib["`**Liberty**`"] ==> naja
pythonlibs["`**Python libraries**<br>naja representation`"] ==> naja
sv@{ shape: disk}
vhdl@{ shape: disk}
verilog@{ shape: disk}
naja@{ shape: rounded}
najaif@{ shape: disk}
lib@{ shape: disk}
pythonlibs@{ shape: disk}
sv:::input
vhdl:::input
slang:::frontend
naja-verilog:::frontend
naja-vhdl:::frontend
verilog:::input
naja:::core
najaif:::input
najaeda:::api
kf:::tool
kfm:::tool
ns:::tool
scope:::tool
lib:::input
pythonlibs:::input
classDef input fill:#eef2ff,stroke:#6366f1,color:#1e1b4b,stroke-width:2px
classDef frontend fill:#fff7ed,stroke:#f97316,color:#431407,stroke-width:2px
classDef core fill:#fef2f2,stroke:#ef4444,color:#450a0a,stroke-width:3px
classDef api fill:#f0fdfa,stroke:#14b8a6,color:#042f2e,stroke-width:2px
classDef tool fill:#f5f3ff,stroke:#8b5cf6,color:#2e1065,stroke-width:2px
click slang "https://github.com/MikePopoloski/slang"
click naja-verilog "https://github.com/keplertech/naja-verilog"
click naja "https://github.com/najaeda/naja"
click najaif "https://github.com/keplertech/naja-if"
click najaeda "https://pypi.org/project/najaeda/"
click kf "https://github.com/keplertech/kepler-formal"
click kfm "https://github.com/keplertech/kepler-formal-mcp"
click ns "https://github.com/keplertech/naja-schematic"
click scope "https://github.com/keplertech/naja-scope"
The best entry point is the najaeda Python package:
pip install najaedaRequires Python 3.10 or later. Pre-built wheels are published for:
- Linux x86_64 and AArch64 (
manylinux_2_28; glibc 2.28 or later) - macOS Apple Silicon (arm64), macOS 11 or later
- Windows x86_64
Full documentation: najaeda.readthedocs.io
For AI-assisted design exploration, naja-scope
is a najaeda-based MCP server that gives MCP-compatible assistants a precise,
structured view of elaborated SystemVerilog or VHDL designs. Instead of pasting large
RTL files into chat, agents can ask targeted questions — what drives a signal,
what is inside a module, where a net comes from — and get small, exact answers
with file-and-line references.
Six hands-on notebooks — open any of them in Colab with no local install needed:
naja_edit is a command-line tool for optimizing and translating netlists.
📺 Presented at ORConf 2024.
# Translate Verilog → SNL
naja_edit -f verilog -t snl -i input.v -o output.snl
# Parse SystemVerilog with explicit top
naja_edit -f systemverilog -t verilog -i input.sv -o output.v --sv_top top
# Dead logic elimination
naja_edit -f snl -t snl -i input.snl -o output.snl -a dle
# Chain optimizations with Python scripts
naja_edit -f snl -t snl -i input.snl -o output.snl -a dle -e pre.py -z post.pyAvailable optimizations (-a): all (DLE + constant propagation + primitives), dle.
Python script examples: src/apps/naja_edit/examples
Regression suite: naja-regress
For the same Naja revision, platform and requested features, CMake and Bazel must deliver equivalent Naja and najaeda products: the same APIs, supported features, defaults, diagnostics, netlist behavior, serialization and package contents. Any difference caused by the build system is a bug. Matching dependency revisions alone does not establish this equivalence; common behavior and package checks must validate it. Independent BCR publication timing does not relax this rule for a published Naja release.
Naja has three delivery paths: CMake builds from sources, Bazel builds from sources, and Bazel Central Registry (BCR) distribution. Both source build systems serve users and package builds, including najaeda; shared source dependencies must use the same revisions. BCR publication follows its own schedule and may lag source builds without blocking source changes or package builds.
CMake currently provides the established install and packaging workflow.
Bazel provides build/test targets. Its default configuration uses the same
naja-if and naja-verilog checkouts as CMake; --config=registered selects the
published dependencies instead. Slang temporarily remains registry-backed with exact
source revision checks until its native upstream Bazel support permits direct
checkout selection. See the repository build policy.
Ubuntu:
sudo apt-get update
sudo apt-get install build-essential cmake git libboost-dev python3-dev \
capnproto libcapnp-dev libtbb-dev pkg-config bison flexmacOS (Homebrew):
brew install cmake capnp tbb bison flex boost
export PATH="/opt/homebrew/opt/flex/bin:/opt/homebrew/opt/bison/bin:$PATH"Nix:
nix-shell -p cmake gnumake boost python3 capnproto bison flex pkg-config tbb_2021_8git clone --recurse-submodules https://github.com/najaeda/naja.git
cd naja
export NAJA_INSTALL="$PWD/install"
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX="$NAJA_INSTALL"
cmake --build build --parallel
ctest --test-dir build --output-on-failure
cmake --install build
# Add the installed Python package to your environment.
export PYTHONPATH="${PYTHONPATH:+$PYTHONPATH:}$NAJA_INSTALL/lib/python"The Bazel build covers the repository's build and test targets on Ubuntu and
macOS. The version is pinned in .bazelversion; using
Bazelisk as the bazel command
automatically selects it.
Initialize naja-if and naja-verilog before a default Bazel build. Schema and parser sources use the same checkouts as CMake, including unpublished changes. Other dependencies currently resolve through the configured registries; the source dependency check verifies shared source revisions.
Ubuntu:
sudo apt-get update
sudo apt-get install build-essential cmake libboost-dev libfl-dev libtbb-dev \
bison flex m4 pkg-config python3-dev gitmacOS (Homebrew):
Install the Xcode Command Line Tools, then:
brew install cmake capnp tbb bison flex boost fmt tomlplusplus pkg-config
export PATH="$(brew --prefix flex)/bin:$(brew --prefix bison)/bin:$PATH"Build and test from the repository root:
git clone https://github.com/najaeda/naja.git
cd naja
git submodule update --init thirdparty/naja-if thirdparty/naja-verilog
bazel build //... --jobs=auto
bazel test //... --test_output=errors --jobs=autoThese are the same smoke commands used by
ubuntu-bazel.yml and
macos-bazel.yml. There is no Bazel
install target; use the CMake workflow above when you need an installed
library, Python package, or packaged artifact.
Check source selection and the remaining registry-backed source revisions:
python3 ci/check_submodule_bazel_sync.pyValidate the registry dependency set independently, without local dependency checkouts initialized:
bazel build --config=registered //...
bazel test --config=registered //... --test_output=errorsThis clears the local dependency overrides and uses the immutable versions in
MODULE.bazel. It does not switch Naja's own source revision.
Registered dependencies may lag source builds; an older schema can therefore
fail to compile newer Naja code. Update and validate registry versions when
preparing BCR distribution, independently of source/package changes. The manual
bazel-registered.yml workflow performs
these checks separately from source CI. BCR's consumer presubmits also validate
Naja as an external dependency, where this repository's .bazelrc is not inherited.
Naja exposes two complementary APIs:
- SNL (Structured Netlist) — full read/write netlist representation
- DNL (Dissolved Netlist) — fast, read-only flattened view for parallel analysis
Extended documentation: naja.readthedocs.io
C++ snippet: NLUniverseSnippet.cpp
App template (copy to start a new tool): src/app_snippet
- Chat: Matrix #naja:fossi-chat.org
- Bugs / features: GitHub Issues
- Contact: contact@keplertech.io
⭐ If you find Naja useful, starring the repo helps spread the word.
Supported by NLNet through the NGI0 Entrust Fund.

