Floorplanning

Before a single one of your million standard cells is placed, someone has to decide the shape of the world they will live in. That is floorplanning — the city planning of chip design. How big is the die, and what aspect ratio? Where do the roads (routing resources) run? Where do the big immovable buildings go? Which districts talk to which, and should they be neighbours?

It is the highest-leverage step in the entire back-end, and the least automatable. A good floorplan makes every later stage — placement, clock trees, routing, timing closure — merely difficult. A bad floorplan makes them impossible, and here is the brutal part: you usually find out weeks later, when routing fails, and the only fix is to come all the way back and start again. A bad floorplan cannot be routed out of.

The pieces of a floorplan

A floorplan, step by step

Here is the whole discipline in one picture — watch the order: outline, doors, boulders, rows, flow.

Utilization: why you must not fill the box

The core utilization is the fraction of the core area actually covered by standard cells:

\text{utilization} = \frac{\text{total cell area}}{\text{core area}}.

Targets sit around 70–80%, and the missing 20–30% is not waste — it is breathing room. Routing needs empty space to drop vias and jog wires; the clock tree will insert thousands of buffers that do not exist yet; timing fixes will upsize cells; engineering changes will add logic late. Push utilization to 95% and placement still succeeds — then routing jams, like a city that paved over every park and wonders why traffic cannot move. Dense regions also concentrate power draw, which the power grid must survive.

Two macros placed close together create a channel — a corridor whose width caps how many wires can cross between them (width ÷ track pitch = tracks). Too narrow a channel is a routing dam. The alternative is abutment: push the macros flush against each other and route around the pair entirely — a deliberate choice that no wires shall cross there.

Try it: utilization and a greedy macro placer

Floorplanning tools score candidate macro positions by (among much else) the total wirelength implied by how strongly each macro talks to its neighbours. Here is a toy version: a utilization check, then a greedy placer that drops three macros onto a grid, each minimising connectivity-weighted Manhattan wirelength to what is already placed:

// ── Utilization check ── const coreArea = 4.0; // mm² const cellArea = 3.1; // mm² of standard cells const util = (cellArea / coreArea) * 100; console.log(`Utilization: ${util.toFixed(0)}% ` + (util > 85 ? "→ routing will jam!" : "→ healthy, room to route")); // ── Greedy macro placement on a 10×10 grid ── // The IO sits at (0,5). Weights = how much traffic each pair exchanges. interface Macro { name: string; wires: [string, number][]; } const placed: { [name: string]: [number, number] } = { IO: [0, 5] }; const macros: Macro[] = [ { name: "CPU", wires: [["IO", 2]] }, { name: "RAM0", wires: [["CPU", 8]] }, // talks heavily to CPU { name: "DMA", wires: [["IO", 5], ["RAM0", 3]] }, ]; const dist = (a: [number, number], b: [number, number]) => Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]); for (const m of macros) { let best: [number, number] = [0, 0]; let bestCost = Infinity; for (let x = 0; x < 10; x++) { for (let y = 0; y < 10; y++) { const spot: [number, number] = [x, y]; if (Object.values(placed).some((p) => dist(p, spot) === 0)) continue; let cost = 0; for (const [other, w] of m.wires) cost += w * dist(placed[other], spot); if (cost < bestCost) { bestCost = cost; best = spot; } } } placed[m.name] = best; console.log(`${m.name.padEnd(4)} → (${best[0]},${best[1]}) weighted wirelength ${bestCost}`); } console.log("Heavy talkers end up adjacent — that is the whole game.");

Real floorplanners search far more cleverly (and juggle timing, power and routability at once), but the objective survives intact: blocks that talk a lot go near each other. The IO logic hugs its pads; a cache hugs its CPU; and the wire bill falls before routing even begins.

If routing is jammed and utilization is high, surely the fix is a few more square millimetres of silicon? Sometimes yes — and it is one of the most expensive sentences a designer can utter. Die cost rises faster than area: you get fewer dice per wafer, and a larger die is more likely to catch a killer defect, so yield falls too — a double penalty that a later lesson quantifies with a merciless exponential. At volume, one square millimetre can be worth millions of dollars a year. This is why floorplanning is a negotiation: the physical designer wants space, the product manager wants the die small, and the floorplan is the treaty they sign.

The classic rookie floorplan puts a big SRAM macro dead centre — it looks tidy, like a courtyard building. It is a disaster. Routing flows across the core like a river system, and a central macro is a dam: every east–west and north–south net in its shadow must detour around it, piling congestion onto the corridors along its edges. The standard discipline is the opposite: macros go to the edges and corners, backs against the wall, pins facing inward toward the logic that uses them — keeping the centre of the core an open, routable sea. (Like most rules it can be broken knowingly — but never accidentally.)