Part 3 — Back-end convergence: making every step after RTL pass (EDA: completing open source, coexisting with commercial)

Finishing the RTL is really only halfway. After it comes a whole row of unfamiliar, fiddly steps — synthesis, STA, PnR, CTS, DRC, LVS, IR, plus analog — each of which has to actually run and pass verification. This post is about wiring open-source EDA tools up as AI's hands and eyes, and about completing "the open-source part" of the flow until it can produce a production-ready result; commercial tools, meanwhile, are welcome to plug in for a fee any time.

After RTL is where the real wilderness begins

The previous two posts were about building the flow, and then using benchmarks to grind "Spec→RTL" until it passes cleanly. But honestly, writing the RTL is the most comfortable stretch of the whole flow. The genuinely unfamiliar, genuinely fiddly part is all after the RTL — and that is the third of the three parts of the architecture: back-end convergence.

From the RTL down, you have to push it through: synthesis, static timing analysis (STA), DFT, floorplanning, placement, clock-tree synthesis (CTS), routing, parasitic extraction, DRC, LVS, IR-drop and antenna checks, and only then out to GDS; analog has its own A1–A9 track on the side. Every one of these is a standalone tool that has evolved over decades, each with its own CLI, its own scripting syntax, its own log format, and its own whole repertoire of weird failure modes. For a software person still new to this flow, this stretch is the hardest and the most time-consuming.

And its biggest challenge isn't that it's "hard to compute" — it's that the existing open-source tools have holes that stall the flow partway and stop it producing anything you could send to fab. To make every step after RTL actually pass, you have to do two things first: let the AI actually touch these tools, and then complete the pieces the tools themselves are missing.

First, give AI a pair of hands and eyes: the MCP-EDA server

AI is great at writing code and great at talking about RTL, but it can't touch the real Yosys, OpenROAD, or KLayout. So the first thing to do is fit it with hands and eyes — and that's what the MCP-EDA server inside Vibe-IC does.

It wraps every real EDA action into a tool the AI can call directly: eda_synth, eda_sta, eda_pnr, eda_drc_klayout, eda_lvs, eda_spice — dozens of them, one for nearly every back-end step. It rides on MCP (Model Context Protocol), the open protocol from Anthropic that Claude Code speaks natively, so the moment the plugin is installed the server auto-registers and the user configures nothing. Having done software for a long time, I know one thing well: don't reinvent a wheel if you don't have to; MCP happens to standardize away exactly the parts that are easiest to get wrong — how a tool declares its parameters, how a call is passed, how a result comes back.

But those "hands" still need a pair of "eyes," for the reason a software person like me stubbed his toe on hardest along the way: a lot of the time these tools won't actually tell you they failed. ngspice runs a .measure in batch mode, the measurement fails, and yet the process dutifully returns rc=0, so CI counts it as a pass; some tools hand you a report that looks perfectly clean while the result underneath is wrong. So each MCP tool isn't just "pressing the button for the AI" — it also parses the tool's log line by line, takes the exit code seriously, returns a structured JSON, and computes a SHA-256 attestation over the artifacts. That way the deterministic compliance gate downstream can check against real evidence, instead of taking the AI's word that "it passed." This is the same thing as the whole plugin's anti-fabrication spirit — which is the subject of the next post.

The open-source tools have holes: completing "the open-source part"

Once the hands and eyes are connected, the real work begins. Running real designs, I quickly hit a wall: the open-source EDA tools themselves have holes. Not the good kind of bug that errors out in your face — a more troublesome kind: the tool gives you exit 0 and a clean report while the result is actually wrong; or it crashes outright under real parasitics and real corners, and the whole back-end flow snaps in the middle. If your architecture is just "call the tool, trust the tool," then you inherit every one of its holes intact, and you never produce anything you could tape out.

So I made a decision that is completely natural for a software person: fork the tools and complete the missing pieces myself. Let me be clear about how I frame this, so it isn't mistaken for squaring off against anyone — what I'm completing is "the open-source part of this end-to-end flow." The goal is simple: let the open-source toolchain run all the way to production-ready, to sign-off grade, instead of stopping at "this step needs a different tool." It's part of my own flow, and finishing it is my responsibility, not something to wait on others for.

