# PCB Component Placement Guidelines From the Netlist Graph

*Published: 2026-09-29 | Author: Jason Ratzlaff*

**PCB component placement** should follow the netlist, not the schematic page or your eye. Treat the board as a graph of which parts talk to which, give every signal net a weight, and move parts until the total weighted wirelength is as small as it can be. Keep decoupling caps attached to the IC they serve and treat big parts as fixed obstacles. Do that and routing becomes a set of short, uncrossed connections instead of a tangle.



I’m Jason Ratzlaff. I design boards and the software that runs on them, and placement is the step I used to lose the most time on. Before I route a single trace, the positions I pick have already decided how long every net will be, how many vias I’ll need, and whether an autorouter can finish at all. So I wrote down the rules I apply by hand, turned them into math, and published the result as [kicad-fluxplace](https://github.com/parkktech/kicad-fluxplace), an MIT-licensed KiCad plugin and command-line tool. This post covers the rules, the objective behind them, what the tool reports, and where it still needs an engineer.

PCB Component Placement Guidelines: Why Placement Decides Routing Quality
-------------------------------------------------------------------------

Most PCB design tips focus on routing. That work matters, but it’s downstream. A trace can only be as short as the gap between its two pads, and you set that gap during placement. Put a memory bus’s controller on the wrong side of the board and no routing skill gets that length back. Scatter a regulator’s input cap, inductor and output cap and the hot loop is large before you draw any copper.

### Placement is an optimization problem with a measurable objective

Once you accept that, placement stops being taste and becomes something you can measure. The standard measure is **half-perimeter wirelength (HPWL)**. For each net, draw the smallest rectangle that contains all of its pads and take half its perimeter. Add that up across every net and you have one number that tracks how much copper the board will need. The fluxplace README states the goal plainly: minimise the summed span of every net. The only way to shrink it is to pull communicating parts together.

Placing by eye

 schematic order, board edges, habit

ObjectiveLooks tidy

Power and groundTreated like any other net

Decoupling capsWherever there was room

Large modulesDropped first, everything piles around them

RepeatableNo



Placing from the netlist graph

 how fluxplace works

ObjectiveMinimum weighted HPWL

Power and groundPlanes, not springs

Decoupling capsOwned by one IC, smallest closest to the pin

Large modulesKeep-outs; connected parts anchor to real pads

RepeatableSame board in, byte-identical placement out





How to Place Components on a PCB From the Netlist Graph
-------------------------------------------------------

The netlist already contains everything a placer needs to know about who talks to whom. Every net is a group of pads that must be connected; every part is a node. Turn that into a weighted graph and the placement problem becomes: find positions for the nodes that make the heavy edges short.

### Build the communication graph, and leave power out

The first rule is the one naive placers break. If you include ground and the main supply rails in the graph, every part on the board is connected to every other part through them. The strongest attraction on the board becomes “be near the CPU’s ground pins”, and the whole layout collapses into a blob around one chip. The structure you actually care about, which subsystem feeds which, disappears.

fluxplace splits nets three ways before it builds anything. Ground and high-fanout supply nets are recognized by name and fanout and handled as planes, which is what they’ll be in copper. Small power hops with only a few parts on them, like a converter feeding one load, stay in as real traces that need width. Everything else is a signal net and becomes a spring. Passives are then collapsed into edges, so a series resistor between two ICs reads as a connection between those ICs rather than a separate node pulling on both.

![Illustration comparing a placement where ground is treated as a net, collapsing all parts onto the hub IC, with one where ground is a plane and weighted signal nets keep the board structure](https://www.parkktech.com/wp-content/uploads/2026/09/placement-graph-ground-plane-illustration.png)Illustrative. Left: ground counted as a net pulls every part onto the hub. Right: ground as a plane and weighted signal springs keep each branch in its place.### Minimize weighted wirelength (HPWL)

With the graph built, the objective is weighted HPWL: each net’s half-perimeter multiplied by how much that net matters. A quadratic formulation is the classic way to solve it fast. Treat each connection as a spring whose energy grows with the square of its length and the minimum-energy layout comes out of one linear solve. The hub IC lands at the weighted average of everything it talks to. It ends up central because of the math, not because someone pinned it there.

Weighting Nets: Diff Pairs, Point-to-Point Links and Buses
----------------------------------------------------------

An unweighted graph treats a stray GPIO the same as a PCIe lane. That’s wrong, and the README says it directly: the weighting is the intelligence. The weights in the published code are simple, and you can read them in `net_weight()` in `fluxplace/graph.py`:

- **High-speed and differential-pair nets** (recognized by name) get a base weight of 4.
- **Tight point-to-point nets** with three or fewer parts, such as a signal and its series resistor or a clock, get 2.
- **Everything else** gets 1.

Each base weight is then divided by (fanout − 1). Without that step a 20-part net would dominate the layout simply because it has so many pairwise edges. With it, a wide bus pulls with roughly the same total force as a short link, spread across its members.

![Line chart of spring weight per pair of parts versus net fanout for high-speed nets, point-to-point nets and other signal nets, computed from net_weight in fluxplace graph.py](https://www.parkktech.com/wp-content/uploads/2026/09/fluxplace-net-weights.png)Computed from `net_weight()` in the public fluxplace source. Power and ground nets are not springs, so they don’t appear.**Weights are where your engineering judgment goes.**The solver is general. What makes the result look like a board an engineer placed is deciding which nets should pull hardest and which nets shouldn’t pull at all.



![Blue circuit board](https://images.unsplash.com/photo-1562408590-e32931084e23?ixid=M3w4ODMzNjJ8MHwxfHNlYXJjaHwxfHxjaXJjdWl0JTIwYm9hcmQlMjBjb21wb25lbnRzJTIwY2xvc2V1cHxlbnwxfDB8fHwxNzkwNjY5MDM5fDA&ixlib=rb-4.1.0&w=1520&q=80&fm=jpg&fit=crop&ar=16:9)Photo by [Umberto](https://unsplash.com/@umby?utm_source=parkk_blog&utm_medium=referral) on [Unsplash](https://unsplash.com/?utm_source=parkk_blog&utm_medium=referral)PCB Decoupling Capacitor Placement: Keep Caps With Their IC
-----------------------------------------------------------

Decoupling is the placement rule everyone knows and a naive optimizer breaks. A bypass cap connects to a power rail and ground and nothing else. Once you remove power and ground from the graph, as you should, the cap has no springs left. An optimizer that only reads the signal graph will leave it wherever it lands, usually far from the pin it’s supposed to serve.

### How close should decoupling caps be?

As close to the power pin as the layout allows, with its ground connection going straight to the plane. A cap’s job is to supply fast current transients locally, and any trace length between the cap and the pin adds inductance to that current loop. The goal is the smallest possible loop from the pin, through the cap, to the ground return. That means the cap sits beside the pin on the same side of the board, with vias at the pads instead of a long trace to reach one.

### One owner per cap, smallest cap closest

fluxplace deals with this explicitly instead of hoping the math works it out:

- **Clusters come from schematic sheets.** A cap drawn on the same sheet as its IC stays in that IC’s cluster. If the board has no schematic, clusters come from topology branches with nearest-branch assignment, so caps still don’t end up stranded.
- **Every bypass cap gets one owner:** the nearest IC on the shared rail.
- **Capacitance rank decides order.** The smallest cap, the one handling the highest frequencies, goes closest to the pin.
- **Plane-only decaps walk to their IC’s side** after the routability gate passes, and the move is reverted if the gate objects.

The same engine keeps crystals with their series resistor and load caps, and keeps a switching converter’s controller, inductor and ceramic caps in a tight hot loop. Each rule is graded after placement (`eval --prc`), so you get a pass or fail instead of “looks close enough”.

Treat Large Parts as Obstacles, Not Points
------------------------------------------

A force-directed placer that models every part as a point makes a mess of big modules. It pulls everything connected to a compute module or an M.2 socket toward that module’s center, and those parts pile up on top of it. Real parts connect at pads on the module’s edge, and nothing can sit under its body.

fluxplace treats large parts as keep-outs with locked orientation. The parts connected to them anchor to the *actual pad* on the perimeter through pin-aware springs, so a USB connector’s ESD part lands next to the pins it protects, not at the module’s center. Edge connectors are fixed on the board perimeter. In the route-aware strategy, big modules are still movable, but they’re pulled into position by their heaviest nets and moved as one rigid object.

Small parts snap to 0, 90, 180 or 270 degrees for simple pick-and-place, and the board outline shrink-wraps the placement so you quote the smallest board that fits.

Does KiCad Have Auto Placement? The KiCad Auto Placement Plugin
---------------------------------------------------------------

Current KiCad releases give you excellent manual placement tools, but no netlist-driven placer that optimizes for routability. That gap is why people search for a KiCad auto placement plugin. fluxplace runs two ways from the same core: inside the PCB editor under Tools, External Plugins, and as a headless CLI for scripts, CI or an AI agent. The core doesn’t depend on pcbnew. Only one module, `kicad_io.py`, touches KiCad, which keeps the placement code unit-testable.

### The build strategy: route-aware placement

The strategy the GUI plugin runs is `build`. It places the way I do by hand: get a rough mental map, place parts one by one, check whether the board routes, then tighten it.

![Four-stage diagram of the fluxplace build strategy: mental map quadratic solve, hands placing parts one at a time, gate global router check, and search shrinking the board](https://www.parkktech.com/wp-content/uploads/2026/09/fluxplace-build-pipeline.png)The four stages of `build`, summarized from the fluxplace README.1. **Mental map.** A quadratic solve over pad positions gives every part a target position. The hub lands centrally because of the weights.
2. **Hands.** Parts are committed one at a time: the hub first, then whichever part has the strongest ties to the parts already placed. Each part tries candidate spots near its target, and each spot is scored by estimating its real traces on a routing grid. The winner’s nets are routed with congestion-negotiated A\* and reserved, so parts placed later can’t block them.
3. **Gate.** A separate coarse global router routes the whole board. Zero overflow means the board is globally routable. If there’s overflow, parts near the congested cells get more spacing and the board is re-legalized. Routability beats density every time.
4. **Search.** Once the gate passes, a binary search shrinks the board to the smallest scale that still routes, re-checking the gate at each step. With `--seeds N`, it also tries perturbed variants and keeps the best routable one.

### Other placement strategies

StrategyWhat it doesUse when`build`Quadratic solve, place-and-route builder, global-router gate, congestion feedback. Won’t return an unroutable board.You want the best result`quad`Analytic quadratic placement with SimPL spreading, no router in the loopYou want a fast hub-central layout`pack`Cluster, pack each cluster in signal order, bin-pack clusters by connectivity, compact. CLI default.You want organized and compact without the router`flux`Pin-aware force-directed; every pad pulled to its net centroidLegacy mode, dense but pushes the hub aside`radial`Hub in the center, branches radiating to edge connectorsYou want a clean first-pass structure

Every strategy is deterministic. The same board in gives a byte-identical placement out, so you can diff results and keep them in version control.

Results: What the fluxplace README Reports
------------------------------------------

I only quote numbers the public README publishes. It reports results on one test board: a topology-blind starting placement compared with fluxplace’s output, keeping the main module clear and each subsystem in its own zone. The README also shows the output line from an example `place` run with the `pack` strategy.

**~50%**less weighted wirelength*test board, vs topology-blind placement*

**~28%**smaller board area*same test board*

**-37%**HPWL in the example run*26,349 mm to 16,627 mm, pack strategy*

0overlaps after placement*same example run*



Total half-perimeter wirelength, example place run

Output of `cli.py place --strategy pack --rotate ortho` as printed in the kicad-fluxplace README (mm)

BeforeAfter

Total HPWL26,349 mm**16,627 mm**



![Bar chart of total half-perimeter wirelength before and after fluxplace in the README example run: 26,349 mm before, 16,627 mm after, a 37 percent reduction](https://www.parkktech.com/wp-content/uploads/2026/09/fluxplace-hpwl-example.png)Numbers from the example output in the [kicad-fluxplace README](https://github.com/parkktech/kicad-fluxplace).Read these for what they are: results on one board, measured with the tool’s own objective. The README says lower HPWL from `eval` correlates directly with higher autoroute completion. It also includes a `calibrate` command, which exports a Specctra DSN, runs Freerouting, and reports whether the internal gate agrees with a real autorouter on your board. That’s the check I’d run before trusting any placer’s claims on your own layout.

How to Install and Try the KiCad Plugin
---------------------------------------

fluxplace targets KiCad 10 and needs numpy. Routing adds Java 17 and Freerouting 2.3.0 or later; the README warns that 2.2.4 fails silently on headless jobs.

1. **Clone the repo into KiCad’s third-party plugin folder.** On Linux that’s the `3rdparty/plugins` folder inside `~/.local/share/kicad/10.0/`; the README lists the Windows and macOS paths. You can also add the repo’s `metadata.json` to the Plugin and Content Manager for one-click installs and updates.
2. **Run the preflight.** `python3 cli.py doctor` checks every requirement and tells you what’s missing; `--install` installs what it can. Use the Python that can import `pcbnew`. On Linux that’s the system interpreter, and a venv made with `--system-site-packages` keeps that access while letting you install extras.
3. **Restart KiCad** and open Tools, External Plugins, fluxplace. The plugin runs the same check the first time you use it.
4. **Or go headless:** analyze, place and evaluate from the command line, then autoroute.

Terminal: plan, place and score a board with the fluxplace CLI```
export KP=/usr/lib/python3/dist-packages   # where pcbnew.py lives
PYTHONPATH=$KP python3 cli.py analyze --board board.kicad_pcb
PYTHONPATH=$KP python3 cli.py plan    --board board.kicad_pcb --out PLACEMENT-PLAN.md
PYTHONPATH=$KP python3 cli.py place   --board board.kicad_pcb --strategy pack --rotate ortho \
                                      --out board.placed.kicad_pcb
PYTHONPATH=$KP python3 cli.py eval    --board board.placed.kicad_pcb
```

`analyze` prints the communication map: the hub, forks, branches, and a lint of floating parts. If the hub it names isn’t the part you’d call the hub, fix your net names before placing. To autoroute afterward, export a Specctra DSN, run Freerouting headless, and import the session file back into KiCad.

Limitations: PCB Placement Best Practices That Still Need You
-------------------------------------------------------------

An optimizer only knows what the netlist and the constraints tell it. A good placement still depends on things an engineer has to supply.

**A placer optimizes the objective you give it, not the product you meant.**Mechanical fit, enclosure features, thermal paths, connector positions set by the housing, and anything your net names don’t reveal are yours to supply as fixed parts, rule areas or outline limits.



- **Net names carry meaning.** High-speed nets, diff pairs and power rails are all detected from naming conventions. A pair named `SIG_A` and `SIG_B` won’t be treated as a pair. Use conventional names or the weighting can’t help.
- **Mechanics come first.** Mounting holes, connector positions set by the enclosure, and tall parts under a lid aren’t in the netlist. Lock them before you run a placer. The `compact` command honors KiCad rule areas and hard outline bounds, and it fails loudly if the parts don’t fit.
- **Thermal and analog isolation are separate problems.** Wirelength doesn’t know a regulator runs hot or that a sensitive analog front end should sit away from a switching node. Handle those with keep-outs and zones.
- **HPWL isn’t signal integrity.** Shorter is usually better, but impedance, return paths, stackup and length matching are still routing and review work. fluxplace has a separate `review` gate and length-tuning commands for that; placement doesn’t replace them.
- **Published results come from one test board.** The ~50% and ~28% figures are what the README reports for that board. Your board will differ, which is why `eval` and `calibrate` exist: measure your own before and after.

Here’s how I use it. I lock the mechanical parts, check that `analyze` finds the right hub, let `build` produce a routable, compact layout, and then spend my time on the parts of the board that need judgment. That’s a better use of an engineer’s afternoon than dragging 0402 caps around the board.

Frequently Asked Questions
--------------------------

What are the most important PCB component placement guidelines?Place parts that share signal nets next to each other, weighting high-speed and differential pairs most heavily. Keep each decoupling cap beside the power pin it serves, keep crystals and converter hot loops tight, and fix connectors and large modules first. Treat power and ground as planes rather than as nets that pull parts together.

How close should decoupling caps be to an IC?As close to the power pin as the layout allows, on the same side of the board, with vias at the cap's pads going straight to the ground and power planes. Any trace between the cap and the pin adds loop inductance. When an IC has several caps, the smallest value goes closest to the pin.

Does KiCad have auto placement?Current KiCad releases give you good manual placement tools but no netlist-driven placer that optimizes for routability. Plugins fill that gap. kicad-fluxplace is an open-source KiCad 10 plugin and CLI that places parts by minimizing weighted wirelength and checks routability with a global router.

How do I install a KiCad plugin?Clone or copy the plugin into the 3rdparty/plugins folder in KiCad's user directory (under ~/.local/share/kicad/10.0 on Linux) and restart KiCad. It then appears under Tools, External Plugins. Plugins that publish a metadata.json can also be added as a repository in the Plugin and Content Manager for one-click installs and updates.

What is HPWL in PCB placement?HPWL, half-perimeter wirelength, is half the perimeter of the smallest rectangle that encloses all of a net's pads. Summed across every net, it is a fast estimate of how much copper a placement will need. Placers minimize a weighted version of it, so the critical nets count for more.

Why should power and ground nets be excluded from a placement graph?Nearly every part connects to ground and the main rails. If those nets pull like signal nets, every part is drawn toward the biggest chip's ground pins and the layout collapses into one blob. Handling them as planes keeps the real signal structure intact.

Is automatic PCB placement better than manual placement?It's better at the part that is pure math: shortening weighted wirelength, packing clusters and checking routability, and it gives repeatable results. It doesn't know about enclosures, thermal paths or analog isolation, so an engineer still locks mechanical parts, sets keep-outs and reviews the result.



Need a board designed, placed or reviewed?
------------------------------------------

I design hardware and the software that runs on it: schematics, PCB layout, fab-ready packages, and edge-AI systems. If you have a board that won’t route or a product that needs one, let’s talk.

[Start the conversation](https://www.parkktech.com/contact/)

---

**Parkk Technology** — Custom Software Development, AI Integration, and Equity Partnerships

- Custom Software Development: We build the software your business actually needs — scoped, shipped, supported.
- AI Integration for Existing Businesses: Add AI capabilities to what you already have — without rebuilding everything.
- Equity Partnership: Considered case by case for validated problems. No fixed package.

Contact: https://www.parkktech.com/contact | Author: Jason Ratzlaff, founder of Parkk Technology