VS Code Extension for riSim
1. Overview
The riSim VS Code extension provides an integrated VHDL simulation and waveform visualization environment within Visual Studio Code.
This extension transforms VS Code into a complete VHDL development and debugging environment, offering:
- Interactive Waveform Viewer: GPU-accelerated waveform visualization with WebGL shaders
- Design Hierarchy Browser: Navigate modules and signals in your VHDL design
- Simulation Control: Run, pause, resume, stop, and restart simulations
- Signal Tracking: Add signals to waveforms directly from code or hierarchy
- Real-time Updates: Live waveform updates as simulation progresses
- Multiple Viewers: Open multiple independent waveform windows
- Markers and Measurements: Place markers and measure time/value differences
2. Architecture
2.1. Components
Extension Core (extension-core/)
- Main extension logic (TypeScript)
- WebSocket communication with event-cache
- VS Code command handlers
- Project navigator and entity tree views
- Spawns and manages event-cache subprocess
Waveform tab (waveform-tab/)
- Svelte-based interactive UI for the waveform tab’s VS Code WebView
- Contains logic to handle size and position and display of UI elements
Message Protocol (message/)
- Type-safe message definitions for waveform tab WebView ↔ extension, WebView ↔ event-cache and the extension ↔ server communication
- Shared TypeScript types and enums
- Protocol versioning
Common Types (common/)
- Shared data structures
- Signal types, time representations
- Configuration types
Logging Infrastructure (logging/)
- Structured logging for debugging
- Log level filtering
- Integration with VS Code output channels
Event-cache MCP server (event-cache-mcp/)
- stdio MCP server that talks to event-cache over WebSocket
- Bundled to
resources/mcp/server.cjs and registered with VS Code for Copilot agent mode
- Exposes hierarchy and waveform query tools beyond the in-process agent tools
Waveform Model (waveform-model/)
- Headless event-cache protocol client and state for a single waveform tab WebView
- Contains websocket message processing and protocol conversion logic
- Contains shared tile metadata/binary parsing logic
- Contains state of the viewport and the waveform entries
- WebGL rendering for high-performance waveform display
- Custom shaders for signal rendering (
shader_code/)
- Signal list management and manipulation
- Time navigation and zoom controls
- Lets tests run frontend protocol flows without loading Svelte UI
2.2. UI and model separation
See docs/architecture.md for a summary of which packages own UI versus protocol, state, and rendering.
3. Key Features
GPU-Accelerated Rendering:
- WebGL-based rendering for smooth scrolling and zooming
- Custom GLSL shaders for different signal types
- Handles thousands of signals efficiently
Signal Display Modes:
- Logic signals: Binary (0/1), multi-state (U/X/Z/W/L/H/-), bit vectors
- Analog signals: Integer and floating-point waveforms
- Drawing modes: Line, step, bar, dots
Time Navigation:
- Pan and zoom with mouse/keyboard
- Jump to specific time
- Find next/previous transition
- Search for signal values
- Marker-based navigation
Delta Cycle Visualization:
- Expand/collapse delta cycles at specific times
- View intermediate signal values within delta cycles
- Essential for debugging VHDL delta cycle behavior
3.2. Simulation Control
Lifecycle Management:
- Compile VHDL sources
- Elaborate design
- Run/stop/pause/resume simulation
- Restart with clean state
Entity Selection:
- Browse available entities in project navigator
- Context menu for quick simulation run
- Support for multiple testbenches
Signal Tracking:
- Add signals from design hierarchy
- Track signals by selecting lines in VHDL code
- Automatic type detection
- Group signals into categories
3.3. Design Hierarchy Browser
The design hierarchy appears in the Design Hierarchy view in the riSim activity bar sidebar.
- Tree view of design structure with multi-select
- Context menu for adding signals to waveform
- Drag signals and modules into the list of tracked signal in the active waveform tab
- Selection and expansion state are remembered per simulation when switching waveform tabs
- The view follows the focused waveform tab; selecting a simulation in the Testbenches sidebar does not change it
- The waveform icon on a simulation focuses that simulation's most-recent waveform tab, opening a new one only if none exists
- Focusing a waveform tab shows its design hierarchy and highlights its simulation in the Testbenches sidebar
3.4. Markers and Measurements
Markers:
- Place named markers at specific times
- Color-coded for easy identification
- Jump between markers
- Rename and remove markers
Measurements:
- Measure time distance between markers
- Measure value differences for analog signals
- Display in configurable time units (fs, ps, ns, us, ms, s)
Cursor Tracking:
- Primary and secondary cursors
- Display signal values at cursor position
- Snap to transitions
3.5. Signal Manipulation
Signal List Operations:
- Reorder signals via drag-and-drop
- Group related signals
- Set display radix (binary, octal, decimal, hexadecimal)
- Color coding for visual grouping
Analog Signal Settings:
- Set Y-axis range (auto or manual)
- Configure drawing mode
- Adjust line thickness
- Toggle grid display
Undo/Redo:
- Complete command history
- Undo/redo for all waveform operations
- Recent command picker
4. Technical Implementation
4.1. WebView Architecture
The waveform viewer runs in an isolated webview context:
Extension Host (Node.js process)
- Spawns event-cache subprocess
- Manages WebSocket connections
- Handles VS Code API calls
Webview (Chromium process)
- Runs Svelte application
- Establishes WebSocket to event-cache
- Renders waveforms with WebGL
- Communicates with extension via message passing
4.2. Communication Flow
┌───────────────────┐ ┌──────────────────┐ ┌──────────────┐ ┌──────────────┐
│ VS Code Extension │◀─────▶│ Webview (Svelte) │◀─────▶│ event-cache │◀─────▶│ GHDL Adapter │
└───────────────────┘ └──────────────────┘ └──────────────┘ └──────────────┘
│ │
▼ ▼
Commands/Config Simulation Events
Extension ↔ Webview: VS Code message API (JSON)
- Extension → Webview: Configuration, commands
- Webview → Extension: User actions, state queries
Webview ↔ event-cache: WebSocket (risim-simulation-protocol)
- Webview → event-cache: Viewport updates, signal tracking requests
- event-cache → Webview: Tiles (metadata + binary payload), status updates
4.3. Rendering Pipeline
- Viewport Update: User pans/zooms waveform
- Request Tiles: Webview sends visible time range and resolution to event-cache
- Tile Generation: event-cache queries layer trees and generates tiles
- Compression: Tiles compressed with zstd
- Transmission: Metadata (JSON) + binary payload sent over WebSocket
- Decompression: Webview decompresses tile data
- GPU Upload: Waveform points uploaded to GPU buffers
- Shader Rendering: Custom shaders draw signals to canvas
4.4. WebGL Shaders
Logic Shader (logic_shader.vert/.frag)
- Renders digital signals (bit/std_logic)
- Handles multi-state values with color coding
- Supports both single-bit and vector displays
Analog Shader (analog_shader.vert/.frag)
- Renders continuous signals (integer/real)
- Line, step, and bar drawing modes
- Y-axis scaling and grid rendering
Text Rendering:
- Value labels and time scales
- Marker labels and measurements
- Signal names in sidebar
4.5. State Management
Svelte Stores:
- Reactive state management for UI
- Separate stores for signals, markers, time range, selection
- Automatic UI updates on state changes
Persistence:
- Waveform configuration saved/restored
- Marker positions and names
- Signal list and display settings
- Viewport state
5. Building
5.1. Prerequisites
System Tools:
jq (JSON processor): sudo apt install jq
- Node.js and npm: via nvm
- Rust toolchain: via rustup
Minimum Versions:
- Node.js: v18+
- npm: v9.8.0+
- Rust: 1.76.0+
5.2. Build Process
On Linux, from vscode-ext/:
# Install dependencies
npm ci
# Build and package platform-specific VSIX files (linux-x64 and win32-x64)
npm run package
This stages event-cache plus Python and GHDL runtime dependencies per platform, then produces dist/risim-{TARGET}-{VERSION}.vsix.
5.3. Development Mode
# Watch mode for TypeScript
npm run watch
# Open in VS Code
code .
Press F5 to launch Extension Development Host.
6. Installation
6.1. From VSIX
code --install-extension dist/risim-linux-x64-*.vsix
6.2. From VS Code
- Open Extensions view (Ctrl+Shift+X)
- Click "..." menu → "Install from VSIX..."
- Select the
.vsix file
7. Usage
Mouse:
- Scroll wheel: Zoom in/out
- Middle-click + drag: Pan horizontally
- Right-click: Context menu
- Click: Place cursor
Keyboard:
- Arrow keys: Move cursor
- +/-: Zoom in/out
- Home/End: Jump to start/end
- Ctrl+Z/Y: Undo/redo
Markers:
- Right-click time axis → "Place Marker"
- Click marker to jump
- Right-click marker to rename/remove
8. AI and Copilot integration
riSim Studio extends GitHub Copilot Chat with three complementary integrations. Together they let you list testcases, run simulations, inspect configuration errors, explore design hierarchies, and query signal values — all from natural language inside VS Code.
| Integration |
VS Code API |
Copilot mode |
Runs in |
Best for |
| Language model tools |
languageModelTools |
Agent |
Extension host |
Fast sidebar queries; running testcases from agent workflows |
@risim chat participant |
chatParticipants |
Ask (and Chat) |
Extension host |
Guided explanations; config help; workflow coaching |
| MCP server |
mcpServerDefinitionProviders |
Agent |
Separate Node process |
Design hierarchy; live signal values; waveform queries |
All three read the same underlying riSim state (the Testbenches sidebar with its nested simulations, risim-config.toml diagnostics, and event-cache). You can use whichever integration is most convenient for your workflow.
┌───────────────────────────────────────────────────────────────────┐
│ GitHub Copilot Chat │
├─────────────────────┬──────────────────────┬──────────────────────┤
│ Agent mode │ Ask / Chat mode │ Agent mode │
│ LM tools (#risim*) │ @risim participant │ MCP tools (risim) │
├─────────────────────┴──────────────────────┴──────────────────────┤
│ riSim extension host │ event-cache-mcp (stdio) │
├──────────────────────────────────┴────────────────────────────────┤
│ event-cache (:15108 / :15109) │
└───────────────────────────────────────────────────────────────────┘
8.1. Overview
Language model tools are functions Copilot can call automatically while planning multi-step tasks in agent mode. riSim contributes four tools that mirror what you see in the Testbenches sidebar (testcases and their nested simulations). They show a confirmation dialog before running testcases.
The @risim chat participant is a domain assistant you invoke explicitly with @risim in the Chat view. It streams markdown answers from the language model, injects workspace context (diagnostics, config file, testcases depending on the slash command), and offers buttons to open risim-config.toml, run all testcases, or open a waveform tab.
The MCP server (riSim event-cache) is a Model Context Protocol server registered by the extension. It runs as a separate process, connects to event-cache over WebSocket, and exposes tools that go deeper than the sidebar — especially design hierarchy and waveform signal queries (get_signal_value, find_transition).
8.2. Prerequisites
- GitHub Copilot Chat installed and signed in
- A workspace folder with
risim-config.toml at its root (try examples/ in this repository)
- riSim extension active — it starts event-cache automatically on activation
- For hierarchy and waveform MCP tools: run at least one testcase in GUI mode so a simulation exists
If you are developing the extension, the default workflow (triggered F5) will build the MCP server artifact (resources/mcp/server.cjs) for you.
This is bundled into the extension and automatically started by VS Code when an agent conversation needs it.
Language model tools extend Copilot agent mode. The agent decides when to call them based on your prompt, or you can reference them explicitly with #.
Enable: Open Copilot Chat → switch to agent mode → open the tools picker → enable the riSim tools (List riSim simulations, List riSim testcases, etc.).
# reference |
Tool name |
What it does |
#risimSimulations |
risim_list_simulations |
Lists simulations in the riSim sidebar (id, label, run state) |
#risimTestcases |
risim_list_testcases |
Lists VUnit testcases discovered for the workspace |
#risimDiagnostics |
risim_get_diagnostics |
Returns risim-config.toml errors from the Problems panel |
#risimRunTestcase |
risim_run_testcase |
Runs testcase(s) by name pattern (* = all) |
Write operations (risim_run_testcase) always show a confirmation dialog before executing.
Examples:
List testcases and ask the agent to pick one to run:
#risimTestcases List my VUnit tests and run the one that looks like a smoke test.
Check configuration before running anything:
Are there any riSim config errors? Use #risimDiagnostics and explain how to fix them.
Run all testcases in GUI mode (opens waveform after simulation):
#risimRunTestcase Run all testcases with guiMode so I can inspect waveforms.
Check simulation status:
#risimSimulations Which simulations are running right now?
What you should see: The agent invokes the tool, shows a confirmation for runs, and summarizes the tool result in its reply. The Testbenches sidebar updates when testcases run or simulations start.
8.4. @risim chat participant (ask mode)
The @risim participant is a conversational riSim assistant. Mention it in Copilot Chat to get streaming markdown answers tailored to VHDL simulation workflows.
Invoke: Type @risim followed by your question, or use a slash command:
| Command |
Purpose |
/explainConfig |
Explains risim-config.toml contents and configuration diagnostics |
/testPlan |
Summarizes discovered testcases and suggests a run order |
/workflow |
Walks through config → testcases → simulation → waveform inspection |
Every request includes current diagnostics from the Problems panel. Slash commands add extra context: config file text (/explainConfig), testcase list (/testPlan), or simulation list (/workflow).
Responses can include action buttons: Open risim-config.toml, Run all testcases, Open waveform tab (when exactly one simulation is active). Follow-up question suggestions appear after each reply in ask mode.
Examples:
Explain configuration problems:
@risim /explainConfig Why can't I run testbenches?
Get a testcase strategy:
@risim /testPlan I have failing integration tests — what order should I run things in?
Learn the end-to-end workflow:
@risim /workflow I'm new to riSim. How do I go from config to viewing signals?
Free-form question (diagnostics injected automatically):
@risim What errors does riSim report for my workspace right now?
What you should see: A streamed markdown reply from riSim, file references to risim-config.toml when relevant, clickable buttons at the bottom, and suggested follow-ups. No tool confirmation dialogs — the participant answers conversationally; use buttons if you want to trigger an action.
8.5. MCP server (agent mode)
The extension registers an MCP server named riSim event-cache. Unlike language model tools, it runs in a separate Node process and talks directly to event-cache over WebSocket (127.0.0.1:15108 control, 127.0.0.1:15109 waveform). This enables capabilities the in-process tools do not have: full design hierarchy trees, live signal value lookups, and reading the UI marker time.
Enable:
- Open a workspace with
risim-config.toml
- Open Copilot Chat → agent mode
- Open the tools picker → enable tools under riSim event-cache
The extension passes RISIM_WORKSPACE_ROOT and RISIM_CONFIG_PATH to the server automatically.
On connect, the server returns instructions in the MCP initialize response. The host may inject these into every agent session — they require calling create_testbench before writing VHDL and using run_testcase instead of GHDL/VUnit CLI commands.
Long-running MCP tools (list_testcases, get_design_hierarchy, run_testcase with wait: true) wait as long as compile and simulation need — there is no artificial timeout. While waiting, the server sends MCP progress heartbeats (phase label and elapsed time) so the host can keep the tool call alive and show activity.
MCP tools:
| Tool |
Description |
list_simulations |
Simulations known to event-cache |
get_design_hierarchy |
Full module/signal tree for a simulation (names, ids, types) |
list_testcases |
Discovered VUnit testcases |
get_diagnostics |
Configuration errors from event-cache |
create_testbench |
Gathers DUT/config context and step-by-step instructions for VUnit testbench generation |
run_testcase |
Start a testcase run; with wait: true, returns plain-text pass/fail summary and simulator reports |
control_simulation |
Start, pause, resume, or stop a simulation |
get_signal_value |
Read a signal at a physical time (femtoseconds) |
find_transition |
Find next/previous transition on a signal |
get_marker_position |
Read the selected marker from the last-focused waveform tab for a simulation |
MCP prompts (slash commands in chat):
| Prompt |
Description |
/mcp.risim.explainWorkflow |
Step-by-step riSim workflow using MCP tools |
/mcp.risim.debugTestbench |
Debug setup: check diagnostics and testcases |
/mcp.risim.generateTestbench |
Generate a VUnit testbench from a spec, run tests, and iterate fixes |
Signal paths use dotted hierarchy names, e.g. tb.dut.clk or tb.bus[0]. Times are in femtoseconds (100 ns = 100000000 fs).
Examples:
Explore hierarchy after a GUI testcase run:
List simulations, then get the design hierarchy for the first one and summarize the top-level signals.
Query a signal value (replace path and time with values from your design):
Using get_signal_value, what is tb.dut.clk at 100000000 fs?
Find when a reset de-asserts:
Use find_transition to find the next transition on tb.dut.reset from 0 fs.
Read the waveform marker, then query a signal at that time:
Use get_marker_position for the simulation, then get_signal_value for tb.dut.clk at the marker physical time.
Run tests and check diagnostics in one flow:
/mcp.risim.debugTestbench
Generate a testbench from a specification:
/mcp.risim.generateTestbench
Create a VUnit testbench for array/sobel_x.vhd using the spec in spec/sobel_x.md.
Blocking testcase run with simulator reports:
Run testcase array_ex.tb_sobel_x.test_input_file_against_output_file with wait enabled and summarize pass/fail and reports.
With wait: true, run_testcase returns plain text: a summary line with the pattern and outcome counts, a shared compile-failure block when compile errors affect multiple testcases, then one line per testcase (PASS, FAIL, or COMPILE_ERROR). Failed simulations include indented report lines: file:line:col @ physical=<fs> fs, delta=<n> [severity]: message.
Control a running simulation:
Pause simulation 12345678901234.
What you should see: The agent calls MCP tools (listed in the chat tool trace), returns hierarchy JSON or signal values in its summary, and may chain multiple tools. If event-cache is not running, tools return a clear connection error — open a riSim workspace and wait for the extension to start event-cache.
8.6. Choosing the right integration
| You want to… |
Use |
| Quickly list testcases or diagnostics during an agent task |
LM tools (#risimTestcases, #risimDiagnostics) |
| Run a testcase from agent mode with confirmation |
LM tool #risimRunTestcase |
| Generate a testbench from a specification |
MCP create_testbench, /mcp.risim.generateTestbench |
| Run testcases and get pass/fail with simulator reports |
MCP run_testcase with wait: true |
| Get a explained walkthrough of config or workflow |
@risim with /explainConfig, /workflow, or /testPlan |
| Open config or waveform from a chat answer |
@risim (response buttons) |
| Inspect module/signal hierarchy |
MCP get_design_hierarchy |
| Read signal values or find transitions |
MCP get_signal_value, find_transition |
| Read the waveform marker position |
MCP get_marker_position |
| Control simulation (pause/stop) from agent mode |
MCP control_simulation |
You can combine them in one session: ask @risim /workflow for orientation, then switch to agent mode with MCP tools to query specific signals after a GUI testcase run.
8.7. Troubleshooting
| Symptom |
What to check |
| riSim tools missing in agent mode |
Workspace folder open; enable tools in the Chat tools picker |
@risim not in participant list |
riSim extension active; reload window |
| MCP server missing |
Extensions view → MCP servers; workspace must have a folder |
| "Cannot connect to event-cache" |
Wait for riSim sidebars to load; Output → riSim; ports 15108/15109 |
| MCP tool appears stuck on compile |
Normal for large projects; progress heartbeats should update every few seconds |
get_marker_position not found |
Open a waveform tab for that simulation and move the marker |
| No simulations listed |
Run a testcase in GUI mode first |
| Signal path not found |
Use get_design_hierarchy and match exact module/signal names |
get_signal_value times out |
Simulation must exist; time must be within simulated range |
| MCP server fails to start |
Run npm run build-mcp; check resources/mcp/server.cjs exists |
| MCP tools stale after MCP code changes |
Run npm run build-mcp, then reload the extension host; accept the tools refresh prompt if shown |
| LM tool run blocked |
Confirm the tool invocation dialog; check "Always allow" if desired |
For MCP issues: MCP: List Servers → riSim event-cache → Show Output.
9. Debugging
9.1. Extension Logs
You can view logs in the riSim output channel of the VS Code window hosting the extension.
In addition, OpenTelemetry logs are exported if the RISIM_VSCODEEXT_LOG_LEVEL environment variable is set to the desired log level.
9.2. Webview Console
- Open Command Palette (Ctrl+Shift+P)
- Run: "Developer: Open Webview Developer Tools"
- Check Console tab for webview logs
10. Automated Testing
10.1. Test Architecture
The extension now separates frontend protocol logic from GUI components:
waveform-model/ holds headless protocol and tile state logic.
waveform-tab/svelte/ holds Svelte UI and WebGL rendering.
waveform-tab/test/test-model.html loads a minimal harness for protocol tests.
waveform-tab/test/test-render.html loads a minimal harness for shader/render tests.
event-cache-mcp/test/ holds Vitest integration tests for the MCP server; each test starts its own event-cache process and uses a Rust fake_simulator fixture for waveform and simulation state setup.
All automated frontend tests run with Playwright in headless Chromium, which is close to the Electron/Chromium runtime used by VS Code webviews.
10.2. Running Tests
From vscode-ext/:
# Build test harness bundles
npm run build-playwright-tests
# Build and run all Playwright tests
npm run test:playwright
# Install browser binary once (if needed)
npx playwright install chromium
MCP server integration tests
From the repository root, build event-cache and the test fixture:
cargo build -p event-cache
cargo build -p event-cache --example fake_simulator
From vscode-ext/:
npm install
npm run test:mcp
Notes:
- Uses the
examples/ workspace via absolute paths resolved from the repository root.
- Tests are skipped automatically when the binaries are not present.
- No LLM or API keys are required; tests call MCP tools directly via an in-memory transport.
Playwright tests
- Protocol tests that require a running
event-cache binary are skipped automatically when the binary is not present.
- Shader snapshot tests currently cover logic rendering directly; analog/literal test cases are scaffolded and can be enabled incrementally as shader-compatibility work progresses.
11. Known Issues
- Large simulations: Memory usage grows with simulation time
- Use trimming manager settings to control
- Delta cycle expansion: May slow down with many delta cycles
- Array signals: Not yet fully supported
- Undo depth: Limited to last 100 actions
12. Future Enhancements
- VCD import: Load standard VCD waveform files
- Custom signal formats: User-defined value formatting
- Python scripting: Scriptable waveform analysis
- Remote simulation: Connect to simulations on remote servers
- Diff mode: Compare two simulation runs side-by-side
13. See Also
event-cache: Backend data service for waveform storage
ghdl/adapter: GHDL simulator integration layer
risim-simulation-protocol: WebSocket protocol definitions
hdl-simulation-protocol: Simulator communication protocol
14. License and Third-Party Notices
riSim Studio is proprietary software; see LICENSE.txt.
The extension bundles and incorporates third-party components (including the GHDL simulator under the GNU GPL v2, a CPython runtime, VUnit under the MPL 2.0, and numerous permissively licensed Rust and JavaScript libraries).
Their licenses, attributions, and the corresponding-source offer for GHDL are collected in THIRD_PARTY_NOTICES.md.
Full license texts are in third-party-licenses/.