Skip to main content
Glama

Waveform MCP — AI-Friendly VCD/FSDB Waveform Debugger

A Model Context Protocol (MCP) server that gives AI agents the ability to read, analyze, and debug VCD/FSDB waveform files from digital circuit simulations.

Parse a waveform once, then query signals, find AXI transactions, render ASCII waveforms, and validate protocol compliance — all through structured JSON-RPC tools.

Features

  • Stateful session: Parse once, query many times. Large files cached in memory.

  • VCD + FSDB support: Native VCD parsing; FSDB via Verdi's fsdb2vcd auto-conversion.

  • 32 structured tools: Signal search, snapshot, edge detection, transaction analysis, AXI write/read channel correlation, burst aggregation, bus-level protocol checks, clock analysis, signal activity stats, dual-waveform diff, value diff between times, ASCII rendering, multi-session comparison, signal aliases, and more.

  • Smart signal search: Ranked relevance matching (exact > base name > suffix > component > substring), with support for bit-select suffixes like wdata[31:0].

  • AXI transaction analysis: Automatically extract valid-ready transactions from all 5 AXI channels (AW/W/B/AR/R) with captured data values. One-call analyze_axi_channel auto-detects signals, aggregates W beats into bursts by wlast, and reports throughput/gap/duration statistics. analyze_axi_write/analyze_axi_read correlate address+data+response channels into complete transfers with latency breakdown.

  • Bus-level protocol checks: Detect AXI protocol violations including data instability while VALID=1/READY=0, BVALID before WLAST, and zero-width valid pulses.

  • Clock & activity analysis: Auto-detect clock signals and report period, frequency, duty cycle, jitter, and gating. Find dead signals (never toggle) and rank signals by change activity.

  • Dual-waveform diff: Compare two loaded waveforms signal-by-signal, report first mismatch time and value for each differing signal. Matches signals by base name across hierarchies.

  • Multi-session support: Load multiple waveforms simultaneously (e.g. golden vs actual) under different session IDs, switch between them, or pass session_id to any tool for cross-waveform comparison.

  • Signal aliases: Define short aliases for long hierarchical paths (e.g. tb.dut.u_memory.wdata[31:0]wdata), usable anywhere a signal name is expected.

  • Flexible time inputs: All time parameters accept integers (picoseconds) or human-readable strings like "100ns", "1.5us", "500ps".

  • ASCII waveform rendering: View timing diagrams directly in the conversation without a waveform viewer. Linear-scan rendering with collision-free time scale and right-boundary labeling.

  • Protocol compliance checking: Detect valid-ready handshake violations.

  • Pickle cache: Large files reload in seconds instead of minutes.

  • CLI fallback: Human-friendly command-line interface for manual debugging.

Related MCP server: EDA Tools MCP Server

Architecture

src/waveform_mcp/core.py    (core library, pure stdlib, no MCP dependency)
   ├── src/waveform_mcp/server.py  (MCP Server — 32 tools over stdio JSON-RPC)
   └── src/waveform_mcp/cli.py     (CLI — backward-compatible, human-friendly)

The core library (core.py) contains all parsing and analysis logic. It can be used standalone in Python scripts, or exposed via MCP or CLI. The package uses a standard src/ layout and is installable via pip install -e ..

Installation

