Types & literals
Hover has two families of type. wire describes circuit topology and holds nothing; the numeric types hold logic values. Keeping them separate is what lets the compiler tell a net apart from a signal.
Structural types
Structural types describe topology only — they cannot hold a logic state or a numerical value.
wire | An electrical net. wire in, out; |
Floating-point types
Floating-point values represent the continuous domains — time, voltage, current.
double— 64-bit.double x = 3.14;float— 32-bit.float y = 1.0;
A note on precision. float variables really are 32-bit C++ floats inside digital module logic, but the MNA solver and the global state maps work exclusively in 64-bit. A float is therefore promoted to double the moment it crosses into an analog module, drives a physical source, or is logged by .save. For anything the solver touches, prefer double — mixed precision is a reliable way to destabilise Newton-Raphson.
Integer types
Integers are for discrete logic: state machines, loop counters, bitwise work.
int— signed 32-bit.int n = -4;unsigned int— unsigned 32-bit.unsigned int k = 42;
Assigning a floating-point value to an integer truncates the fractional part. unsigned is reserved for integers — unsigned double is not a type.
Arrays
Append [size] to any type to get a fixed-size array:
wire arrays can't take a value initialiser — they hold no data.
Multidimensional arrays
Additional [size] suffixes add dimensions, read outer-to-inner exactly as in C:
Two initialisation forms, applied recursively at every level:
- Nested brace literals —
{{...}, {...}}. The nesting depth must match the declared dimensions. - Scalar fill — one value broadcasts to every element across all dimensions, not just the outermost.
int[2][2] grid = 0;zero-fills all four.
Each subscript peels off one dimension, left to right:
Passed to a function, only the outermost dimension may decay; every inner dimension has to stay a known fixed size.
Pointers
Append * to a numeric type. Stars stack one per level of indirection, and combine with array syntax:
A pointer with no initialiser defaults to null, the way a scalar defaults to 0.
Address-of and dereference
& takes an address; prefix * dereferences. These are the same symbols used for bitwise AND and multiplication, disambiguated purely by position exactly as C does it — unary in front of an operand with nothing to its left, binary between two operands.
Pointers as parameters and state
A pointer subscripts like an array — p[i] compiles to *(p + i), the usual C duality. Unlike a scalar parameter, which is copied, a pointer parameter is aliased: writes through it inside a function are visible to the caller.
Because a pointer is just an address-sized value, it can be declared state to persist across timesteps — the standard way to hold a handle from external C++ for the life of the simulation. See the opaque pointer pattern.
Pointer arithmetic (p + 1) isn't supported; use indexing to walk memory.
Number literals & suffixes
Engineering suffixes are part of the number token — no space between digits and suffix. Scientific notation (1e-6, 1e3) also works.
| p | 10⁻¹² | 10p | 10 pF / ps |
| n | 10⁻⁹ | 100n | 100 nH / ns |
| u | 10⁻⁶ | 2u | 2 µF / µs |
| m | 10⁻³ | 2m | 2 mH / ms |
| (none) | 1 | 400 | 400 |
| k | 10³ | 20k | 20 000 |
| Meg | 10⁶ | 1Meg | 1 000 000 |
| G | 10⁹ | 2G | 2 000 000 000 |
Suffixes are case-sensitive: the megohm suffix is Meg, and 1meg is a syntax error.