2f-sim Agent-oriented lhd sim query API

Give a coding agent a stable, non-interactive way to inspect a simulation without generating and parsing a whole VCD or learning a collection of presentation-oriented CLI flags. The interface is one stateless invocation with a versioned JSON request and result. A request may batch several questions; lhd chooses the nearest checkpoint, replays once, and answers every question whose time range is covered.

lhd sim design.prp test.name \
  --workdir run \
  --query queries.json \
  --result-json answers.json

The existing --list-signals, --probe, and --break-when options remain supported as compatibility sugar over this query engine. VCD remains an export for waveform viewers, not the query database.

Request and result contract

--query accepts a file path or - for stdin. The request has a schema name and an ordered array of independently identified queries:

{
  "schema": "lhd.sim.query/v1",
  "queries": [
    {
      "id": "pc",
      "op": "value",
      "signal": "cpu.fetch.pc",
      "at": {"cycle": 10420, "phase": "post"}
    },
    {
      "id": "redirect",
      "op": "next_change",
      "signal": "cpu.fetch.redirect",
      "after": {"cycle": 10420, "phase": "post"}
    },
    {
      "id": "rob_delta",
      "op": "diff",
      "scope": "cpu.rob",
      "from": {"cycle": 10419, "phase": "post"},
      "to": {"cycle": 10420, "phase": "post"}
    }
  ]
}

The response preserves request order and IDs. Each result is independently ok or carries a structured error; one bad signal must not erase unrelated answers. The top-level metadata records the design hash, selected test and arguments, seed, checkpoint used, cycles replayed, sampling phase, and whether any result was truncated. Deterministic ordering makes the JSON suitable for agent tools and tests.

{
  "schema": "lhd.sim.query-result/v1",
  "run": {
    "design_hash": "8f31d5c0",
    "test": "test.name",
    "checkpoint_used": 10000,
    "cycles_replayed": 421
  },
  "results": [
    {
      "id": "pc",
      "ok": true,
      "at": {"cycle": 10420, "phase": "post"},
      "value": {
        "bits": 64,
        "signed": false,
        "hex": "0000000080001040",
        "known_mask": "ffffffffffffffff"
      }
    }
  ]
}

Five v1 operation families

  1. signals. Enumerate queryable signals by exact name, stable ID, scope/module, glob or regex, and kind. Return hierarchical name, aliases, width, signedness, kind, clock domain, port direction, source location, and supported operations. Unknown and ambiguous selectors are errors with suggested matches.
  2. value / values. Read one signal or a selector-defined set at an exact cycle and phase. Values are full-width hardware bit vectors, not host longs: return width, signedness, binary/hex text and a known-bit mask so wide and X/Z-bearing values are lossless.
  3. changes / next_change. Return value transitions for a signal or scope over a bounded interval, or the first transition after a point. Results identify old/new values and the exact observation cycle. This is the direct agent primitive missing from today's per-cycle --probe rows.
  4. find. Search a bounded interval, forward or backward, for the first cycle satisfying a typed expression. The initial expression language supports comparisons, Boolean composition, signal-to-signal comparisons, bit slices, and changed/rising/falling. Stop replay once a forward search is answered instead of merely recording a hit and finishing the run.
  5. snapshot / diff. Return all selected state at one cycle, or only values that differ between two cycles. Selection is explicit and bounded by scope/kind/glob plus a result cap; a response reports truncation rather than silently omitting state.

Execution and semantics

Relationship to existing tasks

WaveformQA agent benchmark

Use WaveformQA: Benchmarking LLM Temporal Reasoning on Digital Waveforms and its code/data repository as the first external acceptance benchmark for this API. WaveformQA supplies 360 questions with programmatically generated ground truth across eight categories and 24 subcategories. Its 13 RISC-V traces span roughly 338–4,185 signals and 5,000–60,000 transitions, so it tests both semantic coverage and scaling beyond hand-written unit fixtures.

