A Floorplan Without the Village

Six steps. Four binaries. No container, no Tcl, no orchestrator. And on the one block we can check against a taped-out design, the rows and tracks match exactly.

August 31, 2026 • By Shivaram Mysore


To get a floorplan out of an open flow today, you install the flow. All of it. The orchestrator, the Python environment it wants, the tool binaries it drives, the container that holds the arrangement together. Then you write a configuration, run the flow, and wait — and what you wanted was to know whether your die was big enough.

That is not anybody's fault. It is what happens when the only way to reach a step is through the machinery built to sequence every step. But it sets a floor on how cheaply you can ask a question, and the floor is high enough that people stop asking.

We have been building the floorplan stage as individual engines. They are now far enough along to run as a chain on their own:

              The usual arrangement

  netlist ──► [ orchestrator + Python + Tcl + container + tools ] ──► floorplan


              This

  netlist ──► import ─► ifp ─► make-tracks ─► tap ─► global-connect ─► pdn ──► floorplan
              └───────────────── four static binaries ──────────────────┘

Six logical steps, implemented by four static binaries. Two of them carry more than one stage — ifp builds the rows and the tracks, pdn connects the supply nets and then builds the grid — but every stage stays independently invocable, which is the property that matters. Nothing here starts a container, sources a Tcl script, or needs anything from PyPI.


What it actually does

Each step is an ordinary command that reads a design database and writes one back:

  • import builds a database from LEF and a gate-level Verilog netlist.
  • ifp turns the die rectangle into a floorplan — core area snapped to the site grid, and the rows every later stage places into.
  • make-tracks lays the routing tracks from the technology's own pitches and offsets.
  • tap cuts the rows around macros and places the well taps and endcaps.
  • global-connect creates the supply nets and connects every cell's power pins to them.
  • pdn builds the grid: follow-pin rails, straps, and the vias that stitch the layers together.

The final output is a DEF. What is not in that list matters as much as what is: placement, clock-tree synthesis and routing are not here. This is the floorplan, and calling it anything more would be a claim we cannot support.


Checked against a real tapeout, not against itself

A tool agreeing with itself proves nothing, so we ran it on a design that has been fabricated.

The Vyges edge-sensor SoC is a taped-out sky130 chip, and its repository ships every block's gate-level netlist, its signed-off configuration, and — for one block — the DEF that went to fabrication. Every number the flow uses is read from that configuration: die area, site, PDN layers, widths, pitches, offsets. The script chooses nothing.

All seven blocks complete the floorplan stage cleanly:

Block Design cells Rows Components out Power shapes Vias
edge_sensor_glue 301 212 5,540 229 2,588
rv_core_ibex_tlul 943 506 29,133 543 13,851
xbar_main 2,314 396 19,822 425 8,435
rv_plic_lite 3,281 139 5,674 150 1,063
spi_host_lite 7,868 175 11,492 189 1,869
uart 13,363 249 20,512 268 3,416
fft_ctrl_tlul 14,207 543 42,270 581 14,042

Design cells are what the netlist contains. Components out is what the DEF contains afterwards — the design plus the well taps and endcaps this flow inserts, which is most of the difference. rv_plic_lite goes from 3,281 to 5,674 because tap placed 2,393 physical cells into it.

For fft_ctrl_tlul, the largest of them, the taped-out DEF is in the repository — so the flow finishes by comparing its own floorplan against the physical implementation that went to fabrication. All 543 rows and all 12 DEF track statements are identical.

Rows and track statements are the right things to compare that way, and they are the only ones. They are settled at floorplan and never move afterwards, so they survive intact into a fully routed DEF. Components and power shapes do not: placement, CTS and routing all change them. Claiming a match on those would be measuring the wrong thing.

The comparison is a real gate, not a decoration — it exits non-zero on a mismatch. It earned that during development, when a coordinate formatter rendered 1294.48 as 1294 and moved the floorplan half a micron. Nothing else in the flow noticed. The check failed immediately.


Or start from nothing

Matching a tapeout proves the engine agrees with a known-good answer. It is not, though, what you would use this for. Most of the time the floorplan does not exist yet — you have a netlist and a rough idea of how big the block wants to be, and the question is what happens if it were smaller.

