Skip to main content
Silica

AI-native EDA environment · MCP server for hardware design and verification

PyPI Python License


What it does

Silica is an MCP server that gives coding agents structured access to an EDA toolchain. The agent lints, simulates, proves, synthesizes, places and routes, programs a board and reads its UART through MCP tools, and gets parsed results back (errors with file and line, timing per clock, utilization, inferred memories, counterexample traces) instead of raw logs.

That closes the loop without copy-paste: run the simulation, read the failure, fix the RTL, re-run. The server also tells the agent the order to work in and the pitfalls to avoid, and a doctor tool reports which EDA tools are installed and how to install the rest.

Silica drives tools you install yourself: open-source tools (mostly from OSS CAD Suite), and commercial ones (VCS, Questa, Xcelium, Vivado, …) when they're on PATH. How well each is tested is listed under Supported tools.

What works today

The full flow has been run end to end on a Digilent Arty A7-100T (Xilinx Artix-7) with a PicoRV32 RISC-V SoC whose firmware prints a banner, echoes UART input and drives LEDs from a timer:

  1. RTL and lint: Verilator, Verible and svlint, with Verilator elaborating the whole multi-file design.
  2. Simulation: Icarus and Verilator running the real firmware from $readmemh, with waveform (read_waveform) and line coverage (read_coverage).
  3. Formal: SymbiYosys prove, cover and bounded checks on the UART and FIFO, a deliberately false assertion reported as FAIL with its counterexample, and eqy equivalence.
  4. Synthesis: Yosys synth_xilinx, with utilization and the firmware ROM reported as block RAM with init data.
  5. Place and route: openXC7's nextpnr-xilinx (100 MHz target, routed at 153 MHz), and the .bit assembled with fpga-as.
  6. Programming: program_device (openFPGALoader) into SRAM, with the FPGA's DONE status checked.
  7. Serial check: capture_serial confirming the banner and the echo over the board's UART.

These runs were manual, on one machine (OSS CAD Suite 2026-10-14, openXC7 toolchain-nix 1.0.0, Verible v0.0-4296, svlint 0.9.5). CI covers the open-source tools in a weekly integration job; see Supported tools.

Known limitations

  • Vivado is synthesis only: there's no implementation or bitstream step.
  • VCS, Questa and Xcelium adapters are tested only with mocked tool calls, never against a real install; the same goes for Quartus, DC Shell, JasperGold, VC Formal, SpyGlass and Verdi. If one misbehaves, please open an issue with the tool version and output.
  • iCE40 and ECP5 bitstreams are packed with icepack/ecppack and checked against the real tools, but program_device has only been tested on these boards with mocked openFPGALoader calls: no iCE40 or ECP5 board has been available. get_project_structure doesn't list iCE40 .pcf files.
  • cocotb needs a Python whose glibc is compatible with the simulator it loads into. With OSS CAD Suite's simulators and a newer system Python (glibc newer than the suite's), run_cocotb fails at import.
  • Formal: an UNKNOWN prove with induction_failures is inconclusive (k-induction didn't close), not a bug. Deep bounded checks can be slow; 120 steps on the example UART took 16 minutes.
  • Offline: clients configured with uvx silica-eda@latest (including the Claude Code plugin) can't start the server without network; see Offline under the install instructions for the --offline workaround.
  • Serial: capture_serial needs the port named explicitly and read/write access to it. A boot banner is usually missed by a capture started after programming.
  • Windows: the serial existence and permission pre-checks are POSIX-only, and the pty-based serial tests skip there.

Quick start

  1. Add silica to your agent. Follow Install in your agent: each client launches uvx silica-eda@latest. Or run the setup wizard, uvx silica-eda@latest setup, which writes that config for you; see Setup wizard.

  2. Install the EDA tools you need: OSS CAD Suite for most open-source tools, Verible and svlint for linting, openXC7 for Xilinx place and route. Then ask the agent to run doctor.

  3. Try the UART example in examples/uart/:

    Run the UART TX simulation in examples/uart/ and tell me if it passes.

    Then break it and let the agent find the bug:

    In examples/uart/uart_tx.sv, change the DATA state's shift to shift_reg <= {shift_reg[6:0], 1'b0};. Run the simulation, find the bug and fix it.

    The testbench then prints [FAIL] lines such as bit[2] is 0, expected 1, and the agent should trace them to the shift direction.

