Standalone differential-pair length matching for routed PCB traces.
import { LengthMatchingSolver } from "@tscircuit/length-matching-solver"
const solver = new LengthMatchingSolver({
hdRoutes,
originalConnections,
differentialPairs,
})
solver.solve()
const { matchedHdRoutes } = solver.getOutput()The solver adds obstacle-aware, tapered multi-lobe meanders until each
differential pair is within its configured length tolerance. It normally tunes
only the shorter connection. When realizing the correction would require a
tooth shallower than minMeanderHeight, it can add a jointly validated meander
to each pair member instead of weakening the geometry constraint. For a
multi-segment match, every selected segment uses the same tooth count,
placement, and tapered profile. Invalid or impossible solver states throw with
a specific error instead of returning partially matched routes.
PostProcessingSolver accepts and returns native high-density routes, so an
autorouting pipeline does not need to serialize routes before post-processing:
import { PostProcessingSolver } from "@tscircuit/length-matching-solver"
const solver = new PostProcessingSolver({
hdRoutes,
differentialPairs,
obstacles,
bounds,
layerCount,
// routingGrid: { innerGridStep: 0.25 },
})
solver.solve()
const { hdRoutes: postProcessedHdRoutes } = solver.getOutput()Pair members resolve by connectionName or rootConnectionName and must each
identify exactly one route. Unsupported or ambiguous geometry throws. Input,
immutable non-pair routes, and returned outputs are independently cloned.
In open routing space, the solver prefers broad, shallow tuning distributed over the available baseline instead of a narrow, deep hairpin. It evaluates a maximally relaxed pitch, an intermediate pitch, and the minimum-clearance pitch for each tooth count. Keeping the compact option allows the same search to work in constrained regions.
The quality score uses geometry-only electrical-risk proxies: depth-to-pitch aspect ratio, added-length density, deviation from the intended depth profile, bend count, and detour severity. It does not calculate impedance, inductance, or propagation delay; those require a PCB stackup and signal information that are not solver inputs. See Meander electrical-quality heuristic for the rationale, exact scoring model, limitations, owning files, and tests.
| Input | Default and meaning |
|---|---|
maximumMeanderDepth |
5 mm maximum normal excursion. |
maxToothCount |
12 teeth per candidate. |
minimumToothPitch |
Optional lower bound, not a fixed requested pitch. |
minMeanderGap |
Greater of 0.3 mm and twice the trace width. |
minMeanderHeight |
Trace width plus the resolved meander gap. |
The actual minimum pitch is the greater of minimumToothPitch and twice the
resolved centerline spacing. Public input types are documented in
lib/length-matching/types.ts.
Algorithm ownership and data flow are indexed in
lib/length-matching/README.md. Visualization
has a separate code map.
bun install
bun run start
bun test
bun run buildbun run start opens the interactive React Cosmos fixture playground at
http://localhost:5000.