Give it a netlist and a die and it builds one:

./flows/floorplan.sh --netlist build/my_block.v --die-area '0 0 600 600'

That is the whole input. The core comes from the die inset by the margins, the tracks come from the technology's own pitches, and the rest follows. Here is the same 13,363-cell block at four die sizes, nothing changed between runs but the rectangle:

Die Rows Effective utilization Wall clock
500 × 500 175 0.583 10.8 s
600 × 600 212 0.399 12.0 s
700 × 700 249 0.291 12.8 s
900 × 900 322 0.174 16.5 s
   500×500     600×600     700×700     900×900
      │           │           │           │
    0.583       0.399       0.291       0.174     effective utilization
      └───────────┴───────────┴───────────┘
                 52 s of compute, total

Four floorplans in under a minute of total compute. That is a different activity from running a flow: you are not committing to a configuration, you are looking at four of them.

Ask for one that cannot work and it says so with a number rather than an opinion. At 300 × 300 the same block reports an effective utilization of 1.692 — the cells require more area than the available core. It does not refuse, and it does not quietly grow the die. It builds what you asked for and hands you the figure that tells you it will not place.

The same standalone approach makes power-grid exploration cheap too. Same die, three strap pitches:

Strap pitch Power shapes Vias
40 µm 270 9,673
80 µm 242 4,899
153.6 µm 229 2,588

A tighter grid is more robust and costs routing resource, and here the trade is a number you can see before anything downstream depends on it.


Seconds, not stages

rv_plic_lite takes 1.6 seconds. fft_ctrl_tlul, at 14,207 cells, takes 36 seconds. Every timing here is single-threaded on one core of a Xeon E5-2699 v4 at 2.20 GHz running Ubuntu 24.04 — a 2016 server part, not a fast modern laptop.

Those numbers are what makes the sweeps above ordinary rather than an exercise. There is no batch to submit and no run directory to go back and read: you change a margin, rerun, and look.

Install is one command. The whole suite — 28 engines, sign-off and construction together — is a 23 MB download. The four this flow needs come to 7.7 MB. There is nothing else to stand up.


Run it yourself

The scripts are public, in the Vyges Loom testbench under flows/. There are two, and the split is deliberate.

floorplan.sh is the tool. Point it at your own netlist:

vyges install physical && vyges install loom
export PATH="$HOME/.vyges/bin:$PATH"

./flows/floorplan.sh --netlist build/my_block.v --die-area '0 0 700 700'

If you do not have the CLI yet, installing it is the one step before this.

The PDK is resolved through vyges pdk-store, so the script contains no vendor-specific directory layout. --pdk selects any registered PDK and --library selects any library in it, including a library you cannot redistribute.

edge-sensor-demo.sh is the worked example. It reads a taped-out block's configuration and calls the same script:

git clone --depth 1 https://github.com/vyges/vyges-edge-sensor-soc
./flows/edge-sensor-demo.sh --repo vyges-edge-sensor-soc --design fft_ctrl_tlul

The demo runs the developer's code path rather than a parallel copy of it, which is why the formatter bug above showed up somewhere it could be caught. The design repository is only ever read — it is a fabricated design, and nothing writes into it.


What this is not

It is not a place-and-route flow. Placement, CTS and routing remain the flow's job.

It is not a claim that the flow is unnecessary. An orchestrator sequences steps, manages state, and handles the parts of a tapeout that are genuinely about coordination. What has changed is that reaching one stage no longer requires all of it.

It is not a claim that the whole floorplan matches silicon. What is compared are the rows and the track statements — the parts of a floorplan that never move again once set. That is a narrower claim than "matches the tapeout", and it is the one the evidence supports.


Why we are showing it this way

Everything we have published about these engines until now has gone through vyges mcp — an AI agent choosing tools from their descriptions and driving them. That remains the more interesting demonstration.

This one is a shell script on purpose. A flow you can read top to bottom, run, and diff against a real tapeout is a different kind of evidence from a model doing it for you: it is checkable by anyone, in the form engineers already trust. The agent story is better when the thing underneath it is boring enough to verify by hand.


Try the floorplan flow: the scripts · install the CLI, then vyges install physical · the Loom engines