Simten

Component Model

Primitives, composites, and the full primitive reference

Try a Primitive

Search for any primitive, see its ports and parameters, and interact with a live demo:

48 primitives
Select a primitive above to see its ports and a live demo

The Core Invariant

Circuits are either structural (nodes + connections) or behavioral (eval/onTick functions). Structural circuits have zero runtime overhead — they're elaborated away before simulation.

When you write a composite like HalfAdder using nodes and connect, you're defining structure. The simulator expands it to primitives before running — this is called elaboration. All runtime behavior ultimately comes from circuits with eval or onTick functions.

You can also write your own behavioral circuits using eval (combinational) or state + onTick (sequential). See the API Reference for details.

Component Resolution

When the system encounters a node:

  1. Check for eval / onTick on the circuit — if found, treat as a behavioral leaf
  2. Check for nodes / connect — if found, elaborate (expand recursively)
  3. Error — circuit has neither

Primitive Reference

Logic Gates

PrimitiveInputsOutputsDescription
Anda: Bit, b: Bitout: BitAND — true when both inputs are true
Ora: Bit, b: Bitout: BitOR — true when at least one input is true
Notin: Bitout: BitNOT — inverts the input
Nanda: Bit, b: Bitout: BitNAND — false only when both inputs are true
Nora: Bit, b: Bitout: BitNOR — true only when both inputs are false
Xora: Bit, b: Bitout: BitXOR — true when inputs differ
Xnora: Bit, b: Bitout: BitXNOR — true when inputs match
Bufferin: Bitout: BitPasses input through unchanged

I/O

PrimitiveInputsOutputsParametersDescription
Switchout: Bitvalue (default: 0)Clickable 1-bit toggle
Buttonout: BitMomentary push button
Inputout: Bus[N]value (default: 0), width (default: 8)Editable numeric input
Ledin: BitVisual LED indicator
Outputin: Bus[8]Multi-bit output sink
Constantout: Bitvalue (default: 0)Fixed value source
Probein: Bitout: BitDebug passthrough

Arithmetic

All arithmetic primitives support a width parameter (default: 8, options: 4, 8, 16, 32).

PrimitiveInputsOutputsDescription
Addera, b, carry_insum, carry_outN-bit adder with carry
Subtractora, b, borrow_indifference, borrow_outN-bit subtractor with borrow
Multipliera, bproduct: Bus[2N]N×N → 2N-bit multiplier
Comparatora, beq, lt, gtN-bit comparator
IncrementerinoutAdds 1 (wraps at max)
LeftShiftervalue, shiftresultLogical left shift
RightShiftervalue, shiftresultLogical right shift
SignedAddera, b, carry_insum, overflow, carry_outSigned add with overflow
SignedComparatora, beq, lt, gt, lte, gteSigned compare
SignedMultipliera, bproduct: Bus[2N]Signed N×N multiplier

Bus Operations

All support width parameter (default: 8).

PrimitiveInputsOutputsDescription
BusAnda, boutBitwise AND
BusOra, boutBitwise OR
BusNotinoutBitwise NOT
BusXora, boutBitwise XOR

Routing

PrimitiveInputsOutputsParametersDescription
Muxin0, in1, sel: Bitoutwidth (default: 1)2-to-1 multiplexer
Decoderin: Bus[2]out0out3: Bit2-to-4 decoder
Splitterin: Bus[8]out0, out1: Bus[4]Split bus in half
Splitter8to8in: Bus[8]bit0bit7: BitSplit bus to individual bits
Combiner8to8bit0bit7: Bitout: Bus[8]Combine bits to bus
BitSlicein: Bus[8]out: Bus[N]low (0), high (7)Extract bit range [low..high]
Concathigh, lowoutlowWidth (4)Concatenate buses
AddressCombinerlo: Bus[8], hi: Bus[8]out: Bus[16]Combine to 16-bit address

Sequential

These components have clocked state that updates on the rising edge of clk.

PrimitiveInputsOutputsParametersDescription
DFlipFlopd: Bitq: Bit, q_bar: Bit1-bit register, captures d on clock edge
Registerdata: Bus[N], we: Bitq: Bus[N]width (8), value (0)N-bit register, writes when we is high

Key difference: DFlipFlop always captures its input on every clock edge. Register only writes when we (write enable) is high — this lets you hold a value across multiple cycles.

Reset behavior (Verilog export): when the exporter's auto-plumbed rst_n is low, both DFlipFlop and Register snap back to their value arg. In simulation, sim.reset() produces the same effect. Memory primitives (RAM, DualPortRAM) preserve their contents during reset — only writes are suppressed.

Memory

PrimitiveInputsOutputsParametersDescription
ROMaddr: Bus[16]data_out: Bus[8]baseAddressRead-only, combinational read
RAMaddr, data_in, we: Bitdata_outaddressWidth (8), dataWidth (8)Single-port, combinational read, clocked write
DualPortRAMaddrA, dataA, weA: Bit, addrBoutA, outBaddressWidth (8), dataWidth (8)Port A reads/writes, port B read-only
DualPortROMaddrA: Bus[32], addrB: Bus[32]dataA: Bus[32], dataB: Bus[32]Two independent read ports, one shared memory. Byte-addressable, returns 32-bit little-endian words. Used for architectures that need simultaneous instruction fetch and data read (e.g. rv32i-board.circuit.ts).

Memory is initialized by calling the component factory with the memory parameter:

nodes: {
  ram: DualPortRAM({ memory: {
    0: 42,    // address 0 = 42
    1: 100,   // address 1 = 100
    64: 33,   // address 64 = 33
  } }),
},

Reads are combinational (address in → data out immediately). Writes happen on the rising clock edge when we is high.

Display

PrimitiveInputsOutputsDescription
SevenSegmentin: Bus[4]Hex digit display (0–F)
HexDisplayin: Bus[N]Multi-digit hex display
ScreendataIn: Bus[8]addrB: Bus[8]8×8 pixel framebuffer display
RasterDisplaydataIn: Bus[8]addrB, scanX, scanY, hblank, vblankHardware-accurate raster with scan counters

The Screen primitive works with DualPortRAM: connect screen.addrB → ram.addrB and ram.outB → screen.dataIn. The screen scans through addresses 0–63 to read pixel data.

I/O Devices

PrimitiveInputsOutputsDescription
Consoledata: Bus[8], we: BitMemory-mapped text output
UART_TXaddr, data_in, we, redata_outMemory-mapped serial transmit
NIC_FIFOaddr, data_in, we, redata_out, tx_data, tx_valid, etc.Network interface with TX/RX FIFOs

On this page