LLM PCB Routing: What the Contract Engineer Taught It | EdgeLog
On this pageThe board<br>What the LLM produced<br>I could have made DRC read zero and did not<br>Power and clock were the same width<br>What code did far better than me<br>Two engagements, and the rigorous one came back empty<br>Putting the two boards side by side<br>Why those 11 violations disappeared, and how I got it wrong first<br>Our own brief was wrong as well<br>Distilled into techniques<br>Replaying it in-house<br>What it lost, and what is unknown<br>The misfires belong in the record too<br>Where things stand<br>Where to call a human
I handed PCB routing to an LLM. It did not go well, so I hired it out. Then I put the returned board next to the previous one, net by net, and turned the differences into a registry of routing techniques for the agent to use next time.
Sixteen techniques went in. Each one names an editor slot, and seven of them read gui_card, which is what you write when no function exists and a person has to do it by hand. The move that saved this board is one of the seven.
An LLM cannot lay out a board the way a practised human does. What USD 145 with a contract engineer bought is not routing skill but a written list of where it fails, and the list outlives the board.
The model was Fable 5, from memory. The repo only ever wrote down “Claude”, so that one is my word, not a log line.
The board
21mm diameter, round, four layers, running off a CR1632 coin cell. The main module is a Raytac AN54LV-15 (nRF54L15, internal chip antenna) with a TDK ICM-42688-P for motion. The first inner layer is solid ground, which leaves two layers of real routing room for fifteen nets.
Three terms carry the rest. A net is one line in the schematic tying a signal together, roughly a single variable in software. A via is the hole drilled to move a trace between layers, and DRC is the check that sweeps the board for anything a fab would reject. Close enough to a linter.
The board is not drawn with a mouse. Python code generates it, and the constants in the rules file look like this.
TRACK_MIN_MM = 0.127 # 5 mil<br>CLEARANCE_MM = 0.1 # tightened (still JLCPCB-capable) to open routing room<br>VIA_DRILL_MM = 0.3<br>VIA_DIA_MM = 0.5<br>Read the comment on the second line. It says, in its own words, that the clearance was tightened to open up room for routing. Half of what follows starts from that one line.
What the LLM produced
The first board came back with 143 DRC violations. The diagnostic classified about 120 of them, 84%, as having no mechanical content: 90 from one bad via template, three rules broken on each of 30 vias, 16 fine-pitch clearance rule mismatches, 18 silkscreen cosmetics, 3 plane fills. That adds to 127, not 120, because the categories double-count a handful and I never reconciled it. Sixteen are left over on the arithmetic that actually adds up, and 8 of those were the real signal: courtyard overlaps.
Bringing the via spec up to our own 0.50/0.30 rule, the one printed above, took those 90 to zero in a single change. The diagnostic named the cause in one line: the freerouting autorouter’s via template ignores the board’s via rules. The padstack it emitted left a 0.075mm annular ring against our own 0.10mm rule, and the diagnostic’s verdict was that the board was not fab-legal. It was not entering a factory.
DRC reported all 90 of them honestly, from the first run. The green light did not lie. Nobody was reading it.
That fix came at a price. Bringing the vias to spec grew a field of fatter vias that created roughly 34 new density violations , and unconnected nets went from 6 to 13 . The total dropped from 143 to 64 while the verdict changed to DENSITY_LIMITED. Sixty-four was the floor reachable by tuning rules, nowhere near the 20 I had set as a target.
The number improves while the verdict gets worse. That combination is where the autorouter ended.
I could have made DRC read zero and did not
While writing the contract brief I tried one thing. Widening the global clearance from the 0.1mm in that code back to 0.16mm takes the 11 boundary violations on the handoff board to zero. It also pushed unconnected nets from 6 to 15, though the brief took that count on the previous revision, not this one.
That is passing DRC by abandoning routing. I did not use it, and the brief says so in those terms.
Watching one number, this trade reads as an improvement. Eleven became zero.
Power and clock were the same width
The quietest defect was here. Battery power VBAT, ground GND, SPI clock SPI_SCK. All three nets carried the same 0.2mm trace width on the board I handed over.
Coin-cell power drawn at the width of an SPI clock. DRC cannot catch this, because no rule was broken. On the board that came back, VBAT stepped between 0.25 and 1.0mm and GND opened up to between 0.3 and 0.7.
What code did far better than me
On exhaustively sweeping part-rotation combinations, code does not even give me a game. What worked here is a for loop, not an LLM. It ran all 2^14, 16384 of them, and...