Install in your agent

Every client below starts the server with uvx silica-eda@latest: uv downloads silica into a cached environment on first use and picks up new releases when the client next starts the server. Install uv first. uvx silica-eda needs a silica-eda release newer than 0.3.1; on 0.3.1 use uvx --from silica-eda@latest silica instead.

silica drives EDA tools you install separately (Verilator, Yosys, SymbiYosys, nextpnr, …); see Installing the EDA tools. Once connected, ask the agent to run the doctor tool: it lists what's installed and how to install what's missing.

Claude Code (plugin, with a workflow skill)

In Claude Code:

/plugin marketplace add simaanc/silica-eda
/plugin install silica-eda@silica-eda

On Claude Code 2.1.275 or later this also works in one step: /plugin install silica-eda --marketplace simaanc/silica-eda.

Updates: the plugin's server always runs uvx silica-eda@latest. To also receive plugin updates (new skills, config changes) automatically, turn on auto-update for the marketplace, which is off by default: /plugin → Marketplaces → silica-eda → Enable auto-update. Admins can set "autoUpdate": true on the marketplace's extraKnownMarketplaces entry in managed settings. Without auto-update, run /plugin marketplace update silica-eda.

Without the plugin, add just the server:

claude mcp add --transport stdio --scope user silica -- uvx silica-eda@latest
Claude Desktop

Open Settings → Developer → Edit Config and add the server to claude_desktop_config.json, then quit and restart Claude Desktop:

{
  "mcpServers": {
    "silica": {
      "command": "uvx",
      "args": ["silica-eda@latest"]
    }
  }
}

If the server doesn't start, Claude Desktop may not see your shell's PATH: put the full path from which uvx in command.

Codex CLI
codex mcp add silica -- uvx silica-eda@latest

or in ~/.codex/config.toml:

[mcp_servers.silica]
command = "uvx"
args = ["silica-eda@latest"]
# The first launch downloads silica; Codex's default start timeout is 10 s.
startup_timeout_sec = 60
Cursor

Add to ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project):

{
  "mcpServers": {
    "silica": {
      "type": "stdio",
      "command": "uvx",
      "args": ["silica-eda@latest"]
    }
  }
}

