wai-quantum 0.5.0

A deterministic quantum stack in pure Rust: byte-exact circuit simulation (statevector / stabilizer / tensor-network MPS / sparse-Pauli backends), sparse Pauli dynamics at utility scale (arbitrary angles, 1024 qubits), belief-propagation tensor networks on the hardware graph, error mitigation, qLDPC decoding, noise learning, circuit-equivalence proofs, a phasor interference-ML layer, information-theoretic limits, noisy channels and state tomography, and signed energy-accounted receipts. No QPU, no cloud, no system libraries in the default features — identical results native, in the browser, and as a WASI component at the edge; the opt-in WebGPU member reaches the platform's GPU interface.
Documentation
//! The gate datapath for an FPGA, and what names its simulated member: the
//! datapath's Verilog (`lanes64.v`), the harness that drives its simulation
//! (`lanes64_harness.cpp`), the implementation id, the simulator's identity
//! and the mutants a conforming build must be caught running. Nothing is built
//! or run here, so all of it is testable on any host; the member itself is
//! `quantum_fabric_fpga`.
//!
//! **Why the datapath is bit-exact.** It is the same transcription of
//! [`lanes::exact_row`] and [`lanes::apply_words`] as the CUDA and OpenCL
//! kernels, in logic: each 32×32 product is assembled from four 16-bit partial
//! products (the size of an FPGA's multiplier blocks), exactly, in 64 bits;
//! `fx(a, b) = (a·b + 2^29) >>> 30` and each row's sum of four are exact in 64
//! bits; the lane keeps each sum's low 32 bits, and a sum outside 32 bits
//! records the gate's op-log index, the lowest winning. A gate visits every
//! pair in order, two cycles a pair, each pair's two addresses its own.
//!
//! **What the member is.** A cycle-accurate simulation of that datapath,
//! compiled by Verilator: its certificates are earned in a simulator
//! ([`Provenance::Simulator`]) and say so, and placement ranks them after
//! silicon. The day the datapath runs on a board, the same corpus certifies it
//! as silicon.
//!
//! [`lanes::exact_row`]: super::lanes
//! [`lanes::apply_words`]: super::lanes::apply_words

use super::Provenance;
use super::wgsl::{Detector, Mutant};

/// The datapath, `lanes64.v`, exactly as it is compiled.
pub const RTL: &str = include_str!("lanes64.v");

/// The simulation's harness, `lanes64_harness.cpp`: it moves bytes and toggles
/// the clock, and computes nothing.
pub const HARNESS: &str = include_str!("lanes64_harness.cpp");

/// The implementation name the id starts with.
pub const IMPLEMENTATION: &str = "fpga-lanes64";

/// Version of the host-side layout: the harness's protocol (probe and run
/// requests, little-endian), the lane layout `{imaginary, real}`, the report
/// word (`u32::MAX` for none) and the RAM's address width
/// ([`ADDRESS_BITS`]). Bumped on any change to them; it is part of the
/// implementation id.
pub const HOST_LAYOUT: u32 = 1;

/// The state RAM's address width: `2^ADDRESS_BITS` lanes, so at most that many
/// qubits.
pub const ADDRESS_BITS: u8 = 20;

/// The options Verilator compiles the datapath and the harness with, besides
/// the output paths.
pub const VERILATOR_OPTIONS: [&str; 10] = ["--cc", "--exe", "--build", "-O3", "-Wno-fatal", "-Wno-lint", "-Wno-style", "-GAW=20", "-CFLAGS", "-O2 -DWQ_AW=20"];

const DOMAIN_IMPLEMENTATION: &[u8] = b"wai:quantum-fabric-fpga\x01";
const DOMAIN_MEMBER: &[u8] = b"wai:quantum-fabric-fpga-member\x01";

fn hex(bytes: &[u8]) -> String {
    bytes.iter().map(|b| format!("{b:02x}")).collect()
}

