A TypeScript HDL where the whole npm ecosystem is your testbench — drive a circuit with real packets, real firmware, any library you can npm install, and watch it run cycle-by-cycle. Synthesizable to Verilog.
$ claude mcp add simten npx @simten/mcpA TypeScript HDL where the whole npm ecosystem is your testbench — drive a circuit with real packets, real firmware, any library you can npm install, and watch it run cycle-by-cycle. Synthesizable to Verilog.
Circuits are TypeScript. Runs natively in Node, Bun, or browser — no testbench language, no codegen step.
import { circuit, bit } from '@simten/core';
import { Xor, And, Or } from '@simten/core/std';
import { simulate } from '@simten/core/sim';
const HalfAdder = circuit('HalfAdder', {
inputs: { a: bit, b: bit },
outputs: { sum: bit, carry: bit },
nodes: { xor1: Xor, and1: And },
connect: ({ inputs, outputs, nodes: { xor1, and1 } }) => [
inputs.a.to(xor1.a, and1.a),
inputs.b.to(xor1.b, and1.b),
xor1.out.to(outputs.sum),
and1.out.to(outputs.carry),
],
});
const FullAdder = circuit('FullAdder', {
inputs: { a: bit, b: bit, cin: bit },
outputs: { sum: bit, cout: bit },
nodes: { ha1: HalfAdder, ha2: HalfAdder, or1: Or },
connect: ({ inputs, outputs, nodes: { ha1, ha2, or1 } }) => [
inputs.a.to(ha1.a),
inputs.b.to(ha1.b),
ha1.sum.to(ha2.a),
inputs.cin.to(ha2.b),
ha2.sum.to(outputs.sum),
ha1.carry.to(or1.a),
ha2.carry.to(or1.b),
or1.out.to(outputs.cout),
],
});
// Same engine in Node — no codegen, no testbench.
const sim = simulate(FullAdder);
sim.set({ a: 1, b: 1, cin: 1 });
console.log(sim.get('sum'), sim.get('cout')); // 1, 1fast-check for property testing, D3 for visualization, the GCC RISC-V toolchain — your circuit code is just code.
// figlet — ASCII art baked into a hardware ROM
import figlet from 'figlet';
import smallFont from 'figlet/fonts/Small';
import { ROM, romFromBytes } from '@simten/core/std';
figlet.parseFont('Small', smallFont);
const banner = figlet.textSync('Simten', { font: 'Small' });
const bytes = [...banner].map(c => c.charCodeAt(0));
const Logo = ROM({ memory: romFromBytes(bytes) });One component renders a fully interactive circuit anywhere — blogs, docs, MDX. Same engine as the editor.
import { CircuitEmbed } from '@simten/embed';
import { HalfAdder } from './half-adder';
// Live, interactive hardware — three lines.
export default function Post() {
return (
<article>
<p>Here's a half adder you can poke at:</p>
<CircuitEmbed circuit={HalfAdder} />
</article>
);
}Double-click any composite to see its internals. CPU → decoder → multiplexer → NAND, all the way down.
An MCP server lets Claude write, simulate, and debug circuits live in your browser — describe, generate, fix, ship.
The framework already runs heavy systems in the browser — for example, a 5-stage pipelined RISC-V CPU executing GCC-compiled C, C++, and Rust, or an IEEE 802.3 Ethernet parser turning wire bytes into protocol fields.
Add upper immediate to PC: sp = PC + (0x20 << 12). Used to compute addresses relative to the current instruction.
// Bare-metal Rust — no OS, no stdlib.
// This runs directly on the CPU hardware.
// When done, register a0 = 55 (0x00000037).
#![no_std]
#![no_main]
use core::panic::PanicInfo;
#[panic_handler]
fn panic(_: &PanicInfo) -> ! { loop {} }
#[no_mangle]
pub extern "C" fn main() -> i32 {
let mut a: i32 = 0;
let mut b: i32 = 1;
for _ in 0..10 {Toggle inputs and play. Same simulator, same Verilog export — Snake also runs on a real ULX3S board.
Every composite is explorable. Double-click the pulsing badge to open its internals — with full simulation and nested drill-down.
Sequential circuits record every state. Step forward, spot something wrong, step back to the exact cycle it happened. No printf debugging — just rewind.
Synthesizable primitives export to structural Verilog. The RV32I CPU and Snake both flash to a ULX3S; the CPU is cross-validated against iverilog cycle-by-cycle. Running it from a clone needs the synth / verify / compile services started locally (Docker; pnpm dev:synth, dev:verifier, dev:compiler). Setup & how it works →
const HalfAdder = circuit('HalfAdder', {
inputs: { a: bit, b: bit },
outputs: { sum: bit, carry: bit },
nodes: { xor1: Xor, and1: And },
connect: ({ inputs, outputs, nodes: { xor1, and1 } }) => [
inputs.a.to(xor1.a, and1.a),
inputs.b.to(xor1.b, and1.b),
xor1.out.to(outputs.sum),
and1.out.to(outputs.carry),
],
});`timescale 1ns / 1ps module HalfAdder ( input a, input b, output sum, output carry ); wire w_xor1_out; wire w_and1_out; assign w_xor1_out = a ^ b; assign w_and1_out = a & b; assign sum = w_xor1_out; assign carry = w_and1_out; endmodule
Not diagrams. Live circuits verified against real specifications.
Or open the editor and start from scratch.