wave-mcp 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wave_mcp-0.2.4/CHANGELOG.md +337 -0
- wave_mcp-0.2.4/LICENSE +27 -0
- wave_mcp-0.2.4/MANIFEST.in +11 -0
- wave_mcp-0.2.4/PKG-INFO +547 -0
- wave_mcp-0.2.4/README.en.md +607 -0
- wave_mcp-0.2.4/README.md +518 -0
- wave_mcp-0.2.4/docs/PACKAGING_MATERIALS.md +88 -0
- wave_mcp-0.2.4/docs/THIRD_PARTY.md +223 -0
- wave_mcp-0.2.4/docs/licenses/EUPL-1.2.txt +287 -0
- wave_mcp-0.2.4/docs/licenses/GPL-2.0.txt +340 -0
- wave_mcp-0.2.4/docs/licenses/LGPL-2.1.txt +501 -0
- wave_mcp-0.2.4/docs/licenses/README.md +46 -0
- wave_mcp-0.2.4/docs/licenses/TraceWeave-MIT.txt +21 -0
- wave_mcp-0.2.4/docs/licenses/epaint-default-fonts.OFL-1.1.txt +97 -0
- wave_mcp-0.2.4/docs/licenses/epaint-default-fonts.SOURCES.txt +25 -0
- wave_mcp-0.2.4/docs/licenses/epaint-default-fonts.Ubuntu-font-1.0.txt +96 -0
- wave_mcp-0.2.4/docs/licenses/epaint-default-fonts.emoji-icon-font.MIT.txt +9 -0
- wave_mcp-0.2.4/docs/licenses/fstdumper-GPL-3.0.txt +674 -0
- wave_mcp-0.2.4/docs/licenses/fstdumper-sys_fst.NOTICE +18 -0
- wave_mcp-0.2.4/docs/licenses/fstdumper.SOURCES.json +10 -0
- wave_mcp-0.2.4/docs/licenses/vcd2fst.SOURCES.json +41 -0
- wave_mcp-0.2.4/docs/licenses/vcd2fst.fastlz.LICENSE +27 -0
- wave_mcp-0.2.4/docs/licenses/vcd2fst.fstapi.LICENSE +23 -0
- wave_mcp-0.2.4/docs/licenses/vcd2fst.helper.LICENSE +21 -0
- wave_mcp-0.2.4/docs/licenses/vcd2fst.jrb.LICENSE +9 -0
- wave_mcp-0.2.4/docs/licenses/vcd2fst.lz4.LICENSE +33 -0
- wave_mcp-0.2.4/pyproject.toml +57 -0
- wave_mcp-0.2.4/setup.cfg +4 -0
- wave_mcp-0.2.4/wave_mcp/__init__.py +10 -0
- wave_mcp-0.2.4/wave_mcp/cli/__init__.py +1 -0
- wave_mcp-0.2.4/wave_mcp/cli/build_session.py +147 -0
- wave_mcp-0.2.4/wave_mcp/cli/main.py +21 -0
- wave_mcp-0.2.4/wave_mcp/cli/query.py +194 -0
- wave_mcp-0.2.4/wave_mcp/cli/vcd2fst.py +61 -0
- wave_mcp-0.2.4/wave_mcp/convert.py +786 -0
- wave_mcp-0.2.4/wave_mcp/diff.py +211 -0
- wave_mcp-0.2.4/wave_mcp/netlist/__init__.py +15 -0
- wave_mcp-0.2.4/wave_mcp/netlist/expr_eval.py +225 -0
- wave_mcp-0.2.4/wave_mcp/netlist/name_infer.py +171 -0
- wave_mcp-0.2.4/wave_mcp/netlist/slang_netlist.py +1135 -0
- wave_mcp-0.2.4/wave_mcp/netlist/trace_engine.py +584 -0
- wave_mcp-0.2.4/wave_mcp/pipeline.py +466 -0
- wave_mcp-0.2.4/wave_mcp/server.py +1004 -0
- wave_mcp-0.2.4/wave_mcp/session.py +268 -0
- wave_mcp-0.2.4/wave_mcp/sources/__init__.py +1 -0
- wave_mcp-0.2.4/wave_mcp/sources/fst_source.py +747 -0
- wave_mcp-0.2.4/wave_mcp/sources/rtl_source.py +566 -0
- wave_mcp-0.2.4/wave_mcp/timeutil.py +72 -0
- wave_mcp-0.2.4/wave_mcp/viewer/__init__.py +219 -0
- wave_mcp-0.2.4/wave_mcp/viewer/cli.py +104 -0
- wave_mcp-0.2.4/wave_mcp/viewer/manager.py +255 -0
- wave_mcp-0.2.4/wave_mcp/viewer/server.py +255 -0
- wave_mcp-0.2.4/wave_mcp/viewer/state.py +237 -0
- wave_mcp-0.2.4/wave_mcp/viewer/surver.py +199 -0
- wave_mcp-0.2.4/wave_mcp/viewer/translate.py +144 -0
- wave_mcp-0.2.4/wave_mcp/viewer/web/demos.html +62 -0
- wave_mcp-0.2.4/wave_mcp/viewer/web/shell.html +87 -0
- wave_mcp-0.2.4/wave_mcp/viewer/web/shell.js +386 -0
- wave_mcp-0.2.4/wave_mcp/viewer/web/sw.js +65 -0
- wave_mcp-0.2.4/wave_mcp/viewer/web/view.html +132 -0
- wave_mcp-0.2.4/wave_mcp.egg-info/PKG-INFO +547 -0
- wave_mcp-0.2.4/wave_mcp.egg-info/SOURCES.txt +64 -0
- wave_mcp-0.2.4/wave_mcp.egg-info/dependency_links.txt +1 -0
- wave_mcp-0.2.4/wave_mcp.egg-info/entry_points.txt +5 -0
- wave_mcp-0.2.4/wave_mcp.egg-info/requires.txt +6 -0
- wave_mcp-0.2.4/wave_mcp.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to wave-mcp are documented here. Format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions follow
|
|
5
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [0.2.4] - 2026-09-08
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **TraceWeave attribution completed, with implementation reference and design
|
|
12
|
+
influence stated separately.** A closer review of our own commit history showed
|
|
13
|
+
that the earlier notices, while accurate as far as they went, described a
|
|
14
|
+
narrower scope than what had actually been consulted, and that two different
|
|
15
|
+
kinds of influence were being collapsed into one sentence. Both are now
|
|
16
|
+
separated:
|
|
17
|
+
- Code-level references, all within the FSDB converter: `ParseScaleFs` was
|
|
18
|
+
implemented with reference to TraceWeave's `_ParseScaleFs` (unit conversion
|
|
19
|
+
plus the parse-failure convention); the `ffrAPI` stub mirrors the subset it
|
|
20
|
+
exercises and follows the same FsdbReader build layout; the FSDB per-bit
|
|
21
|
+
MSB-first ordering (`vc[i] -> s[i]`) and the `fsdbXTag`/`fsdbTag64` layout
|
|
22
|
+
compatibility were cross-checked against its verified wrapper. The last two
|
|
23
|
+
were stated in the original 2026-08-31 commit, dropped on 2026-09-01, and
|
|
24
|
+
are restored.
|
|
25
|
+
- Design-level influence: `diff_waveforms` was written independently and reuses
|
|
26
|
+
no code. First-divergence localization was already on our development roadmap.
|
|
27
|
+
`diff_first_divergence` came earlier, and we referred to it when prioritising
|
|
28
|
+
the feature; that is now credited in `wave_mcp/diff.py` and the notice. It is
|
|
29
|
+
the only design-level influence we are aware of; the broader feature set and
|
|
30
|
+
tool organisation follow the capability set of established commercial waveform
|
|
31
|
+
debug tools.
|
|
32
|
+
- Wording such as "the only place" and "from scratch" is scoped to code, so the
|
|
33
|
+
code-level and design-level relationships are stated separately rather than
|
|
34
|
+
collapsed into one claim.
|
|
35
|
+
- **TraceWeave MIT license text vendored** at
|
|
36
|
+
`docs/licenses/TraceWeave-MIT.txt`, with its original copyright line intact and
|
|
37
|
+
linked from `docs/THIRD_PARTY.md`, so attribution travels with any
|
|
38
|
+
redistribution.
|
|
39
|
+
- **Attribution surfaced in both READMEs**, as a one-line note after the feature
|
|
40
|
+
list linking to the full notice, instead of living only in the FAQ.
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- **`LICENSE`, `docs/THIRD_PARTY.md`, `docs/PACKAGING_MATERIALS.md` and
|
|
45
|
+
`docs/licenses/` now install with the wheel** via `data-files`, so the
|
|
46
|
+
attribution and third-party notices travel with a plain `pip install`
|
|
47
|
+
instead of living only in the sdist or the offline bundle.
|
|
48
|
+
- **Complete redistribution materials for the optional components**: original
|
|
49
|
+
source archives, license texts and provenance records for the standalone
|
|
50
|
+
Python runtime (52 files), `vcd2fst` (27 files) and the viewer assets,
|
|
51
|
+
with hashes verified against upstream. See `docs/PACKAGING_MATERIALS.md`.
|
|
52
|
+
- **Font licenses that the viewer binaries actually embed**: `OFL-1.1` and
|
|
53
|
+
`Ubuntu-font-1.0` for the fonts shipped inside the `surver` binary. Earlier
|
|
54
|
+
releases recorded `epaint_default_fonts` as an unknown license; both texts
|
|
55
|
+
are now vendored and required by the packaging gate.
|
|
56
|
+
- **`deploy/redistribution_materials.py` packaging gate**: blocks a build when
|
|
57
|
+
required redistribution materials are missing, unresolved or hash-mismatched,
|
|
58
|
+
so a release cannot ship without them.
|
|
59
|
+
|
|
60
|
+
## [0.2.3] - 2026-09-05
|
|
61
|
+
|
|
62
|
+
### Fixed
|
|
63
|
+
|
|
64
|
+
- **Signals declared on the DUT top level reported `unresolved_path`.** Scope
|
|
65
|
+
resolution tried three levels: an exact netlist key, a leaf-name match, then
|
|
66
|
+
the FST `component` field. The last level was dead code, because that field is
|
|
67
|
+
empty for every waveform we produce, both Verilator's native FST and
|
|
68
|
+
VCD-derived ones, so it never resolved anything. Historical sessions never
|
|
69
|
+
noticed, since their netlist was elaborated from the testbench top and its
|
|
70
|
+
root key matched the FST root, which let level one absorb every lookup. A
|
|
71
|
+
DUT-rooted netlist breaks that: the root key is the DUT (`decode`) while the
|
|
72
|
+
FST root is the testbench (`top_tb.U_DECODE`), so levels one and two both miss
|
|
73
|
+
and the root falls through to the branch that never works. Level three now
|
|
74
|
+
also accepts `definition_name`, which the anchor pass derives from the
|
|
75
|
+
netlist, so the root resolves and its direct signals become traceable.
|
|
76
|
+
- **Cross-hierarchy tracing only worked in one direction.** `loads()` already
|
|
77
|
+
descended into sub-modules; `drivers()` did not, so the same wire returned a
|
|
78
|
+
connection from `signal_connectivity` and `undriven_signal` from
|
|
79
|
+
`signal_drivers`. Both directions now walk peers, filtered by port direction:
|
|
80
|
+
upstream takes same-level fan-in plus sub-module **output** ports, downstream
|
|
81
|
+
takes same-level loads plus sub-module **input** ports. Direction filtering is
|
|
82
|
+
what keeps a source like a top-level reset from being reported as driven by
|
|
83
|
+
the flops it feeds. Resolved results say which hop they came from.
|
|
84
|
+
- **Source paths from the netlist could not be opened.** `modules_in_file`
|
|
85
|
+
always returned 0 and `signal_drivers` handed back paths such as
|
|
86
|
+
`examples/sample/counter.sv` that resolve against nothing, because paths were
|
|
87
|
+
stored relative to the elaboration cwd but looked up against the cwd at query
|
|
88
|
+
time. Netlist builds now record the cwd they ran from and prefer absolute
|
|
89
|
+
paths; every remaining relative path is rewritten once when the netlist loads,
|
|
90
|
+
resolved against the build root, the netlist directory and its ancestors. One
|
|
91
|
+
normalisation point, because these paths reach callers through drivers, loads,
|
|
92
|
+
fan-in, trace results and declarations alike.
|
|
93
|
+
- **Filelists ignored environment variables.** `-F $PROJ_FE/rtl/foo.f` was taken
|
|
94
|
+
literally, so an entire file group silently dropped out of elaboration as
|
|
95
|
+
missing files. Tokens now pass through `os.path.expandvars`, and an undefined
|
|
96
|
+
variable is left untouched so it still fails as a missing file rather than
|
|
97
|
+
turning into a path that exists by accident.
|
|
98
|
+
- **A misspelled time unit silently moved the cursor.** `--cursor 1000nanoseconds`
|
|
99
|
+
was accepted and landed at an arbitrary time with no warning, because the
|
|
100
|
+
converter fell back to emitting the bare number when unit parsing failed,
|
|
101
|
+
which means something entirely different from converting it. Unknown units are
|
|
102
|
+
now rejected at the CLI and dropped from the generated command batch, and
|
|
103
|
+
remaining markers are renumbered so one bad entry cannot shift the rest onto
|
|
104
|
+
the wrong ids. Accepted units come from a single list in `timeutil`.
|
|
105
|
+
- **The viewer stayed blank in IDE-embedded browsers.** The page receives the
|
|
106
|
+
backend token in the URL query string, and some embedded browsers drop the
|
|
107
|
+
query on navigation, leaving the shell requesting a URL that 404s and a canvas
|
|
108
|
+
that never paints. The token is now served alongside the view state and the
|
|
109
|
+
page falls back to it, so the bare URL works. Each server still serves one
|
|
110
|
+
view on localhost only.
|
|
111
|
+
- **Views intermittently failed to start.** Opening a view takes two ports, one
|
|
112
|
+
for the shell and one for surver, and both were picked by binding a socket,
|
|
113
|
+
reading the port, then closing it and binding again later. In between, the
|
|
114
|
+
port belongs to nobody and any other process on the host can take it, so the
|
|
115
|
+
second bind fails with the port already in use. It only reproduced under
|
|
116
|
+
load, such as a full regression run starting many viewers in quick
|
|
117
|
+
succession, where it surfaced as a random "surver failed to start". The shell
|
|
118
|
+
server now receives an already-listening socket, so picking and binding are
|
|
119
|
+
one operation. surver is a separate binary that only gets a port number, so
|
|
120
|
+
it cannot inherit a socket and instead retires the port and retries on
|
|
121
|
+
another one when the child fails to come up.
|
|
122
|
+
|
|
123
|
+
### Added
|
|
124
|
+
|
|
125
|
+
- `tests/unit/test_dut_root.py`, pinning the DUT-rooted netlist case above on a
|
|
126
|
+
synthetic waveform written by pylibfst, so it needs no simulator and cannot be
|
|
127
|
+
masked by a stale checked-in file. It asserts the conditions that make the bug
|
|
128
|
+
reachable rather than only the outcome, so a later change cannot quietly turn
|
|
129
|
+
it into a test of the leaf-name match. Reverting the fix fails 5 of its 8
|
|
130
|
+
assertions.
|
|
131
|
+
|
|
132
|
+
## [0.2.2] - 2026-09-05
|
|
133
|
+
|
|
134
|
+
### Added
|
|
135
|
+
|
|
136
|
+
- **`WAVE_MCP_SESSION_ROOT` confines where session directories land.** `out_dir`
|
|
137
|
+
is chosen by the calling model, so a drifted prompt could scatter sessions
|
|
138
|
+
across `/tmp`, the cwd, or a shared regression directory, where two users with
|
|
139
|
+
different filelists collide on one directory and silently inherit each other's
|
|
140
|
+
netlist. Set this variable and every `out_dir` resolves inside it: a bare name
|
|
141
|
+
or relative path lands in the root, a path already inside it is kept, and one
|
|
142
|
+
pointing elsewhere is remapped in by basename. Unset, behaviour is unchanged.
|
|
143
|
+
The reply's `session_path` is always the real location.
|
|
144
|
+
- **Environment variables documented in one table.** Both READMEs now carry the
|
|
145
|
+
full set (session root, Verdi/FSDB, vcd2fst, viewer, cache) and state that
|
|
146
|
+
these belong in the `env` block of the MCP client config, since an
|
|
147
|
+
agent-spawned server does not inherit an interactive shell's exports.
|
|
148
|
+
`VERDI_HOME` is now explicit about pointing at the install root rather than a
|
|
149
|
+
subdirectory.
|
|
150
|
+
|
|
151
|
+
### Fixed
|
|
152
|
+
|
|
153
|
+
- **Viewer backends outlived the process that started them.** `SurverManager`
|
|
154
|
+
relied solely on an `atexit` hook, which Python skips on `SIGTERM`, so
|
|
155
|
+
killing a `wave-view` CLI or an MCP server left one `surver` per open view
|
|
156
|
+
running indefinitely, holding memory and a listening port. Found in the field
|
|
157
|
+
with four backends still alive 23 hours after their servers were abandoned.
|
|
158
|
+
Both entry points now install `SIGTERM` / `SIGINT` / `SIGHUP` handlers that
|
|
159
|
+
close views explicitly, and `surver` children additionally set
|
|
160
|
+
`PR_SET_PDEATHSIG` so the kernel reaps them even when the parent is
|
|
161
|
+
`SIGKILL`ed or crashes, which no in-process handler can cover. The
|
|
162
|
+
server-side cleanup inspects `sys.modules` instead of importing the viewer,
|
|
163
|
+
so installs without the optional assets are unaffected.
|
|
164
|
+
|
|
165
|
+
### Changed
|
|
166
|
+
|
|
167
|
+
- **FSDB converter attribution made accurate.** `fsdb2fst` is the newest part of
|
|
168
|
+
wave-mcp and the place where prior public work was consulted at the code level
|
|
169
|
+
rather than starting from scratch: `ParseScaleFs` (FSDB scale string to
|
|
170
|
+
femtoseconds per tick) keeps the error contract and unit table of the public
|
|
171
|
+
TraceWeave implementation, and the offline `ffrAPI` stub mirrors the subset of
|
|
172
|
+
ffrAPI it exercises. Comments naming the project came in with the converter on
|
|
173
|
+
2026-08-31 and were dropped on 2026-09-01 during a broader cleanup of vendor
|
|
174
|
+
references, which left the file described as `original code`. That
|
|
175
|
+
description was inaccurate. `docs/THIRD_PARTY.md` and the headers of both
|
|
176
|
+
source files now carry the project name, author, MIT license, link, and our
|
|
177
|
+
thanks. (The scope stated here was still narrower than what had actually been
|
|
178
|
+
consulted; see [Unreleased](#unreleased) for the complete account.)
|
|
179
|
+
|
|
180
|
+
## [0.2.1] - 2026-09-04
|
|
181
|
+
|
|
182
|
+
### Added
|
|
183
|
+
|
|
184
|
+
- **`WAVE_MCP_SESSION_ROOT` pins where sessions land.** `out_dir` is chosen by
|
|
185
|
+
the calling model, so a drifted prompt could scatter sessions across `/tmp`,
|
|
186
|
+
the cwd, or a shared regression directory, where two users with different
|
|
187
|
+
filelists can collide on one directory and silently inherit each other's
|
|
188
|
+
netlist. Set this variable and every `out_dir` resolves inside it: a bare name
|
|
189
|
+
or relative path lands in the root, a path already inside it is kept, and a
|
|
190
|
+
path pointing elsewhere is remapped in by basename. Unset, behaviour is
|
|
191
|
+
unchanged. The reply's `session_path` is always the real location.
|
|
192
|
+
- **Environment variables are documented in one place.** Both READMEs now carry
|
|
193
|
+
the full table (session root, Verdi/FSDB, vcd2fst, viewer, cache) and state
|
|
194
|
+
that these belong in the `env` block of the MCP client config, since an
|
|
195
|
+
agent-spawned server does not inherit an interactive shell's exports.
|
|
196
|
+
|
|
197
|
+
### Fixed
|
|
198
|
+
|
|
199
|
+
- **Viewer backends outlived the process that started them.** `SurverManager`
|
|
200
|
+
relied solely on an `atexit` hook, which Python skips on `SIGTERM`, so
|
|
201
|
+
`kill`-ing a `wave-view` CLI or an MCP server left one `surver` per open view
|
|
202
|
+
running indefinitely, holding memory and a listening port. Found in the field
|
|
203
|
+
with four backends still alive 23 hours after their servers were abandoned.
|
|
204
|
+
Both entry points now install `SIGTERM` / `SIGINT` / `SIGHUP` handlers that
|
|
205
|
+
close views explicitly, and `surver` children additionally set
|
|
206
|
+
`PR_SET_PDEATHSIG` so the kernel reaps them even when the parent is
|
|
207
|
+
`SIGKILL`ed or crashes, which no in-process handler can cover. The server-side
|
|
208
|
+
cleanup inspects `sys.modules` instead of importing the viewer, so installs
|
|
209
|
+
without the optional assets are unaffected.
|
|
210
|
+
- **Air-gapped launcher could not find its own interpreter.** `install.sh` took
|
|
211
|
+
`--prefix` verbatim, so a relative value baked a relative `RUNTIME` into the
|
|
212
|
+
generated `bin/wave-mcp`. An MCP client spawns that launcher with the user's
|
|
213
|
+
project directory as cwd, not the install directory, so the interpreter path
|
|
214
|
+
resolved to nothing and the client reported only a bare `-32000`. The prefix
|
|
215
|
+
is now absolutized (and probed for write permission) before anything is
|
|
216
|
+
installed, the launcher anchors a relative `RUNTIME` on its bundle, and it
|
|
217
|
+
prints the missing path, the bundle, and the cwd instead of dying silently.
|
|
218
|
+
Reported from an on-site air-gapped deployment.
|
|
219
|
+
- **Install-time check now covers the launcher.** The sanity check ran the venv
|
|
220
|
+
interpreter directly, which bypassed the generated launcher entirely, so any
|
|
221
|
+
cwd-dependent path in it survived install and only surfaced in the client. It
|
|
222
|
+
now also executes `bin/wave-mcp` from an unrelated cwd, reproducing how a
|
|
223
|
+
client starts it.
|
|
224
|
+
- **`WAVE_MCP_VIEWER_ASSETS` silently ignored when relative.** A relative value
|
|
225
|
+
resolved against whatever cwd the client happened to use and then degraded to
|
|
226
|
+
"viewer unavailable" with a hint telling the user to set the variable they had
|
|
227
|
+
already set. Relative values now resolve against `$HOME`, and the hint names
|
|
228
|
+
the real cause (path missing, or `surver` / `wasm/index.html` absent).
|
|
229
|
+
- **Build scripts now absolutize `--out`.** `build_offline_bundle.sh` used
|
|
230
|
+
`dirname "$OUT"` for the tarball step, and the two Docker-based builders pass
|
|
231
|
+
`$OUT` as a `-v` mount source, where a relative path is rejected outright.
|
|
232
|
+
- **`open_session` description no longer mentions a sim log**, which it stopped
|
|
233
|
+
loading; the tool description an agent sees now matches what it does.
|
|
234
|
+
|
|
235
|
+
## [0.2.0] - 2026-09-02
|
|
236
|
+
|
|
237
|
+
Three new capabilities on top of the 0.1.x tool set: a browser wave viewer the
|
|
238
|
+
agent can drive, pass/fail waveform diffing, and an FSDB input path. Tool count
|
|
239
|
+
goes from 27 to 34.
|
|
240
|
+
|
|
241
|
+
### Added
|
|
242
|
+
|
|
243
|
+
- **Browser wave viewer.** `open_wave_view` renders a session in a real
|
|
244
|
+
waveform GUI (Surfer compiled to WASM, streamed by surver), so an agent can
|
|
245
|
+
show you what it found instead of describing it. `update_wave_view` mutates a
|
|
246
|
+
live view (signals, groups, colors, radix, cursor, markers, viewport,
|
|
247
|
+
annotations) and `get_view_state` reads back what the user has since changed
|
|
248
|
+
by hand, which makes the loop two-way. Install with the `viewer` extra
|
|
249
|
+
(`pip install "wave-mcp[viewer]"`). Guides:
|
|
250
|
+
[docs/WAVE_VIEWER.md](docs/WAVE_VIEWER.md),
|
|
251
|
+
[docs/VIEWER_SCREENSHOTS.md](docs/VIEWER_SCREENSHOTS.md).
|
|
252
|
+
- **View lifecycle management.** `list_wave_views` reports the open views
|
|
253
|
+
(id, url, title, waveform paths, revision, backend liveness) and
|
|
254
|
+
`close_wave_view` closes one or all of them, releasing the per-view HTTP
|
|
255
|
+
server. The streaming backend is shared per waveform file set and refcounted,
|
|
256
|
+
so closing one view never cuts off another still reading the same waveform.
|
|
257
|
+
A cap of 8 concurrent views (`WAVE_MCP_MAX_VIEWS`, 0 disables) evicts the
|
|
258
|
+
oldest view so long batch runs cannot pile up views and processes.
|
|
259
|
+
- **Pinnable viewer ports.** Views use random high ports by default; setting
|
|
260
|
+
`WAVE_MCP_VIEWER_PORT_BASE` confines them to a 64-port window so a single
|
|
261
|
+
`ssh -L` rule keeps working across views, and several people on one host can
|
|
262
|
+
each take their own window. Allocation falls back to an ephemeral port when
|
|
263
|
+
the window is full.
|
|
264
|
+
- **`wave-view` CLI** for opening a waveform in the viewer without an MCP
|
|
265
|
+
client, including `--signals` and remote-friendly port printing.
|
|
266
|
+
- **`diff_waveforms`** locates the first divergence between two runs of the
|
|
267
|
+
same design (pass vs fail), reporting per-signal first-difference times and
|
|
268
|
+
coverage of the compared signal set.
|
|
269
|
+
- **FSDB input.** `prepare_session` now accepts `.fsdb` directly and converts
|
|
270
|
+
it via the bundled `fsdb2fst`, with `fsdb_scopes` / `fsdb_signals_file` for
|
|
271
|
+
slicing large dumps. `convert_fsdb_to_fst` exposes the converter as its own
|
|
272
|
+
tool, including `info_only` for a fast summary of a huge file before
|
|
273
|
+
committing to a full conversion. See [docs/FSDB_GUIDE.md](docs/FSDB_GUIDE.md).
|
|
274
|
+
- **Conversion cache.** Both VCD and FSDB conversions now write the `.fst`
|
|
275
|
+
next to the source waveform and reuse it across sessions. The cache key
|
|
276
|
+
covers the source identity plus the slicing options, so changing the scope
|
|
277
|
+
selection produces a fresh conversion instead of silently reusing a partial
|
|
278
|
+
waveform.
|
|
279
|
+
- **Xcelium direct FST output** documented end to end, with the `fstdumper`
|
|
280
|
+
VPI patches required to build it:
|
|
281
|
+
[docs/XCELIUM_FST_GUIDE.md](docs/XCELIUM_FST_GUIDE.md).
|
|
282
|
+
- **Simulator compatibility matrix** covering the four ways to get a waveform
|
|
283
|
+
in (FST direct, VCD auto-convert, FSDB conversion, Xcelium direct):
|
|
284
|
+
[docs/SIMULATOR_COMPATIBILITY.md](docs/SIMULATOR_COMPATIBILITY.md).
|
|
285
|
+
- **Viewer demos.** Four runnable debug scenarios (X propagation, FSM
|
|
286
|
+
deadlock, CDC pulse loss, pass/fail CRC divergence) under
|
|
287
|
+
[examples/viewer_demos](examples/viewer_demos), plus a screenshot capture
|
|
288
|
+
script.
|
|
289
|
+
- **Offline deployment**: one-command Docker pipeline for the air-gapped
|
|
290
|
+
bundle matrix (glibc 2.17 / 2.28), viewer assets packaging, and a vendored
|
|
291
|
+
license directory with a generated crate license report.
|
|
292
|
+
|
|
293
|
+
### Fixed
|
|
294
|
+
|
|
295
|
+
- Viewer served its own demo landing page for `/index.html`, shadowing the
|
|
296
|
+
Surfer WASM entry point that the shell loads in an iframe. The viewer would
|
|
297
|
+
come up with an empty waveform pane. Static resolution now always resolves
|
|
298
|
+
the WASM entry from the assets directory.
|
|
299
|
+
- `update_wave_view` emitted marker commands with the arguments transposed, so
|
|
300
|
+
markers landed at the wrong time.
|
|
301
|
+
- Closing a viewer HTTP server called `shutdown()` without `server_close()`,
|
|
302
|
+
leaking the listening socket and its file descriptor.
|
|
303
|
+
- Viewer service worker returned `undefined` on a failed range request instead
|
|
304
|
+
of an error response, stalling waveform streaming.
|
|
305
|
+
- Slang lint diagnostics were misclassified as errors, and interface scope
|
|
306
|
+
names failed to resolve during elaboration.
|
|
307
|
+
- FST source: definition-name handling for RTL module types, plus scope
|
|
308
|
+
filtering fixes for interface and generate blocks.
|
|
309
|
+
|
|
310
|
+
### Changed
|
|
311
|
+
|
|
312
|
+
- Session paths in the shipped demos are stored relative to the session
|
|
313
|
+
directory, so a cloned repository runs the demos without rewriting paths.
|
|
314
|
+
- Documentation drops internal test logs, decision history and competitor
|
|
315
|
+
comparisons in favour of support status and known limitations.
|
|
316
|
+
- Python interpreter detection in the deploy scripts now gates on the CPython
|
|
317
|
+
version rather than guessing from the binary name.
|
|
318
|
+
|
|
319
|
+
## [0.1.1] - 2026-08-26
|
|
320
|
+
|
|
321
|
+
### Added
|
|
322
|
+
|
|
323
|
+
- `wave-mcp query` CLI subcommand exposing all 27 tools from the shell.
|
|
324
|
+
- Validation overview charts in the README.
|
|
325
|
+
|
|
326
|
+
## [0.1.0] - 2026-08-20
|
|
327
|
+
|
|
328
|
+
Initial public release: 27 MCP tools for RTL waveform debug over FST plus
|
|
329
|
+
SystemVerilog static analysis (pyslang elaboration), covering hierarchy
|
|
330
|
+
browsing, signal values, driver/load tracing, X-cause tracing and file-level
|
|
331
|
+
queries.
|
|
332
|
+
|
|
333
|
+
[0.2.2]: https://github.com/Tencent/wave-mcp/releases/tag/v0.2.2
|
|
334
|
+
[0.2.1]: https://github.com/Tencent/wave-mcp/releases/tag/v0.2.1
|
|
335
|
+
[0.2.0]: https://github.com/Tencent/wave-mcp/releases/tag/v0.2.0
|
|
336
|
+
[0.1.1]: https://github.com/Tencent/wave-mcp/releases/tag/v0.1.1
|
|
337
|
+
[0.1.0]: https://github.com/Tencent/wave-mcp/releases/tag/v0.1.0
|
wave_mcp-0.2.4/LICENSE
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Tencent is pleased to support the open source community by making wave-mcp available.
|
|
2
|
+
|
|
3
|
+
Copyright (C) 2026 Tencent. All rights reserved.
|
|
4
|
+
|
|
5
|
+
wave-mcp is licensed under the MIT.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Terms of the MIT:
|
|
9
|
+
--------------------------------------------------------------------
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
11
|
+
a copy of this software and associated documentation files (the
|
|
12
|
+
"Software"), to deal in the Software without restriction, including
|
|
13
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
14
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
15
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
16
|
+
the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be
|
|
19
|
+
included in all copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
22
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
23
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
24
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
25
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
26
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
27
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
include README.md
|
|
2
|
+
include README.en.md
|
|
3
|
+
include CHANGELOG.md
|
|
4
|
+
include LICENSE
|
|
5
|
+
include docs/THIRD_PARTY.md
|
|
6
|
+
include docs/PACKAGING_MATERIALS.md
|
|
7
|
+
recursive-include wave_mcp/viewer/web *.html *.js
|
|
8
|
+
recursive-include docs/licenses *
|
|
9
|
+
recursive-exclude tests *
|
|
10
|
+
recursive-exclude dev-docs *
|
|
11
|
+
global-exclude __pycache__ *.py[cod]
|