A compiler-based RTL simulator for Veryl and a synthesizable subset of SystemVerilog.
Celox compiles an elaborated Veryl design into executable simulation kernels and exposes the design through a type-safe TypeScript API. The same kernels can be built from synthesizable SystemVerilog through the Rust API (see SystemVerilog support). It is both a practical way to test RTL with Vitest and an open testbed for exploring how RTL simulators should be structured.
Try the Playground · Read the guide · Use the starter template · Browse the API
Celox explores a simple question: what does a modern RTL simulator architecture look like when compilation, scheduling, state representation, code generation, and testbench integration are designed together?
The project makes those boundaries explicit:
- Veryl-specific analysis ends at a source-independent design representation.
- Combinational dependencies and clock domains are scheduled before execution.
- A backend-independent IR and state layout are shared by multiple code generators.
- Native and WebAssembly execution use the same runtime contract.
- The testbench sees the same typed design API regardless of the execution backend.
This makes Celox useful as an architecture laboratory without reducing it to a compiler demo: the result can run real RTL tests, in Node.js or in a browser.
- Import
.verylmodules directly into TypeScript with generated port and hierarchy types. - Write assertions, fixtures, and parameterized tests with Vitest.
- Choose explicit event-based stepping or scheduled, time-based simulation.
- Exercise multiple clock domains and combinational clock cascades.
- Enable four-state simulation and drive or inspect
XandZvalues. - Override top-level parameters and include test-only Veryl sources.
- Inspect child instances and emit VCD waveforms.
- Compile a Veryl design into a native executable and run cocotb tests through VPI.
- Build an external netlist frontend with the Rust SDK and ship its simulator as a native application binary or a frontend-specific N-API/WASI addon.
- Run through the custom native backend on x86-64 and AArch64, the Cranelift fallback on other native targets, or WebAssembly in the browser.
The fastest way to start is the
celox-template. For an existing
Veryl project, install Celox, its Vite plugin, and Vitest:
npm add -D @celox-sim/celox @celox-sim/vite-plugin vitestEnable the plugin in vitest.config.ts:
import { defineConfig } from "vitest/config";
import celox from "@celox-sim/vite-plugin";
export default defineConfig({
plugins: [celox()],
});Given a Veryl module such as src/Adder.veryl:
module Adder (
a: input logic<16>,
b: input logic<16>,
sum: output logic<17>,
) {
always_comb {
sum = a + b;
}
}
you can import the design and test it as a typed object:
import { describe, expect, test } from "vitest";
import { Simulator } from "@celox-sim/celox";
import { Adder } from "../src/Adder.veryl";
describe("Adder", () => {
test("adds two values", () => {
const sim = Simulator.create(Adder);
try {
sim.dut.a = 100n;
sim.dut.b = 200n;
expect(sim.dut.sum).toBe(300n);
} finally {
sim.dispose();
}
});
});The Vite plugin analyzes the project and generates TypeScript sidecars, so port
names, signal values, and visible hierarchy are checked by TypeScript. See the
Getting Started guide
for the required Veryl.toml and tsconfig.json setup.
Simulator gives a test direct control over events. It is a good fit for
combinational blocks and cycle-oriented unit tests:
const sim = Simulator.create(Counter);
sim.dut.enable = 1n;
sim.tick();
expect(sim.dut.count).toBe(1n);
sim.dispose();Simulation manages clocks and simulation time. It is intended for multi-clock
and time-oriented scenarios:
const sim = Simulation.create(Counter);
sim.addClock("clk", { period: 10 });
sim.reset("rst");
sim.runUntil(100);
expect(sim.time()).toBe(100);
sim.dispose();Veryl source
│
▼
frontend analysis and hierarchy elaboration
│
▼
symbolic logic and dependency scheduling
│
▼
Simulator IR (SIR) and backend-independent optimization
│
▼
shared physical state layout
│
├──► native x86-64
├──► native AArch64
├──► Cranelift JIT
└──► WebAssembly
│
▼
event-driven runtime
│
▼
Rust / Node.js / browser hosts
The shared pipeline is deliberate. Scheduling and RTL semantics do not have to be reimplemented for every target, while backend implementations can still own their instruction selection, machine IR, register allocation, and code emission. The runtime separates next-state evaluation from commit when clock domains trigger together, then propagates combinational changes until the step settles.
For details, see the architecture overview, compiler components, and SIR reference.
Celox is under active development. Its focus is synchronous RTL written in
Veryl or in the synthesizable subset of SystemVerilog, tested at the design
level. The SystemVerilog guide
lists what the subset covers and what it leaves out. Celox is not a general
SystemVerilog simulator: it does not run behavioral or verification code
(initial, delays, assertions, classes), and it is not a gate-level timing
simulator or an implementation of detailed delta-cycle event semantics.
That narrower scope is intentional: it keeps the simulator small enough to make architectural changes, compare execution strategies, and test new compiler and runtime boundaries in a complete working system. Expect unsupported constructs and API changes while the design is still evolving.
- Getting Started
- Writing Tests
- Celox CLI and cocotb
- External Frontends and Rust Binaries
- Four-State Simulation
- VCD Waveforms
- TypeScript API
- Simulator Internals
- Release Policy
Celox is a Rust and pnpm workspace. On Linux, run nix develop to enter the
locked development environment (also used by both devcontainer variants).
See Development environment for nix-direnv setup, mbx
cache placement on Btrfs, and devcontainer host-directory configuration.
Choose local checks using the change-based validation matrix.
Run the affected regression and integration tests before pushing. Full CI runs
daily on the default branch and on develop, including external simulator
comparisons, so broader coverage continues even when no files change.
Architecture discussions, bug reports, and focused experiments are welcome in GitHub Issues.
The development environment includes cocotb and Verilator for native VPI integration tests and SystemVerilog benchmarks. Cargo runs through mbx to share compiler outputs and manage target directories.
celox-test-suite provides 648 language
cases and a simulator adapter contract for other Veryl implementations, plus
an optional Verilator verifier for checking the expectations independently.
Licensed under either Apache License 2.0 or MIT, at your option.