Netlist API (and more) for EDA flow development
See the code
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++.
In the APIs and CLI, load_gate_level_verilog, NLDB.loadGateLevelVerilog, and -f gate-level-verilog mean
gate-level (structural) Verilog, not general behavioral RTL. For Verilog or
SystemVerilog RTL, including .v sources, use load_system_verilog,
NLDB.loadSystemVerilog, or -f systemverilog within the slang frontend's
supported RTL subset. Verilog export writes structural netlists. The former Python names
(load_verilog, VerilogConfig, dump_verilog, VerilogDumpConfig, and raw
loadVerilog/dumpVerilog) remain compatibility aliases and warn that they
will be deprecated soon. The CLI also keeps -f verilog and -t verilog as
compatibility aliases with the same migration warning; prefer gate-level-verilog.
The diagram below shows how formats, frontends, APIs, and companion tools integrate around Naja's C++ netlist engine:
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.naja-if Cap'n Proto format provides a
logical-view interchange path.najaeda exposes
the engine through Python. Companion projects build on Naja directly or
through that API: kepler-formal,
naja-schematic, and
naja-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 najaeda
Requires Python 3.10 or later. Pre-built wheels are published for:
manylinux_2_28; glibc 2.28 or later)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 — Netlist CLInaja_edit is a command-line tool for optimizing and translating netlists.
📺 Presented at ORConf 2024.
# Translate gate-level Verilog → SNL
naja_edit -f gate-level-verilog -t snl -i input.v -o output.snl
# Elaborate Verilog/SystemVerilog RTL with explicit top; export a gate-level netlist
naja_edit -f systemverilog -t gate-level-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.py
Available 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 flex
macOS (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_8
git 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 git
macOS (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=auto
These 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.py
Validate the registry dependency set independently, without local dependency checkouts initialized:
bazel build --config=registered //...
bazel test --config=registered //... --test_output=errors
This 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:
Extended documentation: naja.readthedocs.io
C++ snippet: NLUniverseSnippet.cpp
App template (copy to start a new tool): src/app_snippet
⭐ If you find Naja useful, starring the repo helps spread the word.
Supported by NLNet through the NGI0 Entrust Fund.
1,465 followers · starred Feb 2025
255 followers · starred Sep 2024
112 followers · starred Jun 2025
121 followers · starred May 2025
Netlist API (and more) for EDA flow development
See the code
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++.
In the APIs and CLI, load_gate_level_verilog, NLDB.loadGateLevelVerilog, and -f gate-level-verilog mean
gate-level (structural) Verilog, not general behavioral RTL. For Verilog or
SystemVerilog RTL, including .v sources, use load_system_verilog,
NLDB.loadSystemVerilog, or -f systemverilog within the slang frontend's
supported RTL subset. Verilog export writes structural netlists. The former Python names
(load_verilog, VerilogConfig, dump_verilog, VerilogDumpConfig, and raw
loadVerilog/dumpVerilog) remain compatibility aliases and warn that they
will be deprecated soon. The CLI also keeps -f verilog and -t verilog as
compatibility aliases with the same migration warning; prefer gate-level-verilog.
The diagram below shows how formats, frontends, APIs, and companion tools integrate around Naja's C++ netlist engine:
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.naja-if Cap'n Proto format provides a
logical-view interchange path.najaeda exposes
the engine through Python. Companion projects build on Naja directly or
through that API: kepler-formal,
naja-schematic, and
naja-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 najaeda
Requires Python 3.10 or later. Pre-built wheels are published for:
manylinux_2_28; glibc 2.28 or later)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 — Netlist CLInaja_edit is a command-line tool for optimizing and translating netlists.
📺 Presented at ORConf 2024.
# Translate gate-level Verilog → SNL
naja_edit -f gate-level-verilog -t snl -i input.v -o output.snl
# Elaborate Verilog/SystemVerilog RTL with explicit top; export a gate-level netlist
naja_edit -f systemverilog -t gate-level-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.py
Available 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 flex
macOS (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_8
git 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 git
macOS (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=auto
These 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.py
Validate the registry dependency set independently, without local dependency checkouts initialized:
bazel build --config=registered //...
bazel test --config=registered //... --test_output=errors
This 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:
Extended documentation: naja.readthedocs.io
C++ snippet: NLUniverseSnippet.cpp
App template (copy to start a new tool): src/app_snippet
⭐ If you find Naja useful, starring the repo helps spread the word.
Supported by NLNet through the NGI0 Entrust Fund.
1,465 followers · starred Feb 2025
255 followers · starred Sep 2024
112 followers · starred Jun 2025
121 followers · starred May 2025