To date I've forked 13 open-source tools, and all 13 carry my own patches (yosys, OpenROAD, OpenSTA, magic, netgen, iverilog, verilator, KLayout, ngspice, cocotb, cocotb-coverage, pyuvm, sby) — 12 of them pinned directly by the Dockerfile, with OpenSTA pinned through OpenROAD's src/sta submodule. One distinction worth drawing: "carries my patches" and "consumes an upstream capability" are two different things. Take verilator: what I patched is constrained-random solving, while its multithreaded simulation is something upstream already had and I simply use — the latter doesn't mean the former isn't there. xschem isn't forked yet and is used straight from upstream. All of these are pushed under the public github.com/vibeic org (each a real, upstream-tracked fork, so I can pull upstream fixes and contribute mine back), then packaged into a single public Docker image:

ghcr.io/vibeic/vibeic-eda:0.2.17   # built on a forked IIC-OSIC-TOOLS, with these fork fixes layered on

Whoever installs Vibe-IC just runs docker pull and gets the whole fixed toolchain. And the discipline I hold myself to is this: every fix must come with a reproducible FAIL→PASS proof — run the unmodified stock tool once (showing it silently gets it wrong / crashes / fake-passes), then run the patched fork on the same case (showing it's now correct), the two outputs side by side, and it only counts once it's been independently re-run and verified. FIX_STATUS, the living scoreboard, currently records 30 proven FAIL→PASS fixes, each row carrying its proof.

There's one more thing I want to be clear about, because it's Vibe-IC's whole stance: completing open source does not mean I'm against commercial. What this flow emphasizes is that it is end-to-end; as for the tools — open source or commercial — all of them are usable. If one day a commercial EDA vendor wants to plug a tool into this plugin and become part of the flow, I welcome it warmly; users simply pay to use it, exactly as natural as paying to use an IP block on the platform. What I want is a flow that runs end to end, not a contest of which tool to take sides with.

One concrete piece of evidence: svrfdrc

"Can open source actually reach sign-off grade?" Rather than argue it in the abstract, let me give one piece of evidence I ran myself and remember most vividly.

A foundry's sign-off DRC rules are usually written in the SVRF rule format, and a single deck easily runs to tens of thousands of lines. KLayout's DRC engine is itself very strong — it has every geometric operation you could want — but it doesn't natively read SVRF syntax, so the path of using it to run a foundry deck was, by default, broken. Instead of treating "this step needs a different tool" as a reason to stop, I wrote a standalone native svrfdrc C++ buddy inside KLayout: it directly parses a real foundry SVRF deck of about 87,000 lines, 224 layers, and 4,533 rules, translates each rule into a native operation of the KLayout DRC engine, and runs it in the engine.

The whole difficulty is in semantic alignment: SVRF has many format-specific subtleties, and getting one wrong phantoms up thousands of false violations — you have to root-cause and zero out one rule family at a time. In the end, on this complete foundry deck, it runs to {'PASS': 4533}, 0 violations, passing our own consistency checks, and it runs end-to-end inside the plugin's runner — not hand-assembled — with no commercial license needed at all.

I single this one out not to prove who's stronger than whom, but to make one very simple point: an independent open-source engine can run a complete foundry sign-off deck from start to finish, and run it clean. This is what "the open-source part" looks like once it's completed — it can stand at sign-off grade.

An honest block-by-block comparison: what's caught up, what's still behind

Having taken the whole flow apart block by block, I can lay out an honest table: for each block, where the open-source tool has "caught up" and where it's "still behind." Conclusion first — apart from the hard wall of advanced-node PDKs, most of the gaps are an investment gap, not a possibility gap: engineering-fillable and logic-solvable, not a limit of principle (I made this first-principles argument in Post 3; here I just add the tool-by-tool measurements).

The table covers 12 of those 13 forks — which happen to be the two ends of the flow: 6 on the verification side (simulation, verification frameworks, formal) and 6 on the back end (synthesis through sign-off), plus the PDK row at the bottom; the only one not shown is magic (GDS streamout and parasitic extraction). The "What we fixed in our fork" column lists only things I actually changed and that carry a FAIL→PASS proof; every cell is followed by what's still missing, because completing a piece is not the same as catching up to one.

Stage Open-source tool Commercial counterpart My honest assessment What we fixed in our fork
Simulation (RTL / gate-level) iverilog (+ Verilator) VCS / Xcelium 4-state RTL and gate-level simulation are usable; single-run throughput still trails commercial parallel engines The iverilog fork fills in SystemVerilog-2012 testbench coverage (a nonblocking-event codegen segfault, compilation-unit package ordering, forward-declared $dumpvars, break; / continue;), so testbenches written for VCS/Xcelium actually run on an open simulator; the Verilator fork adds constrained-random solving ($countbits with a single non-constant control, power-of-2 base with a variable exponent), while multithreaded simulation (--threads) and parallel verilation are capabilities upstream already had that we simply consume. Still behind: an event-driven engine is inherently serial (vvp's vthreads are coroutines, not OS parallelism), so the win on large regressions comes from fanning out many independent runs, not from a single faster simulation.
Verification frameworks cocotb / cocotb-coverage / pyuvm UVM (SystemVerilog) + commercial coverage / VIP The Python verification environment is workable; the commercial VIP ecosystem is still a clear gap Parallel multi-DUT / multi-seed regression dispatch in the cocotb fork; parallel tree-reduce coverage-DB merging, constrained-random solver scalability (streaming + reservoir sampling, uniform draws in O(1) memory), and coverage rank/merge/closure in the cocotb-coverage fork; RAL accessors, TLM comparators, and sequencer arbitration in the pyuvm fork. Still behind: the coverage database standards (UCIS/UCDB) are external-by-design for the open ecosystem, and pyuvm is bound to a single simulator's serial event loop plus the GIL, so intra-test parallelism simply isn't available.
Formal verification SymbiYosys (sby) + Yosys formal JasperGold / VC Formal Bounded and unbounded safety properties can be proven; liveness and X-propagation remain genuine gaps A batch of formal capabilities landed in the sby fork this cycle (V18/V19/V23/V24/V26–V28/V30/V38–V42/V46/V49/V50 and others, including package-layout and version-drift fixes); parallel task/engine scheduling was already upstream, so we just use it. Still behind: unbounded liveness needs the aiger/aigsmt engine family that isn't in the container, and formal X-propagation needs a yosys dual-rail X-encoding transform pass that doesn't exist yet — neither of those is solved.
Logic synthesis Yosys Design Compiler Small-to-mid-scale synthesis / mapping / equivalence is usable; very-large-scale QoR still trails Module-level parallel synthesis (a thread pool in our fork), an ABC area-recovery / sizing QoR pass, read_liberty integrated clock-gating cells, D-latch→liberty mapping, and tri-state fanin preservation. Still behind: ABC's intra-module core is still serial — which is exactly where this row's large-scale QoR gap sits.
Static timing OpenSTA PrimeTime Core timing engine has caught up; advanced sign-off models (AOCV/POCV) trail a bit — the closest to parity Our fork adds the sign-off SI and timing-ECO kernels: crosstalk delta-delay, CRPR/CPPR including generated and divided clocks, and POCV/LVF sigma-table ingestion — precisely the gap this row calls out. Still behind: SI-aware delay is a standalone command today, not yet folded into the arrival/required propagation graph.
Place & route OpenROAD Innovus / ICC2 Runs all the way to GDS at the sky130 tier; very-large-scale convergence speed and QoR clearly behind Post-detailed-route repair on real parasitics (which also fixed a stock Signal-11 crash), advanced-node DRC completeness (LEF58 MIN-STEP MAX-EDGES enforcement the stock router silently dropped), per-net-weight timing/congestion-driven IO pin placement, and PDN strap-sizing plus decap-sizing inverses gated against an independent field solver. Still behind: convergence speed and QoR on very large designs, exactly as the assessment says.
DRC sign-off KLayout Calibre Engine is at sign-off grade; reading a foundry SVRF deck is filled in by the self-written svrfdrc The native SVRF DRC engine and the svrfdrc driver that reads a foundry sign-off deck directly, plus 16 native sign-off operations (multi-patterning coloring, critical-area analysis, CMP density-gradient, native ERC / voltage-aware spacing, RVE result DB); and this cycle, the root cause of a tl::Thread use-after-free: wait() returned without a real pthread_join, so a worker's closure was freed while the OS thread was still unwinding, intermittently corrupting the heap under --threads (ThreadSanitizer: 6 data races → 0; 250+ oversubscribed stress runs, 0 crashes; reports byte-identical across thread counts). That's the kind of bug that only surfaces once you run the tool at scale on real decks.
LVS sign-off Netgen Calibre Trustworthy once the silent false-pass is fixed; still needs hardening at scale These are the fixes that made the previous column's "once the silent false-pass is fixed" true: a black-box zero-corresponded-pin guard (a black box must not MATCH on zero pins), properties and tolerances carried per-device from the PDK setup, short/open localization, and PERC-lite floating-net plus missing-well-tie ERC. Still behind: hardening at scale.
Analog environment ngspice / xschem Spectre / Virtuoso The biggest gap: single simulations are usable, but the integrated design environment is far behind Process-parallel AC frequency sweep (result-identical, ~5.5× at 8 jobs), a hardened flat-DSPF parasitic reader (stock silently dropped malformed parasitic cards; ours validates and refuses them), an OpenMP device-eval build, and Monte-Carlo / PVT corner fan-out. Still behind: this row's real point is unchanged — what's missing is the integrated design environment (I haven't even forked xschem), not the simulator.
Advanced-node PDK sky130 / GF180 / IHP Various ≤7nm A hard wall: no production-capable open ≤7nm today, only predictive ASAP7 We added ASAP7 (ASU/ARM's 7nm FinFET predictive PDK, BSD-licensed) and NanGate45 to the image as first-class enablements. This does not break the wall: they are predictive/educational and not tapeout-capable, with no foundry standing behind them; all they do is let the flow be exercised end-to-end at a 7nm-class node.

Read down that table and you'll spot a pattern: except for the PDK wall, almost every gap is the kind of thing where "nobody has written a certain pass yet, filled in a certain corner case, or parsed a certain log properly." Where commercial tools lead, it's often not because others can't reach it in principle, but because they've filled in tens of thousands of corner cases, one at a time, with decades of unbroken engineering investment; the open-source side is simply still short of hands to do the filling. And that's exactly where I'm optimistic — this kind of hole can be filled one at a time, and AI is dramatically lowering the cost of the filling.

For a live, tool-by-tool version (updated as the forks fill holes), see the "what our forks still can't do" table on the EDA Forks page.

Honestly, what's still missing

I'm certain about the direction, but today's result is far from complete. There are a few gaps I have to spell out honestly, or this post turns into a sales pitch:

But let me be precise: the vast majority of these gaps are "hole-filling" engineering, not an impossibility of principle. And filling them is exactly what I've spent this stretch doing — taking these open-source EDA tools, benchmarking them against commercial grade, and closing the solvable gaps almost by brute force, one block at a time. Nearly every lag I could figure out how to fill, I've filled; what remains is mostly the PDK hard wall above, the integrated analog environment, and convergence and QoR at very large scale.

So rather than say I'm out to "fight" commercial EDA, I'd say commercial EDA is my benchmark. I hold it up as the reference and chase it step by step — and I do believe that, in time, this open flow can reach its level, and maybe go past it. Does commercial EDA still have a market? Certainly — that segment isn't going anywhere; and whether or how those vendors choose to transform is beyond the scope of this post. When Linux arrived it didn't wipe out the server market, nor Windows on the PC desktop — a more open option showing up isn't necessarily about one side replacing the other; it's more about growing the pie and letting more people get a seat at the table.


Wiring every step after RTL up to real tools, then filling in the open-source part block by block until it reaches sign-off grade — back-end convergence was probably the hardest and most grounded stretch of work this past month. And what makes all of it trustworthy is a deeper principle underneath: neither my own flow nor the tools I'm standing on are allowed to report a false PASS to me. In the next post I want to lay that principle out in full: why, in an IC flow handed to AI, the thing you most need to guard against is never "can't compute it," but "pretending it computed it."