Skip to content

Latest commit

 

History

History
239 lines (173 loc) · 9.37 KB

README_PyPI.md

File metadata and controls

239 lines (173 loc) · 9.37 KB

naja-scope

PyPI version Python versions License: Apache 2.0

Let your AI assistant explore SystemVerilog designs — without pasting source code into the chat.

naja-scope is an MCP server that gives AI agents (Claude, and any MCP-compatible assistant) a precise, structured view of your elaborated SystemVerilog design. Instead of dumping thousands of lines of RTL into the model's context, the agent asks targeted questions — what drives this signal? what's inside this module? where does this net come from? — and gets back small, exact answers with file-and-line references.

Built on the najaeda netlist engine.

On a 17-question CVA6 benchmark, the same Claude Code agent scored 17/17 with naja-scope versus 10/17 with grep/read source tools — in 77 turns instead of 123, processing about 5× less input. How it was measured

pip install naja-scope
claude mcp add naja-scope -- naja-scope-mcp

See it in action: demo recording.


Why

Large designs don't fit in a chat window. Pasting RTL is slow, expensive, and the model still can't reliably trace connectivity across hierarchy. naja-scope turns your design into something an agent can navigate:

  • 🔎 Trace connectivity — find what drives or loads any signal, across module boundaries.
  • 🌲 Walk the hierarchy — explore modules, instances, and ports on demand.
  • 🎯 Jump to source — every answer comes with file:line ranges, so the agent can quote the exact RTL that matters.
  • 🧩 Logic cones — trace fan-in / fan-out combinational cones up to the register boundary.
  • 💡 Recover design intent — enum state names, struct/union fields, and parameter formulas that normally vanish when a design is elaborated.

Works on RTL and gate-level netlists alike — load elaborated SystemVerilog, or a post-synthesis structural Verilog netlist plus its Liberty standard-cell library (see Gate-level designs). VHDL loading is in beta.

All responses are token-bounded: lists paginate, large results truncate with clear markers. Your context stays small; your answers stay accurate.


Does it actually help?

naja-scope helps most when the answer exists in the elaborated design rather than in any single source file. In an initial 17-question run on the cv32a6_imac_sv32 configuration of CVA6, the same Claude Code agent was tested with naja-scope and with source-search tools alone.

Agent setup Provider and models Initial automated score Turns Input processed Output tokens
Agent + naja-scope Anthropic Claude Code; claude-sonnet-4-6 with claude-haiku-4-5-20251001 helper 17 / 17 77 1,058,556 19,520
Agent + grep/read source Anthropic Claude Code; claude-sonnet-4-6 with claude-haiku-4-5-20251001 helper 10 / 17 123 5,461,719 55,962

The difference is clearest on structural questions that source search cannot answer directly:

CVA6 question Agent + naja-scope Agent + grep/read source
Flattened register groups under ex_stage_i 92, in 4 turns No answer at the turn limit
Flattened register groups under commit_stage_i 0, in 3 turns No answer at the turn limit
Elaborated hpdcache_mux variants 20, in 3 turns No answer at the turn limit

Source search remains the right tool for local textual questions. naja-scope adds the elaborated hierarchy, connectivity, lowered primitives, and generated or uniquified structures that are otherwise difficult to reconstruct.

See the benchmark methodology and multi-model runner and historical result record for configuration, scoring, token accounting, and reproducibility details.


Install

pip install naja-scope

That's it — najaeda and the MCP runtime come along automatically.


Connect it to Claude Code

claude mcp add naja-scope -- naja-scope-mcp

Or add it to any MCP client's config:

{
  "mcpServers": {
    "naja-scope": {
      "command": "naja-scope-mcp"
    }
  }
}

Then just ask your assistant to load a design and start exploring:

"Load my UART design from rtl/uart.sv with top uart_top, then show me everything that drives tx_o."

The agent loads the design once and answers follow-up questions instantly — no re-reading source, no giant pastes.


Connect it to ChatGPT

ChatGPT connects to MCP servers over an HTTP endpoint (custom connectors / Developer mode), so run naja-scope as an HTTP server instead of stdio:

naja-scope-mcp --transport streamable-http --host 127.0.0.1 --port 8000

This serves MCP at http://<host>:8000/mcp. Expose that URL where ChatGPT can reach it (e.g. an ngrok/cloudflared tunnel for a local run), then in ChatGPT open Settings → Connectors, add a custom connector, and paste the URL (https://<your-host>/mcp). The HTTP server has no built-in auth — only expose it over a trusted tunnel.


Gate-level designs

Already synthesized? Load the structural Verilog netlist together with the Liberty library that defines its standard cells, and navigate the gates the same way as RTL:

"Load the Liberty library pdk/stdcells.lib, then the gate netlist build/top.v, and tell me what cells top is built from and what drives data_out."

Hierarchy, per-cell counts, drivers/loads, and logic cones all work on the netlist; cones stop at the sequential cells. get_source shows an object's line in the netlist, and for Yosys output yosys_source_attributes=True adds origins that get_source(path, origin=0) reads back in the RTL.


VHDL (beta)

VHDL loading is available in beta. Call load_vhdl(file=["pkg.vhd", "child.vhd", "top.vhd"], top="my_entity") to explore its elaborated hierarchy and connectivity; the files may be listed in any order. A single path per call also works (load packages first); package-only files may return top: null until the top file is loaded. The frontend supports a restricted two-state RTL subset, and supported constructs may change. get_intent/load_intent remain SystemVerilog-only; VHDL source ranges are not guaranteed.


What you can ask

Once a design is loaded, your assistant can:

  • Resolve any signal or instance by hierarchical path (with glob and did-you-mean suggestions).
  • Find objects design-wide by pattern.
  • Show the hierarchy of any module.
  • Get drivers / loads of a net — the real endpoints, across hierarchy; literal drivers preserve four-state 0 / 1 / X / Z values.
  • Trace logic cones (fan-in / fan-out) and see the register frontier.
  • Get source — the exact SystemVerilog lines behind any object.
  • Get a module card — ports, counts, clock/reset at a glance.
  • Recover design intent — state-machine names, struct fields, parameter expressions lost during elaboration.

Requirements

  • Python 3.10+
  • Works anywhere najaeda runs (Linux, macOS, Windows)

Support & contact


License

Apache-2.0. See LICENSE.

Optional browser schematic

Requires naja-schematic 0.2.0 or later (the release containing the embeddable viewer API):

pip install "naja-scope[schematic]"

Restart the MCP server after installation. Load a design as usual, then use:

  • open_schematic(path="top.u_cpu"): returns a local browser URL and focuses the instance. Omit path for the top. Anonymous #id instances are supported.
  • annotate_schematic(items=[{"path": "top.u_cpu", "message": "Check reset", "severity": "warning"}]): replaces the overlay. Use kind="term" with a pin/port path to annotate that terminal; annotations apply to the whole port, not individual bus bits. Pass items=[] to clear. At most 200 annotations, each with at most 2000 message characters.
  • get_schematic_selection(): returns the last clicked instance as a regular naja-scope path, usable with source, hierarchy and module-card queries.

The viewer shares the existing raw naja universe; it does not elaborate again. The server binds to loopback and returns a token-bearing URL. Open that URL on the machine running the MCP server; it is not a remote or embedded MCP UI. Treat the URL as access to the loaded design. Design loads/resets refresh open viewers and clear selection, focus and annotations. The browser server stops with naja-scope. Existing tools remain usable without the schematic extra.