This is the second of the three parts. The last post laid down the skeleton of the flow; this one answers a sharper question: how do you know the front-end — turning a spec into RTL — is actually correct? The answer is benchmarks: throw the flow at public IC-design suites and grind until almost everything passes. Three principles hold that up.

Of the whole flow, "Spec → RTL" is the earliest and the most dangerous stretch. It's the first point where the user's intent gets translated into something a machine has to take at face value — a spec that lived in a human head becomes RTL that downstream tools will treat, literally, as gospel. Get this step wrong and every later station faithfully inherits the error: synthesis, place-and-route, timing, DRC — all of them meticulously build the wrong chip. So the front-end can't merely be "occasionally correct"; it has to be "reliably correct."
The problem is: how do you measure "reliably correct"? Not by gut feel, and certainly not by letting the AI declare "looks fine." My approach is to use public benchmarks as a magnifying glass:
For me a benchmark isn't a scoreboard to brag with; it's a microscope. Every failing case points precisely at one real gap in the front-end. The score is a by-product; the real output is a list of "why does this class of problem break?" That list is exactly what the next three principles exist to clean up, one item at a time.
The first principle is about discipline: keep optimizing the front-end until the score approaches its ceiling. Not "good enough" — every fail is a to-do.
But it isn't a blind chase for 100% either. A small minority of fails are honest floors: the benchmark itself has a defective case, the prompt genuinely under-specifies the design, or there's a real tool limitation. I don't paint those green; I label them honestly, state the reason, and move on. Everything else has to converge to a pass.
The how matters. When a case fails, I don't patch that one case — I trace it up to the whole class it represents, fix the root cause at the class level, and then re-run blind to confirm. Fixing one case and re-running that one case is self-deception; fixing a class and running the whole suite again is real forward motion.
And there's a detail that's easy to skip but that I hold hard: we optimize the pass-rate of the flow itself, not of some hand-tuned answer. The number has to reflect what the flow can do starting from the spec, with no peeking at the solution — it measures the runner, not an LLM being led by the hand. It looks small, but it decides whether the whole number means anything.
The second principle is the skeleton of the whole front-end: program-first + AI-backup, dual-track convergence. Broken out:
The most elegant thing about this dual-track scheme is its endpoint: a good AI recovery should eventually converge into a program, or a program-gate. In other words, the best possible ending for an AI saving a case is that the case never needs the AI again — it has become a deterministic rule the flow runs by itself. Whatever can be programmed gets programmed; that is the steady settling of the dual-track toward the "program" side.
The third principle answers a longer-term question: all these things that keep getting recovered, reconciled, and converged — where do they settle? The answer is a fixed extraction (capture) loop that routes each gain to its proper home:
.py program or a compliance gate, moving straight to the program-first side.Behind that IC-expert-agent sit two bodies of ever-growing knowledge: the expert-DB (ic_expert_db.json, design craft classified by ic_class) and the per-layer lessons (ic_expert_L1..L9, mistakes accumulated layer by layer). The expert-DB is keyed by design class, meaning the craft of a given chip family is stored structurally and auto-recalled every time after; the lessons are keyed by design layer, meaning the errors each layer is most prone to are written down one at a time, so next time the same layer gets checked against the rules first.
The keyword throughout is accumulation. Every trap stepped on, every case saved, is written back through the capture loop — so what one run learns, the next run, the next person, the next chip all get to use. That's the sharpest difference from a human brain: human experience retires, resigns, forgets; this agent's experience only moves one way — up. That's why I keep describing it as a senior engineer who never retires and only accumulates experience — you can read the whole growth history of the front-end as this senior engineer's record of continuing on-the-job education.
Put the three principles together and they interlock into a compounding loop: a benchmark surfaces a gap → the capture loop routes it → it becomes a program, a gate, or a lesson → the next round starts stronger. What I want has never been a one-shot front-end that's "clever this time," but a front-end that ratchets — each notch forward locks and can't slide back.
By this point, the front-end's job is to turn a spec reliably into correct RTL. But RTL is only halfway — it still has to make it through synthesis, place-and-route, CTS, DRC, LVS, and STA, carried all the way to silicon by the EDA tools. That stretch is what the next post, Part 3, covers: back-end convergence.
Next time (Part 3) I want to talk about the world after RTL: how those fiddly, unfamiliar back-end steps get to pass and verify one by one, and why — when the existing open-source EDA tools hadn't yet reached production grade in certain spots — I decided to complete the open-source part of the flow by hand.