Macro Placement on the IBM/ICCAD04 Benchmarks

Adam Holmes · code on GitHub

A chip is millions of tiny logic cells plus a few hundred big fixed blocks — memory units and other prebuilt components. Macro placement is deciding where those blocks go, and it largely sets how good the finished chip is. This is my solver for a benchmark challenge that grades each placement with one number — mostly wirelength, plus density and routing congestion; lower is better, no blocks may overlap. Each animation replays one complete run: the reference placement the benchmark comes with (left), my placer working (middle) — spreading, legalizing, then improving — and the score per frame (right; dashed line = reference). Blocks are rectangles, cell clusters are dots.

ibm01: reference | optimization | score curve ibm09: reference | optimization | score curve ibm17: reference | optimization | score curve ibm18: reference | optimization | score curve

Result. Starting from random placements, with one hour per benchmark, my placer averages 0.9758 across all 17 — 34% below the provided reference placements (avg 1.477; the RePlAce academic tool scores 1.458, simulated annealing 2.125) — beating the reference on every design with zero overlaps, verified on the official scorer. The hour is measured strictly: a hard wall clock covering everything, run on hardware slower than the competition machines — so the budget claim is conservative.

per-benchmark comparison

How it works

The score is 1.0·wirelength + 0.5·density + 0.5·congestion. The core idea is to combine a smooth global optimization of a differentiable proxy with simulated annealing using the full, non-differentiable loss — two optimization stages, with a legalization step in between, all scheduled into one hour:

The tuned configuration

About fifteen hyperparameters, tuned by Bayesian optimization on 3 designs (easy / medium / hard) and reported on all 17; the other 14 are held out. Configurations are always compared on paired random seeds, so I wasn't comparing lucky runs — single-seed differences are mostly luck.

settingvalue
wirelength smoothing2.44 (lower = closer to exact wirelength)
schedule back-loading3.99 (spread early, tighten late)
density weight (final / start)0.074 / ~3% of it  ·  target fill 0.65
wirelength weight at start73% of full  ·  learning rate 0.39
overlap tolerancedeep-overlap penalty off for the first 6% of the run, full by 65%
block swapssame-size pairs swapped under annealing, first third of the run
gradient steps15,000 per placement
local-search temperature3×10⁻⁴ cooling to 10⁻⁶  ·  200–250k moves per pass
proposal mix25% optimal-location · 20% route-shift · rest small random steps
configuration search

The configuration search: score vs. trial. It plateaus once differences between good configurations fall below run-to-run noise.

What I learned

Appendix — what didn't work

Each verdict comes from experiments run with identical random seeds in both arms, so noise cancels.