Skip to main content

rtl-buddy-xeno

SystemVerilog AST-mutation corpus generator. Consumes a hand-authored template, applies CDC-aware structural mutations, and emits mutants with a Prediction annotation declaring how downstream oracles should react.

Two consumers:

  • rtl-buddy-cdc fuzzer — oracle is cross-frontend agreement on the mutant's CDC-rule finding set (cdc#221, Stage 3 Layer B).
  • rb mut mutation-testing harness in rtl_buddy — oracle is FPV / regression property survival (rtl_buddy#206).

The name is an Alien xenomorph reference crossed with the CDC pun — "xeno" = crossing into a foreign clock domain.

Quickstart

from rtl_buddy_xeno import Mutator, MutationKind

mutator = Mutator.from_sv("path/to/template.sv")
for mutant in mutator.generate(
    kinds=[MutationKind.CLOCK_POLARITY_SWAP],
    count=10,
    seed=0,
):
    print(mutant.diff_summary)
    print(sorted(mutant.prediction.cdc_rules_added))
    # mutant.sv is the mutated source; feed it to the analyzer.

Each Mutant carries:

  • sv — the mutated SystemVerilog source.
  • diff_summary — short human-readable description.
  • seed — provenance token (operator-internal; reproduces this specific mutant given the same parent + operator).
  • prediction — a Prediction dataclass with both CDC-oracle fields (cdc_rules_added, cdc_rules_removed) and FPV-oracle fields (perturbs_signals, perturbs_liveness); empty defaults mean "no prediction in this dimension," distinct from a negative prediction.
  • kind — which MutationKind produced the mutant.

A mutant whose observed delta disagrees with prediction is actionable: either a real gap in the rule pack (file an issue against rtl-buddy-cdc) or a buggy mutation operator (fix here). That diagnostic loop is the point.

Use mutator.candidates(kinds=...) to enumerate Site objects without actually producing mutants — the budget-estimation primitive consumed by rb mut list (rtl_buddy#206). Use the schedule= kwarg on generate to choose between Schedule.SEQUENTIAL (default) and Schedule.ROUND_ROBIN; round-robin is the rb-mut idiom for budgeted runs across multiple kinds.

Mutation kinds

Fourteen operators covering both consumer pools, all implemented. See umbrella xeno#2 for the full table including MCY-expressibility.

Kind Status Used by Parser layer Exercises
CLOCK_POLARITY_SWAP implemented cdc#221 regex (no extras) CDC-016 (chain-stage gated; standalone flops predict nothing)
ATTRIBUTE_TOGGLE implemented cdc#221 regex (no extras) CDC-002 / -003 / -010 / -019, RDC-001 / -007 (per attribute)
ASSIGN_DROP implemented rtl_buddy#206 Verible + slang property survival on the LHS
SYNC_CHAIN_DEPTH_PERTURB implemented cdc#221 Verible CDC-002 / -018 (rationale only — no positive claim)
CHAIN_STAGE_INSERT implemented cdc#221 Verible CDC-018 (rationale only — no positive claim)
COMB_BETWEEN_STAGES implemented cdc#221 Verible CDC-014 (rationale only — no positive claim)
BIT_EXTRACT_PERMUTE implemented cdc#221 Verible CDC-019 / -020 (rationale only — no positive claim)
RESET_POLARITY_FLIP implemented cdc#221 Verible (+ optional slang) RDC-007 (rationale only — no positive claim)
RESET_FANIN_MERGE implemented cdc#221 Verible (name-heuristic resets) RDC-005 (rationale only — no positive claim)
ARITH_FLIP (+ ↔ -, * ↔ /) implemented rtl_buddy#206 Verible (+ optional slang) property survival
BIT_OP_FLIP (& ↔ |, ~ ±) implemented rtl_buddy#206 Verible (+ optional slang) property survival
COND_NEGATE implemented rtl_buddy#206 Verible property survival
COND_CONST implemented rtl_buddy#206 Verible property survival
PORT_BINDING_SWAP implemented rtl_buddy#206 Verible property survival + maybe CDC

All fourteen kinds are implemented — IMPLEMENTED_KINDS == frozenset(MutationKind), no operator raises NotImplementedError. The CDC rule-id predictions are deliberately conservative: an operator only populates cdc_rules_added when it can structurally justify the claim from its parser view (CLOCK_POLARITY_SWAP requires a ≥2-stage chain heuristic; ATTRIBUTE_TOGGLE keys off a known attribute name). The context-blind operators (SYNC_CHAIN_DEPTH_PERTURB, CHAIN_STAGE_INSERT, COMB_BETWEEN_STAGES, BIT_EXTRACT_PERMUTE, RESET_POLARITY_FLIP, RESET_FANIN_MERGE) leave cdc_rules_added empty and record the candidate rule in the rationale instead, so the downstream coverage report measures the actual fire rather than trusting an over-confident guess. The rule-ids above mirror rtl-buddy-cdc's rule pack by convention — they are string literals, with no code dependency on rtl-buddy-cdc.

Parser layering

Decision ratified in xeno#4 (supersedes the v0.0.1 text/slang two-layer sketch). Three orthogonal jobs, each operator picks which two or three it needs:

  1. Find candidate sites — locate operator tokens in legal SV positions (not inside strings, comments, `define bodies). Source-faithful CST. Verible, via the viewer's public helpers (rtl_buddy_view.cst_cache etc., promoted in view#109).
  2. Semantic gating — "is this + inside a parameter expression, skip"; "is this always_ff a synchroniser chain head." Elaboration. pyslang under the [slang] extra.
  3. Emit the mutated source — byte-splice on the original source string. Pure string operation; no parser. Same pattern CLOCK_POLARITY_SWAP already uses.

Byte offsets are the lingua franca: both Verible CST nodes and pyslang AST nodes carry source ranges referencing the same bytes, so an operator that uses pyslang for semantic identification still emits the splice as a byte-range on the original source string. No round-trip through either AST for emission.

No-straddle rule: a single operator never mixes layers within itself. It's exactly one of regex-only, Verible-only, or Verible+slang. No half-and-half within one operator. The rule is enforceable by reading the top-level structure of src/rtl_buddy_xeno/operators/ — each module declares its parser choice via the imports it carries.

Install

Note: rtl-buddy-xeno is preparing for its first PyPI release. Until that lands (see RELEASING.md), install from source: pip install git+https://github.com/rtl-buddy/rtl-buddy-xeno.

# Bare install — only the regex-based operators (CLOCK_POLARITY_SWAP
# and ATTRIBUTE_TOGGLE) run without extras.
pip install rtl-buddy-xeno

# With Verible CST support (required by every structural operator
# except CLOCK_POLARITY_SWAP and ATTRIBUTE_TOGGLE). Pulls in
# `rtl-buddy-sch>=0.7.0` (a floor, with no upper cap — the viewer is
# pre-1.0 and we don't speculatively block its next minor). 0.7.0 is
# the first release under that name: the viewer's distribution renamed
# rtl-buddy-view -> rtl-buddy-sch there, and `rtl-buddy-view` is frozen
# at 0.5.0. If you already have the old dist, uninstall it first —
# `pip uninstall -y rtl-buddy-view` — so a single distribution owns the
# `rtl_buddy_view` import package. For local development use
# `uv sync --extra verible` against this repo.
pip install "rtl-buddy-xeno[verible]"

# With pyslang elaboration (used by the four semantically-gated
# operators: ASSIGN_DROP, RESET_POLARITY_FLIP, plus the optional
# semantic-gating path on ARITH_FLIP / BIT_OP_FLIP).
pip install "rtl-buddy-xeno[slang]"

# Most operators need both.
pip install "rtl-buddy-xeno[verible,slang]"

The [verible] and [slang] extras are independent; each operator's module imports lazily so the no-extras install path keeps working for CLOCK_POLARITY_SWAP and ATTRIBUTE_TOGGLE. Operators that require an absent extra raise ImportError with a clear pointer at which extra to install.

Library boundary

xeno never reads root_config.yaml itself — that's the orchestrator's job (rtl_buddy). Callers inject the Verible CST cache directory as a function argument; xeno's cst.py facade accepts a cache_dir parameter and passes it through to view's cst_cache.get_or_compute. This keeps xeno usable as a standalone library (including in unit tests) without any project-config dependency.

Development

uv sync                       # bare install
uv sync --extra verible       # + Verible CST
uv sync --extra slang         # + pyslang
uv sync --all-extras          # full

uv run ruff check
uv run ruff format --check
uv run mypy
uv run pytest -q

Python ≥3.11, src-layout, frozen dataclasses, pure functions in the operator path. Conventions mirror rtl-buddy-cdc.

Design references

  • xeno#2 — umbrella tracking source-level SV mutation across consumers; includes the operator pool / MCY-expressibility table and the prior-art positioning.
  • xeno#3 — API design (Prediction shape, full MutationKind enum, candidates method, Schedule enum).
  • xeno#4 — parser layering (Verible CST + pyslang + byte-splice; the three-job decision).
  • view#109 — upstream view-side helper promotion that unblocks xeno's [verible] extra.
  • cdc#221 — Stage 3 Layer B; the originating consumer.
  • cdc#222 — Stage 4; future downstream consumer (grammar-generated topologies flow through the same Mutator.from_sv surface).
  • rtl_buddy#206 — rb mut harness; second consumer.

License

BSD 3-Clause. See LICENSE.

Metadata

Release files for rtl-buddy-xeno 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rtl-buddy-xeno 0.2.0
File Size Uploaded
rtl_buddy_xeno-0.2.0.tar.gz 55.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for rtl-buddy-xeno 0.2.0
File Interpreter ABI Platform
rtl_buddy_xeno-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 131.2 kB

Release files / rtl_buddy_xeno-0.2.0.tar.gz

Download URL rtl_buddy_xeno-0.2.0.tar.gz
Size 55.2 kB
Tags Source
SHA-256 checksum
How to use checksums
6acaf371af564c6f26e6679d72a115e7c33f4a3a8639d007a10619e58c2671fa
BLAKE2b-256 checksum
How to use checksums
c0660d5e7caabee91e190d25259355fff6be75042126a22141df400b4eef17e4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release files / rtl_buddy_xeno-0.2.0-py3-none-any.whl

Download URL rtl_buddy_xeno-0.2.0-py3-none-any.whl
Size 76.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5c6a623db3b038cd8596fc831a6daaa355395d58fde3b14f50d2f5f0602caff0
BLAKE2b-256 checksum
How to use checksums
088e2013add093a7346ae3c8f7a5e52b40201c9d45fdb2a111336f2bd9d2654c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page