| name | xwave |
| description | Use when an AI agent needs structured JSON access to FSDB waveform facts through xwave, including sessions, scope discovery, values, signal lists, APB/AXI transactions, generic events, condition checks, expression/window verification, signal inspection, anomaly detection, handshake inspection, or protocol debug facts.
|
xwave AI JSON Interface
This skill is for AI agents using xwave ai ... as a structured waveform fact API. Prefer the AI JSON entry point over the human CLI whenever you need machine-readable output, deterministic errors, or multi-step debug evidence.
Human-oriented legacy CLI details were moved to references/cli-reference.md. Load that file only when the user explicitly asks about non-AI command syntax.
Entry Point
Use one of these forms:
tools/xwave-env ai query request.json
tools/xwave-env ai query -
tools/xwave-env ai query --json '{"api_version":"xwave.ai.v1","action":"value.at","target":{"fsdb":"waves.fsdb","auto_open":true},"args":{"signal":"top.clk","time":"10ns"}}'
tools/xwave-env ai query --json '{"api_version":"xwave.ai.v1","action":"cursor.set","target":{"session_id":"case_a"},"args":{"name":"deadlock","time":"120340ns","note":"stall start"}}'
tools/xwave-env ai query --json '{"api_version":"xwave.ai.v1","action":"value.at","target":{"session_id":"case_a"},"args":{"signal":"top.ready","at":"@deadlock-20ns","format":"hex"}}'
tools/xwave-env ai schema
tools/xwave-env ai actions
Output Verbosity
Important: xwave ai query defaults to compact output. Compact output deliberately omits tool, session, empty warnings, empty suggested_next_actions, and meta.elapsed_ms. Do not assume those fields exist unless you request them.
Use compact for normal AI workflows:
{"output":{"verbosity":"compact"}}
Use full when maintaining older scripts or discovering exact response fields:
{"output":{"verbosity":"full"}}
Use debug when diagnosing session/daemon/socket/FSDB fingerprint issues:
{"output":{"verbosity":"debug"}}
Errors still include structured error.code/message, and non-empty recovery hints remain present in compact output.
AI value objects are intentionally minimal everywhere: {"value":"...", "known":true|false}. Do not expect text, bits, hex, unsigned, signed, or unknown_reason; choose the string representation with request format.
For scripted extraction, pipe JSON output into python3 instead of parsing human text. This is the recommended way for AI agents to pull specific fields or compute custom statistics:
tools/xwave-env ai query --json '{"api_version":"xwave.ai.v1","action":"session.list"}' \
| python3 -c 'import json,sys; d=json.load(sys.stdin); print(d["ok"], d.get("summary", {}))'
For larger summaries, keep the xwave query bounded and do the aggregation in Python:
tools/xwave-env ai query --json '{"api_version":"xwave.ai.v1","action":"event.export","target":{"session_id":"case_a"},"args":{"name":"if0","expr":"valid && !ready","time_range":{"begin":"0ns","end":"100us"}},"limits":{"max_rows":1000}}' \
| python3 -c 'import json,sys; d=json.load(sys.stdin); rows=d.get("data",{}).get("events",[]); print(len(rows))'
For event counts or grouped counts, prefer built-in aggregation over exporting all rows:
tools/xwave-env ai query --json '{"api_version":"xwave.ai.v1","action":"event.export","target":{"session_id":"case_a"},"args":{"name":"if0","expr":"valid && ready","time_range":{"begin":"0ns","end":"100us"},"aggregate":{"count":true,"group_by":["qid"],"events":false}}}'
Request envelope:
{
"api_version": "xwave.ai.v1",
"request_id": "optional-id",
"action": "value.at",
"target": {
"fsdb": "/path/to/waves.fsdb",
"auto_open": true
},
"args": {},
"limits": {
"max_rows": 1000,
"max_events": 1000,
"max_samples": 1000000
},
"output": {
"verbosity": "compact"
}
}
Response envelope always contains:
compact: ok/action plus non-empty summary/data/findings/error/suggested_next_actions/meta.truncated
full/debug: ok/action/session/summary/data/findings/suggested_next_actions/warnings/error/meta
Only ok/action/error and action-specific key data should be treated as always relevant. Field presence depends on output.verbosity; compact output will not include session/meta/tool scaffolding. Field names inside summary, data, and findings are action-specific and may differ by action. Do not guess detailed keys such as latency subfields from memory. For a field dictionary and extraction guidance, see references/ai-response-dictionary.md. For exact fields on a specific build and FSDB, run tools/xwave-env ai schema when available, or issue a small bounded query and inspect the returned JSON before writing extraction code.
AI usage rules:
- Start with
session.open for repeated work, then use target.session_id as a string.
- For one-shot queries, use
target.fsdb + auto_open:true.
- Always inspect
ok and error.code; do not parse human text.
- Prefer
python3 -c 'import json,sys; ...' pipelines for extracting fields or computing statistics from xwave ai query output.
- Use
cursor.set after finding an important event time, then use @name, @name-20ns, @name+5ns, @name-10cycle(top.clk), or active cursor forms such as @-10ns in later time fields.
- Time fields accept absolute TimeSpec strings directly. Cycle offsets use real FSDB clock edges:
cycle(clk) means posedge, and posedge(clk) / negedge(clk) choose the edge explicitly.
- For range actions, prefer
around/before/after when investigating context around a cursor, for example {"around":"@deadlock","before":"100cycle(top.clk)","after":"20cycle(top.clk)"}.
- Treat value
known:false, status:"unknown", and pass:null as inconclusive waveform facts, not failures.
- Use
scope.list after SIGNAL_NOT_FOUND.
- Use
limits.max_rows/max_events/max_samples for broad scans.
- Load APB/AXI/Event configs before protocol or event actions.
- Runtime state and persisted configs live under
~/.xwave/: registry.json plus sessions/<hashed-session-dir>/session.json, endpoint.json, socket, debug.log, lists.json, apb.json, axi.json, events.json, and cursors.json.
- Transport defaults to UDS. For LSF or multi-host clients, open with
args.transport:"tcp" and a reachable bind_host; keep port:0 unless the user explicitly needs a fixed port. The daemon writes the actual auto-assigned TCP port to endpoint.json, so later AI requests still only need target.session_id.
Session Actions
session.open
Open a named session for an FSDB. The session name is required, is the real session id, and is reused by every later target.session_id field. Names may be up to 256 characters and may contain letters, digits, _, ., and -; duplicate names fail. Transport defaults to uds. Use args.transport:"tcp" for TCP; TCP ports are automatically assigned when port is omitted or 0, and the actual endpoint is stored in ~/.xwave/sessions/<hashed-session-dir>/endpoint.json.
{"api_version":"xwave.ai.v1","action":"session.open","target":{"fsdb":"/path/to/waves.fsdb"},"args":{"name":"case_a"}}
{"api_version":"xwave.ai.v1","action":"session.open","target":{"fsdb":"/path/to/waves.fsdb"},"args":{"name":"case_tcp","transport":"tcp","bind_host":"127.0.0.1","port":0}}
session.list
List known sessions. Use before reusing an existing session.
{"api_version":"xwave.ai.v1","action":"session.list"}
session.doctor
Check daemon, transport endpoint, socket/PID, FSDB fingerprint, and health for a session.
{"api_version":"xwave.ai.v1","action":"session.doctor","target":{"session_id":"case_a"}}
session.gc
Clean stale or idle sessions.
{"api_version":"xwave.ai.v1","action":"session.gc"}
session.kill
Stop one session or all sessions.
{"api_version":"xwave.ai.v1","action":"session.kill","args":{"id":"all"}}
Cursor Actions
Cursor actions store named session-local times. Use them when a debug flow has a key event time and later queries need context before or after that point. All later time fields can use @name, @name-20ns, @name+5ns, @name-10cycle(top.clk), @-10ns, or @+5ns.
cursor.set
Create or replace a cursor. The response includes data.resolved_time, so use that as the canonical time for evidence.
{"api_version":"xwave.ai.v1","action":"cursor.set","target":{"session_id":"case_a"},"args":{"name":"deadlock","time":"120340ns","note":"rready stall starts"}}
cursor.get
Fetch one cursor.
{"api_version":"xwave.ai.v1","action":"cursor.get","target":{"session_id":"case_a"},"args":{"name":"deadlock"}}
cursor.list
List cursors and the active cursor.
{"api_version":"xwave.ai.v1","action":"cursor.list","target":{"session_id":"case_a"}}
cursor.use
Set the active cursor, enabling short forms such as @-20ns.
{"api_version":"xwave.ai.v1","action":"cursor.use","target":{"session_id":"case_a"},"args":{"name":"deadlock"}}
cursor.delete
Delete a cursor.
{"api_version":"xwave.ai.v1","action":"cursor.delete","target":{"session_id":"case_a"},"args":{"name":"deadlock"}}
Scope And Value Actions
scope.list
List available FSDB signals under a scope. Use this to recover from missing or ambiguous paths.
{"api_version":"xwave.ai.v1","action":"scope.list","target":{"session_id":"case_a"},"args":{"path":"top.u_dut","recursive":true},"limits":{"max_rows":200}}
value.at
Read one signal at one time. Use for point evidence.
{"api_version":"xwave.ai.v1","action":"value.at","target":{"session_id":"case_a"},"args":{"signal":"top.u_dut.ready","at":"@deadlock-20ns","format":"hex"}}
value.batch_at
Read many signals at the same time. Prefer this over many value.at calls.
{"api_version":"xwave.ai.v1","action":"value.batch_at","target":{"session_id":"case_a"},"args":{"at":"@deadlock","signals":["top.u_dut.valid","top.u_dut.ready","top.u_dut.fifo_full"],"format":"hex"}}
Signal List Actions
list.create
Create a named signal list.
{"api_version":"xwave.ai.v1","action":"list.create","target":{"session_id":"case_a"},"args":{"name":"if0"}}
list.add
Add a signal after probing that it exists.
{"api_version":"xwave.ai.v1","action":"list.add","target":{"session_id":"case_a"},"args":{"name":"if0","signal":"top.u_dut.valid"}}
list.delete
Remove by signal path or list index.
{"api_version":"xwave.ai.v1","action":"list.delete","target":{"session_id":"case_a"},"args":{"name":"if0","index":"2"}}
list.show
Show list members.
{"api_version":"xwave.ai.v1","action":"list.show","target":{"session_id":"case_a"},"args":{"name":"if0"}}
list.value_at
Read all list signals at one time.
{"api_version":"xwave.ai.v1","action":"list.value_at","target":{"session_id":"case_a"},"args":{"name":"if0","time":"42us","format":"binary"}}
list.validate
Check whether every signal in a list exists in the current FSDB.
{"api_version":"xwave.ai.v1","action":"list.validate","target":{"session_id":"case_a"},"args":{"name":"if0"}}
list.diff
Find the earliest time where list values are not all equal.
{"api_version":"xwave.ai.v1","action":"list.diff","target":{"session_id":"case_a"},"args":{"name":"if0","begin":"0ns","end":"100us"}}
APB Actions
apb.config.load
Load and persist an APB config. config_path points to JSON, or config may inline the object.
{"api_version":"xwave.ai.v1","action":"apb.config.load","target":{"session_id":"case_a"},"args":{"name":"apb0","config_path":"apb.json"}}
apb.config.list
Return the saved APB config.
{"api_version":"xwave.ai.v1","action":"apb.config.list","target":{"session_id":"case_a"},"args":{"name":"apb0"}}
apb.query
Query APB reads or writes. Use direction:"wr" or direction:"rd", with optional address, num, or last.
{"api_version":"xwave.ai.v1","action":"apb.query","target":{"session_id":"case_a"},"args":{"name":"apb0","direction":"wr","address":"0x100","num":1}}
apb.cursor
Iterate APB transactions with op:"begin", next, pre, or last.
{"api_version":"xwave.ai.v1","action":"apb.cursor","target":{"session_id":"case_a"},"args":{"name":"apb0","op":"begin","direction":"all"}}
apb.transfer_window
Return APB transactions whose transfer time is inside a time range.
{"api_version":"xwave.ai.v1","action":"apb.transfer_window","target":{"session_id":"case_a"},"args":{"name":"apb0","time_range":{"begin":"40us","end":"45us"},"direction":"all","limit":50}}
AXI Actions
axi.config.load
Load and persist an AXI config. Use a full five-channel config with clk, rst_n, and optional edge.
{"api_version":"xwave.ai.v1","action":"axi.config.load","target":{"session_id":"case_a"},"args":{"name":"axi0","config_path":"axi.json"}}
axi.config.list
Return the saved AXI config.
{"api_version":"xwave.ai.v1","action":"axi.config.list","target":{"session_id":"case_a"},"args":{"name":"axi0"}}
axi.query
Query AXI reads or writes. Use optional address, id, num, or last.
{"api_version":"xwave.ai.v1","action":"axi.query","target":{"session_id":"case_a"},"args":{"name":"axi0","direction":"rd","id":"0x3","num":1}}
axi.cursor
Iterate AXI transactions with op:"begin", next, pre, or last.
{"api_version":"xwave.ai.v1","action":"axi.cursor","target":{"session_id":"case_a"},"args":{"name":"axi0","op":"next","direction":"rd"}}
axi.analysis
Return AXI latency or outstanding statistics. Use analysis:"latency" or analysis:"osd" and optional direction or id.
{"api_version":"xwave.ai.v1","action":"axi.analysis","target":{"session_id":"case_a"},"args":{"name":"axi0","analysis":"latency","direction":"all"}}
axi.channel_stall
Inspect one AXI channel valid/ready stall behavior. Channels: aw, w, b, ar, r.
{"api_version":"xwave.ai.v1","action":"axi.channel_stall","target":{"session_id":"case_a"},"args":{"name":"axi0","channel":"r","time_range":{"begin":"40us","end":"45us"},"rules":{"max_wait_cycles":16}}}
axi.outstanding_timeline
Return outstanding samples over a window. Use for buildup/root-cause evidence.
{"api_version":"xwave.ai.v1","action":"axi.outstanding_timeline","target":{"session_id":"case_a"},"args":{"name":"axi0","time_range":{"begin":"40us","end":"45us"},"direction":"all","limit":100}}
axi.request_response_pair
Return AXI transactions whose request or response time is inside a window.
{"api_version":"xwave.ai.v1","action":"axi.request_response_pair","target":{"session_id":"case_a"},"args":{"name":"axi0","time_range":{"begin":"40us","end":"45us"},"direction":"rd","limit":20}}
axi.latency_outlier
Return transactions with largest request-response latency.
{"api_version":"xwave.ai.v1","action":"axi.latency_outlier","target":{"session_id":"case_a"},"args":{"name":"axi0","time_range":{"begin":"0ns","end":"100us"},"direction":"all","top_n":5,"limit":500}}
Event Actions
event.config.load
Load and persist a generic event config bound to the current FSDB.
{"api_version":"xwave.ai.v1","action":"event.config.load","target":{"session_id":"case_a"},"args":{"name":"if0","config_path":"if0.event.json"}}
event.config.list
List event configs or return one config.
{"api_version":"xwave.ai.v1","action":"event.config.list","target":{"session_id":"case_a"},"args":{"name":"if0"}}
event.find
Find the first clock-sampled event matching an expression.
{"api_version":"xwave.ai.v1","action":"event.find","target":{"session_id":"case_a"},"args":{"name":"if0","expr":"valid && !ready","time_range":{"begin":"40us","end":"45us"}}}
With protocol context:
{"api_version":"xwave.ai.v1","action":"event.find","target":{"session_id":"case_a"},"args":{"name":"if0","expr":"valid && !ready","time_range":{"begin":"40us","end":"45us"},"context":{"window":"200ns","axi":"axi0","apb":"apb0"}}}
event.export
Export matching events. Always set a limit unless you intentionally need a large scan.
{"api_version":"xwave.ai.v1","action":"event.export","target":{"session_id":"case_a"},"args":{"name":"if0","expr":"valid && !ready","time_range":{"begin":"40us","end":"45us"},"limit":100}}
Use aggregate when you need counts instead of full event rows:
{"api_version":"xwave.ai.v1","action":"event.export","target":{"session_id":"case_a"},"args":{"name":"if0","expr":"valid && ready","time_range":{"begin":"0ns","end":"100us"},"aggregate":{"count":true,"group_by":["qid","val"],"events":false}}}
Important: group_by names are not magic built-ins. Every group key must already be defined by the event config as either a signals alias or a fields entry. If qid is a standalone FSDB signal, define it under signals:
{
"clk": "xring_tb_top.clk",
"rst_n": "xring_tb_top.rst_n",
"signals": {
"valid": "xring_tb_top.credit_init_valid",
"ready": "xring_tb_top.credit_init_ready",
"qid": "xring_tb_top.credit_init_qid"
}
}
If qid is a bit slice inside a payload, define the payload signal and expose qid under fields:
{
"clk": "xring_tb_top.clk",
"rst_n": "xring_tb_top.rst_n",
"signals": {
"valid": "xring_tb_top.credit_init_valid",
"ready": "xring_tb_top.credit_init_ready",
"payload": "xring_tb_top.credit_init_payload"
},
"fields": {
"qid": {"signal": "payload", "left": 7, "right": 4},
"val": {"signal": "payload", "left": 2, "right": 0}
}
}
After that, aggregate.group_by:["qid","val"] groups by those configured values. If a group key is missing, unreadable, or contains x/z, it is grouped as unknown.
Wave Fact Verification Actions
verify.conditions
Check point-time conditions. Use this to verify hypotheses generated from RTL or protocol reasoning.
{"api_version":"xwave.ai.v1","action":"verify.conditions","target":{"session_id":"case_a"},"args":{"time":"42us","conditions":[{"signal":"top.u_dut.fifo_full","op":"==","value":"1"},{"signal":"top.u_dut.state","op":"!=","value":"0"}]}}
expr.eval_at
Evaluate a Boolean expression at one time using aliases.
{"api_version":"xwave.ai.v1","action":"expr.eval_at","target":{"session_id":"case_a"},"args":{"time":"42us","signals":{"valid":"top.u_dut.valid","ready":"top.u_dut.ready"},"expr":"valid && !ready"}}
window.verify
Verify expressions sampled on clock edges over a window. mode may be always, never, or eventually.
{"api_version":"xwave.ai.v1","action":"window.verify","target":{"session_id":"case_a"},"args":{"clock":"top.clk","sampling":"posedge","time_range":{"begin":"42us","end":"44us"},"conditions":[{"expr":"valid && !ready","signals":{"valid":"top.u_dut.valid","ready":"top.u_dut.ready"},"mode":"always"}]}}
signal.changes
Return value changes for a signal in a range.
{"api_version":"xwave.ai.v1","action":"signal.changes","target":{"session_id":"case_a"},"args":{"signal":"top.u_dut.fifo_full","time_range":{"begin":"40us","end":"45us"},"limit":20,"format":"binary"}}
signal.stability
Check whether a signal remains stable in a range.
{"api_version":"xwave.ai.v1","action":"signal.stability","target":{"session_id":"case_a"},"args":{"signal":"top.u_dut.active_count","time_range":{"begin":"42us","end":"44us"}}}
signal.trend
Sample a numeric signal on clock edges and summarize monotonicity, min, max, and stable state.
{"api_version":"xwave.ai.v1","action":"signal.trend","target":{"session_id":"case_a"},"args":{"signal":"top.u_dut.active_count","clock":"top.clk","sampling":"posedge","time_range":{"begin":"40us","end":"45us"},"max_samples":10000}}
signal.statistics
Count sampled high/low/unknown cycles and numeric min/max/final values over a clocked range. Prefer this over manual event.export counting for signal-level statistics.
{"api_version":"xwave.ai.v1","action":"signal.statistics","target":{"session_id":"case_a"},"args":{"signal":"top.u_dut.ready","clock":"top.clk","sampling":"posedge","time_range":{"begin":"@stall-100cycle(top.clk)","end":"@stall+20cycle(top.clk)"},"max_samples":1000000}}
sampled_pulse.inspect
Compare raw valid/payload transitions against DUT clock sampling. Use this when raw waveform activity exists but the DUT may not have sampled a valid pulse.
The returned raw_begin/raw_end or raw_time fields are real waveform transition times. previous_sample_edge, next_sample_edge, and nearest_sample_edge are DUT clock sampling edges that explain whether the pulse was visible to the DUT.
{"api_version":"xwave.ai.v1","action":"sampled_pulse.inspect","target":{"session_id":"case_a"},"args":{"clock":"xring_tb_top.clk","valid":"xring_tb_top.credit_init_vld","payload":"xring_tb_top.credit_init_pd","time_range":{"begin":"0ns","end":"200us"},"sampling":"posedge","format":"hex"},"limits":{"max_samples":1000000,"max_findings":20}}
Typical use: inspect summary.risk_count; if nonzero, set a cursor at data.first_risk.raw_begin or data.first_risk.raw_time, then run value.batch_at or signal.statistics around that cursor.
inspect_signal
Summarize signal transitions, period-like intervals, and glitches.
{"api_version":"xwave.ai.v1","action":"inspect_signal","target":{"session_id":"case_a"},"args":{"signal":"top.clk","time_range":{"begin":"0ns","end":"1us"},"glitch_threshold":"1ns","limit":1000}}
detect_anomaly
Find waveform anomalies such as glitches, stuck values, and x/z.
{"api_version":"xwave.ai.v1","action":"detect_anomaly","target":{"session_id":"case_a"},"args":{"signals":["top.u_dut.ready","top.u_dut.valid","top.u_dut.data"],"time_range":{"begin":"0ns","end":"100us"},"checks":[{"type":"glitch","min_pulse_width":"1ns"},{"type":"stuck","min_duration":"1us"},{"type":"unknown_xz"}],"max_findings":50}}
handshake.inspect
Analyze a generic valid/ready interface sampled on a clock.
{"api_version":"xwave.ai.v1","action":"handshake.inspect","target":{"session_id":"case_a"},"args":{"clock":"top.clk","valid":"top.u_dut.valid","ready":"top.u_dut.ready","data":["top.u_dut.data"],"time_range":{"begin":"40us","end":"45us"},"rules":{"max_wait_cycles":100,"check_data_stable_when_stalled":true}}}
Recommended AI Workflows
Point fact verification
session.open
value.batch_at
- If missing signal:
scope.list
- Store
data.values[] as evidence.
Valid/ready stall debug
handshake.inspect for generic interfaces, or axi.channel_stall for AXI channels.
- Use
value.batch_at at stall begin/mid/end for related control signals.
- Use
window.verify to prove the blocking condition persists.
- Use
event.find or event.export when you need exact event samples.
Protocol context around an event
axi.config.load and/or apb.config.load
event.config.load
event.find with context.window plus context.axi and/or context.apb
- Use returned transactions and
delta_ps as evidence.
Performance-safe scanning
Use bounded ranges and limits:
{"limits":{"max_rows":100,"max_events":100,"max_samples":100000}}
Prefer:
value.batch_at over repeated value.at
event.find before event.export
signal.statistics before exporting events just to count high/low cycles
event.export with aggregate.events:false before exporting full event rows for counts
axi.channel_stall before full AXI transaction inspection
signal.stability before full signal.changes
Error Handling
Common error.code values:
| Code | AI response |
|---|
SIGNAL_NOT_FOUND | Run scope.list near the parent scope and retry with a candidate path. |
SESSION_NOT_FOUND / SESSION_UNHEALTHY | Run session.list, session.doctor, or reopen the FSDB. |
INVALID_REQUEST / MISSING_FIELD | Fix the JSON request shape before retrying. |
EXPR_PARSE_FAILED | Simplify or validate aliases in the expression. |
WAVE_QUERY_FAILED | Check FSDB, config binding, and time range. |
If ok:false, do not use data as evidence. If ok:true but a value has known:false, preserve it as unknown evidence rather than converting it to pass/fail.