One-click install: open this link in your browser (GitHub doesn't make cursor:// links clickable):

cursor://anysphere.cursor-deeplink/mcp/install?name=silica&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyJzaWxpY2EtZWRhQGxhdGVzdCJdfQ==
VS Code (GitHub Copilot)
code --add-mcp '{"name":"silica","type":"stdio","command":"uvx","args":["silica-eda@latest"]}'

or in .vscode/mcp.json (workspace) or your user-profile mcp.json:

{
  "servers": {
    "silica": {
      "type": "stdio",
      "command": "uvx",
      "args": ["silica-eda@latest"]
    }
  }
}
Gemini CLI
gemini mcp add -s user silica uvx silica-eda@latest

or in ~/.gemini/settings.json (user) or .gemini/settings.json (project):

{
  "mcpServers": {
    "silica": {
      "command": "uvx",
      "args": ["silica-eda@latest"]
    }
  }
}

Setup wizard

uvx silica-eda@latest setup (or silica setup from a pip install) asks which clients and EDA tools you use, saves the tool choices to ~/.silica/config.toml, and adds a silica server that runs uvx silica-eda@latest to each client's config. It shows each change and asks before writing it; other servers and settings in the file are kept. uvx is written as a full path when it's on PATH, because desktop apps may not see your shell's PATH.

Client What the wizard does
Claude Code Runs claude mcp add --transport stdio --scope user silica -- uvx silica-eda@latest
Claude Desktop mcpServers in claude_desktop_config.json (macOS, Windows, Linux)
Codex CLI Runs codex mcp add silica -- uvx silica-eda@latest
VS Code (Copilot) Runs code --add-mcp '{"name":"silica","type":"stdio","command":"uvx","args":["silica-eda@latest"]}', which adds it to your user profile
Cursor mcpServers in ~/.cursor/mcp.json, with "type": "stdio"
Gemini CLI mcpServers in ~/.gemini/settings.json
Windsurf mcpServers in ~/.codeium/windsurf/mcp_config.json
OpenCode mcp in ~/.config/opencode/opencode.json, as {"type": "local", "command": ["uvx", "silica-eda@latest"]} (macOS, Linux)
Zed context_servers in ~/.config/zed/settings.json (Linux)

Where a client's documentation gives no config path for your platform (Zed on macOS and Windows, OpenCode on Windows), or the existing file can't be read as plain JSON (for example a Zed settings.json with comments), the wizard leaves the file alone and prints the block to add by hand.

Optional extras. capture_serial needs pyserial and run_cocotb needs cocotb. With uvx, add them to the arguments: "args": ["--with", "pyserial", "silica-eda@latest"] (or --with cocotb). With pip, install silica-eda[serial] or silica-eda[cocotb].

Offline. @latest makes uvx ask PyPI for the newest release every time the client starts the server, so without network the server doesn't start (error: Request failed after 3 retries), even when silica is already cached. To work offline, put --offline before the package, "args": ["--offline", "silica-eda@latest"] (the plugin's command can't be edited: disable the plugin with /plugin and add the server with claude mcp add --scope user silica -- uvx --offline silica-eda@latest). uvx then runs the newest release already in its cache, which needs at least one earlier online start. Remove --offline again to get updates.

Pin a version or roll back. Replace silica-eda@latest with an exact version, silica-eda@<version> (for example uvx silica-eda@0.4.0 once that release exists), and the client keeps running that release until you change it. To roll back after a bad release, pin the previous version the same way. The Claude Code plugin always runs @latest; to pin there, add the server with claude mcp add and a pinned version instead of installing the plugin. Releases are listed on PyPI and in the changelog.

MCP tools

Tool Description
doctor Report silica's version, whether a newer release exists, which EDA tools are installed (with versions) and how to install missing ones.
lint Verible, Verilator, svlint or SpyGlass. Verilator elaborates file and extra_files together. Errors and warnings come back with file, line and rule.
format_rtl Format SystemVerilog with verible-verilog-format. Diff-first (dry_run), refuses files with syntax errors.
run_simulation Verilator, Icarus, GHDL, VCS, Questa or Xcelium. Runs in the DUT's directory; returns errors including $fatal/$error messages, an optional VCD (trace, testbench calls $dumpfile/$dumpvars) and Verilator coverage.
run_cocotb Run a cocotb (Python) testbench; per-test pass/fail. Needs the cocotb extra.
read_waveform Read signal transitions from a VCD/FST trace in a time window, without a viewer.
launch_waveform Open a trace in Surfer, GTKWave or Verdi for the user.
read_coverage Summarize a Verilator coverage.dat per file with uncovered lines.
run_formal SymbiYosys prove/bmc/cover, eqy equivalence, JasperGold, VC Formal. failures are reachable counterexamples (with traces); an UNKNOWN prove lists induction_failures instead.
synthesize Yosys, Vivado, Quartus or DC Shell. Utilization, errors with file and line, a JSON netlist for FPGA targets, and (Yosys) every inferred memory with its mapping and whether it has init data.
run_place_route nextpnr for ice40, ECP5, Nexus, MachXO2 and Xilinx 7-series (arch="xilinx", openXC7). Returns a loadable bitstream for Xilinx (.bit via fpga-as), iCE40 (.bin via icepack) and ECP5 (.bit via ecppack). Routed timing per clock and utilization.
program_device openFPGALoader. SRAM by default, SPI flash on request; a Xilinx load counts as success only when the FPGA asserts DONE. Takes .bit/.bin.
capture_serial Read a UART for a set time, optionally send text, match an expect regex. Opens only the port you name. Needs the serial extra.
get_project_structure List the project's RTL and constraint files.
read_rtl / search_rtl Read a file with line numbers / grep the project's RTL.
write_rtl Change a file, diff-first (dry_run=True by default).
get_constraints Read a constraint file (.xdc, .sdc, .lpf).

Prompts with step-by-step triage scripts: debug_simulation_failure, debug_formal_failure, write_testbench, generate_assertions, close_timing, cdc_review.

Supported tools

Tool Used by Verification
Verilator lint, run_simulation, read_coverage Real tool in CI; used in the Arty A7 flow
Icarus Verilog run_simulation, run_cocotb Real tool in CI; used in the Arty A7 flow
GHDL run_simulation (VHDL) Real tool in CI
cocotb run_cocotb Real tool in CI
Verible, svlint lint, format_rtl Real tools, tested locally (not in CI)
Yosys synthesize Real tool in CI (generic, ice40, xilinx); used in the Arty A7 flow
SymbiYosys, eqy run_formal Real tools in CI
nextpnr-ice40 + icepack run_place_route (arch="ice40") Real tools in CI (place and route, packing); programming mocked only
nextpnr-ecp5 + ecppack run_place_route (arch="ecp5") Real tools in CI (place and route, packing); programming mocked only
nextpnr-nexus, -machxo2 run_place_route Mocked only
openXC7 nextpnr-xilinx + fpga-as run_place_route (arch="xilinx") Tested on hardware (Arty A7-100T)
openFPGALoader program_device Tested on hardware (Arty A7-100T); iCE40 and ECP5 mocked only
pyserial capture_serial Tested on hardware; pty-based tests in CI
Surfer, GTKWave, Verdi launch_waveform Untested (fire-and-forget launch)
VCS, Questa, Xcelium run_simulation Mocked only
Vivado synthesize Mocked only; synthesis only
Quartus, DC Shell synthesize Mocked only
JasperGold, VC Formal run_formal Mocked only
SpyGlass lint Mocked only

"Real tool in CI" means the weekly integration workflow runs it from OSS CAD Suite. "Tested on hardware" means the manual Arty A7-100T run described under What works today. "Mocked only" means unit tests with captured or representative output, never a real install.

Checking a design on hardware

program_device and capture_serial close the loop on a real board: program it, then read what the design prints. capture_serial needs pyserial, from the serial extra:

pip install "silica-eda[serial]"

A typical check after run_place_route has produced a bitstream, here checking that the firmware on an Arty A7-100T echoes what it receives:

program_device(bitstream="build/soc.bit", board="arty_a7_100t")
  -> {"success": true, ...}

capture_serial(port="/dev/serial/by-id/usb-Digilent_Digilent_USB_Device_<serial>-if01-port0",
               baud=115200, duration=6, send="hello silica\r", send_delay=0.5,
               expect="hello silica")
  -> {"matched": true, "match": "hello silica", "elapsed_s": 0.53,
      "lines": [{"t": 0.526, "text": "hello silica"}], ...}

Name the port explicitly; silica never scans for serial devices. On boards with an FTDI JTAG+UART bridge (Digilent Arty, Basys, Nexys) the UART is the second interface, if01. The design starts running as soon as programming finishes, so a banner printed at boot is usually gone before a capture opened afterwards: send something the firmware answers (as above), or press the board's reset button during the capture. If the port is missing or your user can't open it, the result carries an error and a fix such as:

sudo setfacl -m u:you:rw /dev/ttyUSB1   (temporary: lasts until the device is unplugged);
permanent: sudo usermod -aG uucp you, then log out and back in

Xilinx 7-series flow

With openXC7 set up, an Artix-7 design goes from RTL to a programmed board in three calls:

synthesize(top_module="soc_top", files=["rtl/soc_top.sv", ...], target="xilinx", tool="yosys")
  -> {"netlist": "/tmp/silica_synth_.../netlist.json", "memories": [...], ...}

run_place_route(netlist="<netlist>", arch="xilinx", device="xc7a100tcsg324-1",
                constraint="arty.xdc", freq=100, output="build/soc.bit")
  -> {"output": "build/soc.bit", "timing_summary": {"clocks": [{"max_freq_mhz": 153.4, "pass": true}]}, ...}

program_device(bitstream="build/soc.bit", board="arty_a7_100t")
  -> {"success": true, ...}

device is the full part with speed grade. For the Arty A7-100T the openFPGALoader board is arty_a7_100t (arty is the 35T).

Configuration

Controlling tool selection

By default every detected tool is available and auto picks the best one (open-source first). To control this per category, edit ~/.silica/config.toml:

[tools.simulation]
priority = ["verilator", "iverilog"]   # ordering for auto-selection
enabled  = ["verilator", "iverilog"]   # allowlist — everything else is blocked

priority reorders what auto tries. enabled is an enforced allowlist: tools not on it can't be used even when the model asks for one explicitly — the request is rejected with an error naming the tool and what's enabled, so the model can retry with an allowed one. Useful when a machine has commercial tools installed that shouldn't be run (license pools, air-gapped flows). Leave enabled empty or unset for no restriction.

Categories: simulation, synthesis, place_route, formal, lint, format, waveform, program.

Guardrails

Built for pointing an autonomous agent at a real repo:

  • File access is confined to the project directory — read_rtl, write_rtl, format_rtl, get_constraints, search_rtl and get_project_structure reject absolute or .. paths that escape the project root (SILICA_PROJECT_ROOT, the project.root config key, or the directory the server was started in). Relative paths are resolved against that root.
  • Writes are diff-first — write_rtl defaults to a dry run that returns a unified diff; nothing touches disk until explicitly confirmed.
  • A hung tool never kills the server — every tool call has a timeout and returns a structured error instead of crashing the session.

CLI

Command Description
silica serve Start the MCP server (stdio). Default when no subcommand is given. silica-eda is the same command.
silica setup Interactive wizard that writes MCP client configs that start the server with uvx silica-eda@latest; see Setup wizard.
silica config Show the configuration and which tools are detected.
silica --version, silica --help Print the version, or the commands.

Versioning and compatibility

silica follows Semantic Versioning, applied to what MCP clients and agents depend on: tool names, their parameters, and the fields in their results. The same rules hold for 0.x releases.

  • Within a major version no tool is renamed or removed, no parameter is removed or made required, and no result field is removed or renamed. Minor releases may add tools, optional parameters and result fields.
  • Deprecations are announced in CHANGELOG.md and in the affected tool's description at least one minor release before the change ships in the next major version.
  • Every user-visible change is listed in the changelog when it merges, under "Unreleased", and moves under the version heading at release.

Development

git clone https://github.com/simaanc/silica-eda
cd silica-eda
uv sync                                       # editable install + dev deps
uv run ruff check silica/ tests/ scripts/
uv run pytest tests/ -q                       # integration tests skip tools that aren't installed
uv run silica serve                           # run the server from the checkout

See CONTRIBUTING.md for conventions, docs/architecture.md for the code layout, and RELEASING.md for releases.

License

silica is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0-only). You can use, modify and redistribute it, including commercially. If you distribute a modified version, or run one as a service that others interact with over a network, you must make your changes' source available under the same license.

Metadata

Release files for silica-eda 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for silica-eda 0.5.0
File Size Uploaded Provenance
silica_eda-0.5.0.tar.gz 253.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for silica-eda 0.5.0
File Interpreter ABI Platform
silica_eda-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 415.7 kB

Release files / silica_eda-0.5.0.tar.gz

Download URL silica_eda-0.5.0.tar.gz
Size 253.5 kB
Tags Source
SHA-256 checksum
How to use checksums
0c0eb3e24881549af728e0e7b4725b3c422bb46e79a78ed6942cb6362c92633b
BLAKE2b-256 checksum
How to use checksums
5251681283c7b3a9b47e0d4868db0774883ebb808507eb07456e4f14fb22d92a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.3 {"installer":{"name":"uv","version":"0.13.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / silica_eda-0.5.0-py3-none-any.whl

Download URL silica_eda-0.5.0-py3-none-any.whl
Size 162.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b72206b4cf4990be7718d4990fd8d3145effb6381a843889d91172eaf5db9b0a
BLAKE2b-256 checksum
How to use checksums
3a11f030e853c513fbe3c6fac69f6679be6fa84bd5bffe0737fab0b56a423003
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.3 {"installer":{"name":"uv","version":"0.13.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for silica-eda 0.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page