digiwleeaBlogOpen the lab →
← All posts

An AI tutor that is not allowed to lie about circuits

2026-07-16 · Tacettin Sancak

My circuit simulator has an AI tutor. You can ask it to build you a full adder, and a few seconds later a working full adder appears on your canvas, wired, laid out, and correct. Every time. Not because the language model is reliable, but because the system around it refuses to let an unreliable answer through.

That's the interesting part. Anyone can pipe an LLM's output onto a canvas. The problem is that a tutor that draws a *wrong* circuit is worse than no tutor at all: a beginner cannot tell the difference, and the whole point of a simulator is that the thing on screen is true. So the rule I built the integration around is simple: the model proposes, the engine disposes. Nothing the model says reaches the canvas until the real simulator has proven it.

The model never places anything

The first design decision: the model is not allowed to talk about geometry at all. Its build tool takes a *logical netlist*, a list of nodes ("an AND gate here, an input called A there") and connections between named pins. No coordinates, no wire paths, no layout hints.

This isn't just about saving tokens. Early experiments made it obvious that LLMs are confidently terrible at 2D placement: parts overlap, wires cross bodies, pins end up on the wrong side. Worse, coordinate output *looks* plausible, so failures are silent. A logical netlist, by contrast, is the model's native register: it is a statement about *meaning* ("the adder's carry feeds the OR gate"), and meaning is exactly what a language model is good at and exactly what I can verify.

So the contract is: the model describes what the circuit *is*, and my layout engine decides where everything *goes*.

Layout is a claim, and claims get checked

Here is the guarantee the layout engine makes: a candidate layout is emitted only if, after actually placing the parts and routing the wires, the resulting electrical connectivity is *exactly* the netlist the model asked for. Not approximately. Exactly.

Verification is not a heuristic. The candidate is run through the same pipeline a hand-built circuit uses: parts are placed on the grid, wires are routed around obstacles, the circuit is flattened, and a union-find pass groups every wire endpoint and pin into electrical nets. That gives a partition of all pins into nets. The intended netlist gives another partition. If the two partitions are not identical, the candidate is thrown away. A wire that brushes a neighboring pin, a route that shorted two nets, a pin left floating: all of these change the partition, so all of them are caught by construction rather than by a list of special cases I hoped was complete.

The check runs on the real simulator's data structures, not a parallel implementation. That matters. A separate "validator" would drift from the engine over time and start approving circuits the engine disagrees with. Using the engine itself means the verification is definitionally in sync with what the user will experience.

A cascade of layout strategies

One layout algorithm cannot handle everything, so the engine tries a sequence of them, and the verify gate is what makes the cascade safe: the first candidate that *proves itself* wins, and a strategy that fails costs nothing but time.

Transistor-level circuits go to a CMOS schematic generator that knows what pull-up and pull-down networks are supposed to look like. Gate-level circuits get a classic schematic layout. Circuits built from larger blocks go through a proper graph-layout pass (ELK), with each part's ports pinned at their true pin offsets so the router's plan survives contact with the actual component shapes. After that come progressively more conservative fallbacks, ending in a channel router that is provably collision-free: ugly, but never wrong.

The ordering encodes taste: try the layout a human engineer would draw first, fall back toward guaranteed-correct-but-plain. Because every candidate passes the same partition check, adding a new strategy is risk-free. The worst a bad strategy can do is waste its slice of the wall-clock budget.

The loop: do, check, continue

Correct layout only guarantees the circuit matches what the model *asked for*. It does not guarantee the model asked for the right thing. An LLM will cheerfully produce a "full adder" whose sum output is just A XOR B.

So after every build, the system sweeps the circuit through the simulator and hands the model back the actual truth table of the thing it just built. Not "looks good!", the real input-to-output mapping, measured. For clocked circuits it runs the simulation forward over clock cycles and reports behavior over time, because a single-instant reading of a flip-flop tells you nothing.

This turns the tutor into an agent with a lab bench. It builds, reads the measurement, notices the sum column is wrong, rebuilds with the missing XOR, and checks again. The model's judgment is still fallible, but it is now fallible *in front of an instrument*, and the instrument does not flatter it. Most wrong first attempts fix themselves within an iteration or two, without the user ever seeing the broken version.

Failing is a feature

The last piece is what happens when nothing verifies: the tutor simply does not build. It says so, and the canvas stays untouched.

That felt unsatisfying to ship. Every instinct says "degrade gracefully, show *something*". But showing something is precisely the failure mode this whole design exists to prevent. A tutor that occasionally draws a subtly shorted circuit teaches a beginner that circuits are mysterious and untrustworthy. A tutor that occasionally says "I couldn't build that correctly, let me try a different structure" teaches them that correctness is checkable. In an educational tool, the second lesson is half the curriculum.

The same gate protects the library: when the tutor authors a reusable component, it builds the part off-canvas, verifies it against the simulator, and only then saves. Nothing unverified is ever persisted anywhere.

What generalizes

None of this is specific to circuits. The pattern is:

  1. Constrain the model's output to the semantic layer it is actually good at,

and keep it away from layers where its errors are silent.

  1. Verify with the production engine, not a lookalike validator, and verify

the *whole* property (partition equality), not a checklist of known failure modes.

  1. Feed measured reality back into the loop, so the model iterates against an

instrument instead of its own confidence.

  1. Prefer honest refusal over plausible wrongness.

LLMs are proposal generators with excellent taste and no integrity. The engineering is in building the judge.

This is from building digiwleea, a free browser lab where you build a CPU starting from single transistors. Go move things around and try to break a circuit.

← All posts