Requirements

  • Python >= 3.10

  • mcp >= 2.0 (for MCP Server; CLI and core library don't need it)

  • Verdi with fsdb2vcd in PATH (only for FSDB files; VCD files don't need it)

Install (package mode, optional)

pip install -e ".[mcp]"     # installs core + MCP SDK
pip install -e .             # core only (zero dependencies, for CLI/scripts)

Install MCP dependency (manual mode)

pip install "mcp[cli]"

Clone / copy the project

# All files are self-contained in this directory
cd D:\workspace\waveform_mcp

No build step required. The project is pure Python.

MCP Server Deployment

Claude Desktop

Edit claude_desktop_config.json (location varies by OS):

Windows: %APPDATA%\Claude\claude_desktop_config.json

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

Linux: ~/.config/Claude/claude_desktop_config.json

{

  "mcpServers": {

    "waveform-debugger": {

      "command": "python",

      "args": \["D:\\\workspace\\\waveform\_mcp\\\waveform\_mcp.py"]

    }

  }

}

Restart Claude Desktop. The server will appear in the MCP status indicator with 17 tools.

Cursor

Create or edit .cursor/mcp.json in your project root:

{

  "mcpServers": {

    "waveform-debugger": {

      "command": "python",

      "args": \["D:\\\workspace\\\waveform\_mcp\\\waveform\_mcp.py"]

    }

  }

}

Restart Cursor. Enable the server in Settings > MCP.

Other MCP-compatible clients

Any MCP 2.x-compatible client (Cline, Continue, custom agents) can connect via stdio:

{

  "command": "python",

  "args": \["D:\\\workspace\\\waveform\_mcp\\\waveform\_mcp.py"]

}

Verify the server is working

\# List registered tools (should show 17)

python -c "import asyncio, sys; sys.path.insert(0,'.'); from waveform\_mcp import server; print(asyncio.run(server.list\_tools()).\_\_len\_\_())"

\# Run full MCP communication test

python test\_mcp\_server.py

Tool Reference

Session Management

Tool

Description

load_waveform(path, use_cache=true, session_id?)

Load a VCD/FSDB file and parse into memory. Must be called first. session_id for multi-waveform comparison.

get_waveform_info(session_id?)

Get signal count, module count, max time, timescale, module list.

unload_waveform()

Unload all sessions and free memory.

list_sessions()

List all loaded sessions and the active session ID.

switch_session(session_id)

Switch the active session.

close_session(session_id?)

Close a specific session and free its memory.

Signal Aliases

Tool

Description

set_alias(alias, signal_name, session_id?)

Define a short alias for a long hierarchical signal path. Usable anywhere a signal name is expected.

list_aliases(session_id?)

List all user-defined aliases.

remove_alias(alias, session_id?)

Remove a user-defined alias.

Tool

Description

list_modules()

List all module hierarchy paths.

list_signals(module?, pattern?)

List signals, optionally filtered by module or name pattern.

search_signals(pattern, match_mode="auto", exclude_constants=false)

Search signals by name. auto mode ranks by relevance. Supports [31:0] suffixes.

Match modes:

  • auto — ranked relevance (recommended)

  • exact — exact full path match

  • suffix — base name ends with pattern (supports bit-select suffixes)

  • contains — case-insensitive substring

  • regex — regular expression

Time Queries

Tool

Description

snapshot(time, signals, session_id?)

Get signal values at a specific time (bin/hex/dec). time accepts int (ps) or "100ns"/"1.5us".

watch_signals(signals, trigger?, time_window?, max_events=10, trigger_on="first", session_id?)

Track values over time. trigger_on="any" reports when ANY signal changes; each event includes triggered_by.

next_edge(signal, from_time, edge="rising", session_id?)

Find next rising/falling edge after a time.

prev_edge(signal, from_time, edge="rising", session_id?)

Find previous rising/falling edge before a time.

find_edges(signal, edge="both", max_n=100, session_id?)

Find all edges of a signal.

Transaction Analysis

Tool

Description

find_transactions(valid_signal, data_signals, ready_signal?, max_n=10, session_id?)

Find valid-ready transactions and capture data values at each start. Registered-ready handshake time is correct (end = ready assertion, not valid fall).

analyze_axi_channel(channel_prefix, max_n=100, session_id?)

One-call AXI channel analysis: auto-detect signals, extract transactions, aggregate W beats into bursts by wlast, report throughput/gap/duration stats. Channel: aw/w/b/ar/r.

get_transaction_stats(valid_signal, data_signals, ready_signal?, max_n=100, bytes_field?, session_id?)

Extract transactions and compute cross-transaction stats: count, duration min/avg/max, gap min/avg/max, total bytes, throughput Mbps.

compare_transaction_fields(transactions, expected_field, actual_field)

Compare two fields across all transactions, find mismatches.

analyze_axi_write(max_n=100, session_id?)

Correlate AW+W+B channels into complete write transfers with latency breakdown (AW->W, W-burst, WLAST->B, total). Time-proximity matching handles unequal channel counts.

analyze_axi_read(max_n=100, session_id?)

Correlate AR+R channels into complete read transfers with latency breakdown (AR->R-first, R-burst, total).

Protocol, Clock & Activity Analysis

Tool

Description

check_axi_protocol(channel="write", session_id?)

AXI bus-level protocol checks: data stability while VALID=1/READY=0, BVALID before WLAST, zero-width valid pulses.

analyze_clock(clock_signal?, session_id?)

Auto-detect clock and report period, frequency, duty cycle, jitter, and gating periods.

signal_activity_stats(module?, top_n=20, session_id?)

Rank signals by change count, find dead signals (never toggle), report average changes per signal.

Value Diff & Comparison

Tool

Description

value_diff_between_times(t1, t2, signals?, session_id?)

Find all signals whose value changed between two time points. Useful for "what changed after reset?".

compare_waveforms(session_a, session_b, signals?, time_window?)

Compare two loaded waveforms signal-by-signal, report first mismatch time and value for each differing signal.

Visualization

Tool

Description

render_ascii_waveform(signals, time_start, time_end, width=80, session_id?)

Render ASCII timing diagram with collision-free time scale and right-boundary label. Linear-scan for performance.

Validation & Checking

Tool

Description

check_signal_value(signal, expected_value, at_time, session_id?)

Check if signal equals expected value (bin/hex/dec).

find_signal_mismatch(signal_a, signal_b, time_window?, session_id?)

Find times when two signals differ.

check_valid_ready_protocol(valid_signal, ready_signal, session_id?)

Detect valid-ready handshake violations.

Example Workflow (Agent Debugging AXI2MEM)

Here's how an agent would use the tools to debug a waveform:

1\. load\_waveform(path="/path/to/axi2mem\_tb.vcd")

   → 671 signals, 66 modules, 475us max time

2\. search\_signals(pattern="awvalid", exclude\_constants=true)

   → \["axi2mem\_tb.awvalid", ...]

3\. find\_transactions(

     valid\_signal="awvalid",

     data\_signals=\["awaddr", "awlen", "awsize", "awburst"],

     ready\_signal="awready",

     max\_n=5

   )

   → 5 write address transactions with addresses and lengths

4\. find\_transactions(

     valid\_signal="wvalid",

     data\_signals=\["wdata", "wstrb", "wlast"],

     ready\_signal="wready",

     max\_n=5

   )

   → 5 write data transactions:

     \[0] 115ns wdata=0xDEADBEEF wstrb=0xF wlast=1

     \[1] 385ns wdata=0xA0000000 wstrb=0xF wlast=0

     ...

5\. render\_ascii\_waveform(

     signals=\["clk", "awvalid", "awready", "wvalid", "wready"],

     time\_start=90000, time\_end=110000, width=80

   )

   → ASCII timing diagram showing handshake timing

6\. check\_valid\_ready\_protocol(valid\_signal="wvalid", ready\_signal="wready")

   → 0 violations (clean protocol)

CLI Usage

The CLI (src/waveform_mcp/cli.py) provides a human-friendly interface for manual debugging. It is backward-compatible with the original script.

List signals

python debug\_waveform.py --vcd waveform.vcd --list-signals

python debug\_waveform.py --vcd waveform.vcd --list-signals --pattern valid

Snapshot at a time

python debug\_waveform.py --vcd waveform.vcd --watch result mode --time 95000

python debug\_waveform.py --vcd waveform.vcd --watch result mode --time 95000 --json

Time-series with trigger

python debug\_waveform.py --vcd waveform.vcd --watch result mode --trigger valid -n 20

Time window trace

python debug\_waveform.py --vcd waveform.vcd --watch valid result --time 95000-97500

Transaction analysis (new)

python debug\_waveform.py --vcd waveform.vcd \\

  \--transactions valid\_out \\

  \--data result mode overflow \\

  \--ready ready\_in \\

  -n 5

ASCII waveform (new)

python debug\_waveform.py --vcd waveform.vcd \\

  \--ascii clk valid\_out ready\_in result \\

  \--time 90000-110000 \\

  \--width 100

FSDB support

python debug\_waveform.py --vcd waveform.fsdb --watch result --time 95000

Requires fsdb2vcd from Verdi in PATH.

Cache (new)

python debug\_waveform.py --vcd huge.vcd --cache --watch result --time 95000

First load parses and saves cache; subsequent loads are ~5x faster.

Python API Usage

Use the core library directly in scripts:

from waveform\_core import WaveformSession

\# Load waveform

session = WaveformSession("/path/to/waveform.vcd", use\_cache=True)

\# Search signals

valid\_signals = session.search\_signals("valid", exclude\_constants=True)

\# Snapshot

snap = session.snapshot(95000, \["result", "mode"])

print(snap\["signals"]\["result"]\["hex"])

\# Find AXI transactions

txs = session.find\_transactions(

    "awvalid", \["awaddr", "awlen"],

    ready\_signal="awready", max\_n=10

)

for tx in txs:

    print(f"  addr={tx\['data']\['awaddr']\['hex']} len={tx\['data']\['awlen']\['hex']}")

\# ASCII waveform

wave = session.render\_ascii(\["clk", "valid", "ready"], 90000, 110000, width=80)

print(wave)

\# Protocol check

violations = session.check\_valid\_ready\_protocol("valid", "ready")

session.unload()

FSDB Support

FSDB (Fast Signal Database) is Synopsys Verdi's proprietary format. Since it's not open, this project uses Verdi's fsdb2vcd command-line tool for conversion:

  1. When you load a .fsdb file, the server automatically calls fsdb2vcd to convert it to a temporary VCD.

  2. The converted VCD is then parsed normally.

  3. The temporary file is cleaned up on unload.

Requirements:

  • Verdi installed with fsdb2vcd in PATH, or

  • Set VERDI_HOME environment variable, or

  • Pass fsdb2vcd_path explicitly in Python API

Limitations:

  • Conversion adds overhead (proportional to file size).

  • FSDB-specific features (like signal hierarchy browsing in Verdi) are not available.

  • For very large FSDB files, consider converting to VCD manually first.

Testing

Core library tests (synthetic VCD)

python test\_waveform\_core.py

12 tests covering: load/parse, search, snapshot, transactions, edges, ASCII rendering, protocol check, cache, watch signals, mismatch detection, module listing.

MCP communication tests

python test\_mcp\_server.py

8 tests covering the full stdio JSON-RPC lifecycle: initialize, tools/list, load_waveform, search, snapshot, transactions, ASCII rendering, unload.

End-to-end agent workflow test

python test\_e2e\_mcp.py                          # auto-detects real VCD, falls back to synthetic

python test\_e2e\_mcp.py /path/to/your/waveform.vcd

15-step simulation of a full agent debugging session over real stdio JSON-RPC: initialize → tools/list → load → search (7 patterns) → list_modules → snapshot → find_transactions (all AXI channels) → render_ascii → find_edges/next_edge → protocol_check → watch_signals (trigger) → check_signal_value → unload. Uses real AXI2MEM VCD when available.

Real VCD tests

python test\_real\_vcd.py /path/to/your/waveform.vcd

10 tests against a real waveform: load performance, module/signal inventory, search patterns, snapshot at multiple times, edge detection, watch with trigger, AXI transaction analysis (5 channels), ASCII rendering, protocol check, cache performance.

Generate a test VCD

python generate\_test\_vcd.py

Creates test_waveform.vcd with a simple valid-ready pipeline for quick testing.

File Structure

waveform\_mcp/

├── AGENTS.md                    # Agent rules file (project context, run commands, conventions)

├── README.md                    # This file

├── WAVEFORM\_MCP\_DESIGN.md      # Detailed design document (architecture, API, roadmap)

├── waveform\_core.py             # Core library: parsing, querying, analysis (no MCP dep)

├── waveform\_mcp.py              # MCP Server: 17 tools over stdio JSON-RPC

├── debug\_waveform.py            # CLI: human-friendly command-line interface

├── generate\_test\_vcd.py         # Test VCD generator

├── test\_waveform\_core.py        # Core library test suite (12 tests)

├── test\_mcp\_server.py           # MCP communication test suite (8 tests)

├── test\_e2e\_mcp.py              # End-to-end agent workflow test (15 steps, real VCD support)

├── test\_real\_vcd.py             # Real VCD test suite (10 tests)

└── test\_waveform.vcd            # Generated test VCD (small, synthetic)

Performance

Measured on a 22MB VCD (671 signals, 475us simulation):

Operation

Time

Initial parse

2.0s

Cache load (2nd time)

0.75s

Snapshot query

0.1-0.6ms

Transaction analysis (5 tx)

0.2ms

ASCII render (80 chars)

0.3ms

Protocol check

0.3ms

For files >100MB, use --cache or use_cache=True to avoid re-parsing.

Troubleshooting

"No module named 'mcp'"

Install the MCP SDK:

pip install "mcp\[cli]"

"fsdb2vcd not found"

  • Ensure Verdi is installed and fsdb2vcd is in PATH.

  • Or set the VERDI_HOME environment variable.

  • Or convert FSDB to VCD manually: fsdb2vcd -i input.fsdb -o output.vcd

MCP server not showing up in client

  • Check the path in the config is correct (use absolute paths).

  • Check Python is in PATH (use full path to python.exe if needed).

  • Run python src/waveform_mcp/server.py directly — it should start and wait for input (no errors).

  • Check client logs for connection errors.

Signal search returns too many results

  • Use exclude_constants=true to filter out parameters and constants.

  • Use more specific patterns (e.g., awvalid instead of valid).

  • Use match_mode="suffix" for exact base-name suffix matching.

ASCII waveform looks wrong

  • Ensure the time window is correct (in picoseconds).

  • For multi-bit signals, values are shown as hex labels at change points.

  • Increase width for more detail.

Design Document

See docs/DESIGN.md for the full design document, including:

  • Detailed architecture and design principles

  • Complete API specification

  • Tool-by-tool parameter reference

  • FSDB support design (two approaches)

  • Deployment configuration for all clients

  • Extension roadmap (v1.1, v1.2, v2.0)

  • Verification checklist

License

Internal use.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables analysis of RTL waveform files (VCD, FST) through WAL (Waveform Analysis Language). Supports signal inspection, transition extraction, and advanced waveform queries for hardware design verification.
    16
    BSD 3-Clause
  • F
    license
    Not graded
    quality
    B
    maintenance
    An MCP server that provides AI assistants with a persistent, sandboxed Python environment for waveform analysis, enabling loading and manipulation of VCD/FST/FSDB files and temporal pattern matching.
    9
    -
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to analyze hardware simulation VCD waveforms and GTKWave save files, providing access to signal values, bus definitions, and groupings without loading entire files.
    5
    MIT