/// A length-prefixed byte string, so that no field reads as part of another.
fn put(o: &mut Vec<u8>, bytes: &[u8]) {
    o.extend_from_slice(&(bytes.len() as u64).to_be_bytes());
    o.extend_from_slice(bytes);
}

/// `"fpga-lanes64/<16 hex>"`: the first 8 bytes of
/// BLAKE3(`"wai:quantum-fabric-fpga\x01"` ‖ put([`RTL`]) ‖ put([`HARNESS`]) ‖
/// put of each of [`VERILATOR_OPTIONS`] ‖ [`HOST_LAYOUT`] as a big-endian
/// `u32`), in hex. Any edit to the datapath, the harness, the options or the
/// host layout changes it. The simulator and its compiler are part of the
/// member id instead.
pub fn implementation_id() -> String {
    implementation_id_of(RTL)
}

/// [`implementation_id`] for another datapath text, such as a mutant's.
pub fn implementation_id_of(rtl: &str) -> String {
    let mut o = DOMAIN_IMPLEMENTATION.to_vec();
    put(&mut o, rtl.as_bytes());
    put(&mut o, HARNESS.as_bytes());
    for option in VERILATOR_OPTIONS {
        put(&mut o, option.as_bytes());
    }
    o.extend_from_slice(&HOST_LAYOUT.to_be_bytes());
    format!("{IMPLEMENTATION}/{}", hex(&blake3::hash(&o).as_bytes()[..8]))
}

/// What a simulated FPGA member is, as its id hashes it.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SimIdentity {
    /// The simulator's version line, as `verilator --version` prints it.
    pub simulator: String,
    /// The C++ compiler's version line.
    pub compiler: String,
    /// The host's architecture and operating system.
    pub host: String,
}

impl SimIdentity {
    /// `"local/fpga-sim-<d12>"`. `d12` is the first 12 hex digits of
    /// BLAKE3(`"wai:quantum-fabric-fpga-member\x01"` ‖ put(simulator) ‖
    /// put(compiler) ‖ put(host) ‖ [`ADDRESS_BITS`]). It sorts after every
    /// `local/cpu-<arch>`.
    pub fn member_id(&self) -> String {
        let mut o = DOMAIN_MEMBER.to_vec();
        put(&mut o, self.simulator.as_bytes());
        put(&mut o, self.compiler.as_bytes());
        put(&mut o, self.host.as_bytes());
        o.push(ADDRESS_BITS);
        format!("local/fpga-sim-{}", hex(&blake3::hash(&o).as_bytes()[..6]))
    }

    /// The key a runner declares in CI: `"fpga-sim-verilator"`.
    pub fn key(&self) -> String {
        "fpga-sim-verilator".into()
    }

    /// The simulator's version number: the second word of its version line,
    /// `"5.052"` from `"Verilator 5.052 2026-09-05 rev …"`.
    pub fn version(&self) -> &str {
        self.simulator.split_whitespace().nth(1).unwrap_or("")
    }

    /// `Simulator("verilator <version>")`: what every certificate this member
    /// earns says it was earned in.
    pub fn provenance(&self) -> Provenance {
        Provenance::Simulator(format!("verilator {}", self.version()))
    }
}