The benchmark target is agent plus tool, not an agent reading a raw waveform. For every question, give the coding agent the natural-language question, the signals result, and the v1 query schema. The agent creates one or more JSON queries, invokes lhd sim --query, and returns the final answer. Compare that answer with WaveformQA's ground truth and retain the complete query/tool transcript.

WaveformQA categoryExpected v1 building blocksExamples covered
Lookupvalue, values, findvalue at time/edge, value when another signal changes, first match
Countingchanges, findtransition, rising-edge and conditionally gated counts
Arithmeticchanges plus agent arithmeticperiod, frequency and time difference
Temporalchanges, next_change, findbefore/after, event ordering and last value before an event
Multistepfind followed by value or another findcycles after trigger, nth-event value and conditional sequences
Correlationfind, values, next_changedual/triple conditions and which signal changes first or last
Misdirectionsignals, find, valuehigh-order occurrences, event-after-event and glitch-resistant stable values
FSMchanges, findstate sequences, next state and return counts

Do not add an operation merely to mirror a benchmark subcategory. First record whether an agent can compose the five primitives correctly and efficiently. A category that requires excessive result rows, tool calls or replay work is evidence for a later aggregation or expression-language extension.

Coverage ruling

WaveformQA is an event-time benchmark, while v1 deliberately observes one settled post-step value per simulation cycle. Therefore the full published score is not a valid v1 acceptance gate without qualification. Classify every question before running it and publish the denominator in each class:

Report both coverage (questions expressible with the current API) and accuracy on covered questions. The long-term evaluation target is to grow coverage without weakening exact semantics. In particular, WaveformQA can provide evidence for a later timestamp/phase extension, but it does not overturn v1's explicit cycle/post boundary.

Benchmark layers and metrics

  1. Artifact and reproduction gate. Pin an accessible WaveformQA commit and checksums for questions, ground truth, VCD and event-time JSON. Record licenses. Recreate each core/workload under lhd sim, map published signal identities to stable query IDs, and compare a reference transition slice before claiming an end-to-end result. A non-equivalent regenerated trace is a setup failure, not an agent error.
  2. Engine oracle. Translate each covered question to a reviewed canonical query sequence and require lhd sim to reproduce the published ground truth. This isolates API semantics and simulator correctness from model behavior.
  3. Query synthesis. Score whether the agent emits valid queries, selects the correct signals/time bounds and reaches the canonical answer. Keep query-schema, unknown-signal, wrong-signal and wrong-order failures separate from final arithmetic mistakes.
  4. End-to-end agent answer. Score exact/normalized answer accuracy for all eight categories and every signal/transition complexity bin. Report aggregate accuracy, accuracy among completed runs, and incomplete/resource-limited runs separately.
  5. Speed and cost. Record agent planning time, number of tool calls, input/output tokens, simulator setup/build time, checkpoint selected, cycles replayed, query execution time, result bytes and peak RSS. Publish median, p95 and per-category values; a single end-to-end wall time hides whether the bottleneck is the agent, build, replay or an over-broad query.

Run three comparable baselines: the paper's raw VCD prompt, its event-time JSON prompt, and agent-generated lhd sim queries. The first two measure direct waveform consumption; the third should avoid context growth with total trace size by retrieving only the evidence needed for an answer. Use the published waveform/answer artifacts as the oracle. For the full performance result, recreate or import each design/workload into a real lhd sim run so checkpoint/replay time is measured; a VCD-only adapter may validate query semantics but does not count as the end-to-end result.

For reproducibility, pin the coding-agent model and version, system/tool prompt, query schema, sampling policy, context limit, temperature/seed and maximum tool calls. Keep per-question transcripts and run repeated trials when the agent is nondeterministic. Because the public benchmark may enter model training data, also use WaveformQA's generator to create held-out questions and trace windows with the same 24-subcategory stratification.

Subtasks — pending

V1 boundaries

No interactive debugger or resident daemon; no VCD parser/index as a prerequisite; no arbitrary combinational-temporary or subcycle observation; no memory-content, structural-cone, causal/provenance, or multi-clock phase queries. Those can extend the versioned protocol after the five operations establish a reliable agent loop.

Acceptance