/// The mutants: textual edits of [`RTL`] that a conforming build must be
/// caught running, each by the detector named. Each `find` occurs exactly once
/// in [`RTL`].
pub const MUTANTS: [Mutant; 6] = [
    // The rounding constant is half what it should be.
    Mutant { name: "F1", find: "assign fx = (prod + 64'sd536870912) >>> 30;", replace: "assign fx = (prod + 64'sd268435456) >>> 30;", detector: Detector::Probe },
    // The product is shifted by one bit too few.
    Mutant { name: "F2", find: "assign fx = (prod + 64'sd536870912) >>> 30;", replace: "assign fx = (prod + 64'sd536870912) >>> 29;", detector: Detector::Probe },
    // A low half is taken as signed in its partial product.
    Mutant { name: "F3", find: "wire signed [32:0] hl = ah * $signed({1'b0, bl});", replace: "wire signed [32:0] hl = ah * $signed(bl);", detector: Detector::Probe },
    // The control test is inverted.
    Mutant { name: "F4", find: "wire        selected = ((i_ix & ctrl[AW:0]) == ctrl[AW:0]);", replace: "wire        selected = ((i_ix & ctrl[AW:0]) != ctrl[AW:0]);", detector: Detector::Certificate },
    // A sign of row 0's real part is wrong, on the imaginary part of the
    // top-right entry, which `Y` has.
    Mutant { name: "F5", find: "wire signed [63:0] s0r = p0r0 - p1i0 + p2r1 - p3i1;", replace: "wire signed [63:0] s0r = p0r0 - p1i0 + p2r1 + p3i1;", detector: Detector::Certificate },
    // The range guard never fires.
    Mutant { name: "F6", find: "if (oor && index < report) begin", replace: "if (1'b0) begin", detector: Detector::Range },
];

/// [`RTL`] with `m` applied. Panics unless `m.find` occurs exactly once.
pub fn mutate(m: &Mutant) -> String {
    let n = RTL.matches(m.find).count();
    assert_eq!(n, 1, "mutant {}: `{}` occurs {n} times in the datapath", m.name, m.find);
    RTL.replacen(m.find, m.replace, 1)
}

#[cfg(test)]
mod tests {
    use super::*;

    fn identity() -> SimIdentity {
        SimIdentity { simulator: "Verilator 5.052 2026-09-05 rev v5.052".into(), compiler: "a compiler 21.0".into(), host: "aarch64-macos".into() }
    }

    #[test]
    fn every_field_of_the_identity_is_in_the_member_id() {
        let base = identity();
        let id = base.member_id();
        assert!(id.starts_with("local/fpga-sim-") && id.len() == "local/fpga-sim-".len() + 12, "{id}");
        assert!(id.as_str() > "local/cpu-x86_64" && id.as_str() > "local/cpu-aarch64");
        for v in [
            SimIdentity { simulator: "Verilator 5.054".into(), ..identity() },
            SimIdentity { compiler: "another".into(), ..identity() },
            SimIdentity { host: "x86_64-linux".into(), ..identity() },
        ] {
            assert_ne!(v.member_id(), id, "{v:?}");
        }
        assert_eq!(base.key(), "fpga-sim-verilator");
        assert_eq!(base.version(), "5.052");
        assert_eq!(base.provenance(), Provenance::Simulator("verilator 5.052".into()));
    }

    #[test]
    fn the_implementation_id_follows_the_datapath_and_the_harness() {
        let id = implementation_id();
        assert!(id.starts_with("fpga-lanes64/") && id.len() == "fpga-lanes64/".len() + 16, "{id}");
        for m in &MUTANTS {
            assert_ne!(implementation_id_of(&mutate(m)), id, "mutant {}", m.name);
        }
        // The address width is one number in two places: the RTL parameter and
        // the harness's bound.
        assert!(VERILATOR_OPTIONS.contains(&"-GAW=20") && VERILATOR_OPTIONS.contains(&"-O2 -DWQ_AW=20"));
        assert_eq!(ADDRESS_BITS, 20);
    }

    #[test]
    fn every_mutant_edits_the_datapath_once_and_names_distinct_edits() {
        let mut seen = std::collections::BTreeSet::new();
        for m in &MUTANTS {
            let edited = mutate(m);
            assert_ne!(edited, RTL, "mutant {} changes nothing", m.name);
            assert!(seen.insert(edited), "mutant {} duplicates another", m.name);
        }
        for d in [Detector::Probe, Detector::Certificate, Detector::Range] {
            assert!(MUTANTS.iter().any(|m| m.detector == d), "no mutant for {d:?}");
        }
    }
}