Skip to content

Latest commit

 

History

223 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@tscircuit/fanout-solver

BGA fanout preprocessor for SimpleRouteJson.

FanoutSolver routes every connected package pad to one shared breakout boundary before the general-purpose autorouter runs. It can put a small escape via in a pad-to-pad channel or move an oversized via diagonally into the interstice between four pad corners. It routes every member of a bus in the same direction and treats each bus-layer decision atomically.

Behavior

  • Uses SimpleRouteJson.buses when present. It also understands a point busId and names such as BUS_DDR_01.
  • Detects rectangular pad footprints through obstacle componentId metadata, including perimeter packages and two-pad passives.
  • Handles multiple mixed footprints inside one shared breakout boundary.
  • Routes perimeter and inner-matrix pads.
  • Uses sharedBoundary as the common exit rectangle. Without one, it infers a shared rectangle around the source footprints selected for the buses, without expanding that boundary to include destination footprints.
  • Ends every fanout trace exactly on its selected sharedBoundary edge. Border distribution and lane spreading happen inside the rectangle, never after the trace has crossed the boundary.
  • Infers one outward direction per bus from the bus endpoints, or accepts an explicit direction override.
  • Accepts an additive preferredExit bus field for a particular edge (left, right, top, or bottom) or corner (top-left, top-right, bottom-left, or bottom-right). A corner chooses a compatible adjacent edge and reserves the bus at that end of the border.
  • Accepts an unambiguous exitPosition bus field when the local pad escape and final boundary edge differ. For example, rightside_top escapes locally upward into the upper band and terminates on the right boundary, while topside_right escapes locally rightward and terminates on the top boundary.
  • availableCornersAndSides can restrict every boundary-terminated bus to named regions of the shared boundary. For example, ['top_left', 'top_middle', 'top_right'] allows only top-edge exits; top is an alias for top_middle (with matching aliases for the other edges).
  • borderDistribution: "even" uses outward-only shoves to equalize under-filled gaps across the occupied border interval while preserving bus order, existing wider corridors, and trace/clearance pitch. The default "preserve" mode stays source-aligned.
  • Supports balanced nearest-edge partitioning for package breakouts. Ties alternate instead of favoring one axis; square grids distribute equally across north, south, east, and west.
  • Enumerates combinations of the copper layers implied by layerCount.
  • Keeps a bounded beam of route alternatives for multi-connection buses, so grouped power/signal lanes can backtrack across layer and track choices before committing a prefix.
  • For dense fields with competing constrained layers, reserves every signal and plane source escape before routing complete bus groups. Boundary repairs keep exact exits and existing vias fixed; a blocked group can use its source layer for transit when that layer is explicitly permitted for every bus in the group.
  • Keys route-prefix caches by both bus and layer, preserving plan uniqueness when grouped-layer search changes bus order.
  • Prefers depth-cycled layer assignments: matching north/south (or east/west) bus depths share a layer, and deeper pairs cycle through every available escape layer. This forces a small stackup to reuse routing channels.
  • Keeps outward-edge buses on their source layer when possible. If a bus needs a via, every connection in that bus receives one and moves to the same assigned layer; mixed via use within a bus is never committed.
  • Accepts a bus-level termination target. The default { type: "boundary" } preserves the ordinary breakout contract, while { type: "plane", layer: "inner1" } escapes each source pad to a legal local via and considers the connection complete on that plane instead of extending it to the shared boundary.
  • Uses a straight pad-pair escape when the via fits. Otherwise it uses a 45° four-pad interstitial escape and nested side bands that spread deeper two-layer buses around already-routed outer buses.
  • compactBusTracks provides a trace/clearance-pitch fallback envelope when the original endpoint track cannot route, so a wide pad row does not consume a disproportionately wide breakout corridor.
  • Boundary tracks project onto the original downstream pad coordinates and prefer their layer when legal. This lets ordered edge-pad buses make direct, visibly continuous pad connections.
  • Chamfers orthogonal routing corners into 45° segments before validating and emitting the fanout.
  • Honors a boundary bus maxLengthSkew as a hard local-fanout constraint. It adds straight/45° meanders while retaining source escapes and boundary endpoints, and atomically rejects an assignment when the requested skew cannot fit inside that bus's shared boundary. Coordinated dense routing can tune inside the pad field after reserving and checking all other copper. Bounded paired shortening commits only a complete pair under its original skew limit.
  • Verifies oriented-pad, via, trace, and already-routed fanout clearance on every complete candidate, independent of the routing strategy that produced it.
  • Resolves netConnectionName, connection, port, trace, and obstacle metadata into electrical-net identities. Same-net copper may merge; different-net pads, traces, and vias must retain clearance on every layer they occupy.
  • allowSameNetMerges lets grouped branches such as VCC or GND reuse connected copper instead of reserving artificial clearance from one another. It is opt-in for ordinary branches; different electrical nets remain hard obstacles. When dense plane escapes are staged around pre-existing all-layer copper on their declared plane net, those plane branches are already electrically joined and are matched as same-net copper.
  • allowBlindAndBuriedVias describes the host board's manufacturing rule. It defaults to true for standalone compatibility; hosts that manufacture through-all vias should pass false, which reserves every copper layer in route planning and emitted-copper DRC while preserving each route's logical layer transition.
  • Via-in-pad remains opt-in through SimpleRouteJson.allowViaInPad === true. Undefined or false uses an offset dogbone, including plane terminations.
  • Audits route continuity, unique connection coverage, boundary exits, and retained downstream endpoints before marking a solution complete.
  • completeOriginalEndpoints adds a bounded fail-first completion stage after fanout. It first places DRC-gated interstitial capacitor escapes, then tries breakout-to-pad routes with layer transitions at interior points along the existing fanout copper, and finally calls the optional routeDownstreamConnections host callback. Vias at original or moved routing endpoints are rejected. A candidate is retained only when it improves independently proven original endpoint connectivity and the complete emitted copper remains DRC-clean.
  • Emits supplied fanout traces, via obstacles, and moved breakout endpoints in a new SimpleRouteJson. The returned problem is ready for a downstream autorouter to finish.

Install

This repository uses tscircuit's source-first GitHub package convention:

bun add https://github.com/tscircuit/fanout-solver

Usage

import {
  AutoroutingPipelineSolver6,
  CapacityMeshSolver,
} from "@tscircuit/capacity-autorouter"
import { FanoutSolver } from "@tscircuit/fanout-solver"

const fanoutSolver = new FanoutSolver(simpleRouteJson, {
  maxLayerCombinations: 256,
  sharedBoundary: {
    minX: -25,
    maxX: 25,
    minY: -25,
    maxY: 25,
  },
  componentBounds: {
    "bga-01": { minX: -4.7, maxX: 4.7, minY: -4.7, maxY: 4.7 },
  },
  busDirections: {
    ddr: "right",
  },
  busExitPreferences: {
    clocks: "top-right",
  },
  availableCornersAndSides: ["top_left", "top", "top_right"],
  borderDistribution: "even",
  compactBusTracks: true,
  completeOriginalEndpoints: true,
  routeDownstreamConnections: (inputSrj, { effort }) => {
    const downstreamSolver = new AutoroutingPipelineSolver6(inputSrj, {
      effort,
    })
    downstreamSolver.solve()
    if (!downstreamSolver.solved) {
      throw new Error(downstreamSolver.error ?? "Downstream routing failed")
    }
    return downstreamSolver.getOutputSimpleRouteJson().traces ?? []
  },
  buses: [
    {
      busId: "ground",
      connectionNames: ["VSS_A1", "VSS_A2"],
      direction: "right",
      termination: { type: "plane", layer: "inner1" },
    },
  ],
})
fanoutSolver.solve()

if (fanoutSolver.failed) {
  throw new Error(fanoutSolver.error ?? "Fanout failed")
}

const autorouter = new CapacityMeshSolver(
  fanoutSolver.getOutputSimpleRouteJson(),
)
autorouter.solve()

Canonical exit positions are edge-first: topside_left, topside_center, topside_right, rightside_top, rightside_center, rightside_bottom, bottomside_right, bottomside_center, bottomside_left, leftside_bottom, leftside_center, leftside_top, and center. They normalize atomically into the local direction, boundary-band preferredExit, and physical exitEdge; conflicting bus-level legacy fields are rejected. Existing buses that omit exitPosition retain their previous behavior. Hosts can import getFanoutExitPositionConfig to inspect the same normalized tuple without duplicating this mapping.

The downstream callback is optional. It lets the application choose its board-level router while keeping @tscircuit/fanout-solver free of a runtime autorouter import. Returned traces are still accepted only after the fanout solver's connectivity and copper-clearance checks pass.

The canonical bus input is the current SimpleRouteJson bus structure:

{
  buses: [
    {
      busId: "ddr",
      connectionNames: ["BUS_DDR_01", "BUS_DDR_02", "BUS_DDR_03"],
      preferredExit: "right",
      maxLengthSkew: 0.25,
    },
  ],
}

preferredExit is an optional fanout extension to SimpleRouteBus; omitting it leaves ordinary SimpleRouteJson behavior unchanged. All listed connections receive the same escape direction and target layer. If one connection cannot be routed cleanly, the solver rejects that bus for the current layer assignment and tries another combination. busExitPreferences provides the same override without modifying the input object.

maxLengthSkew is measured in millimeters of planar routed copper within this fanout phase. It is supported for multi-connection boundary buses. A loose or omitted constraint leaves the routed geometry unchanged; an impossible constraint fails instead of returning a fanout that violates the declared skew. Plane-terminated buses reject maxLengthSkew because they do not have a boundary tuning corridor.

availableCornersAndSides is a solver-wide hard constraint. Its directed corner names distinguish the two edges meeting at a corner: top_left exits through the top edge, while left_top exits through the left edge. The complete set is top_left, top_middle, top_right, right_top, right_middle, right_bottom, bottom_right, bottom_middle, bottom_left, left_bottom, left_middle, and left_top. top, right, bottom, and left alias the corresponding middle region. An empty list is invalid; omit the option to allow all edges.

termination is another additive extension:

type FanoutBusTermination =
  | { type: "boundary" }
  | { type: "plane"; layer: string }

A plane-targeted connection may contain only its package-pad source point. The solver creates the local dogbone and via, records it in planeTerminations, and removes the completed connection from the returned downstream SimpleRouteJson. Plane layers are fixed targets and are not included in the bus-layer combination search.

Output contract

getOutput() returns:

  • simpleRouteJson: the downstream routing problem with fanout prefixes
  • fanoutTraces: the newly supplied pad-to-breakout traces
  • completionTraces: optional DRC-gated traces from breakouts to original endpoints
  • endpointCompletion: optional independent connectivity/DRC reports and bounded-search diagnostics
  • planeTerminations: the completed local-via connection, layer, and via data
  • busLayerAssignments: the selected layer for every bus
  • busDirections: the direction shared by each bus
  • attempts: score and success metadata for every tried layer combination
  • validation: the final geometry/connectivity report, including the number of independently validated breakouts

Dataset 01

datasets/dataset01.ts contains five deterministic footprinter samples. The samples contain exactly one through five BGA footprints, and every sample is solved as one SimpleRouteJson.

Sample Footprints Pads Connections
sample001 1 64 64
sample002 2 100 100
sample003 3 136 136
sample004 4 200 200
sample005 5 236 236

The Cosmos debugger provides Previous/Next controls and direct sample tabs. It also stores the selected dataset and sample in the dataset and sample URL parameters. Each sample has one shared boundary around all of its footprints, and component bounds come from the exact footprinter-generated copper pad extents.

Dataset 31 benchmark

Run ./benchmark.sh (or bun run benchmark) to benchmark all 72 dataset 31 directional cases: 12 each for AM62L, RK3308, K230, i.MX6ULL, T113-S3, and AM3352 from tscircuit/dataset-fanout31-am62l. The upstream revision is pinned in scripts/generate-repro/package.json and recorded in every report. Other datasets remain available for regression tests and the debugger, but have no benchmark commands or workflows.

./benchmark.sh
./benchmark.sh --list
./benchmark.sh --sample 11-left-center
./benchmark.sh --sample 13-rk3308-top-left-offset
./benchmark.sh --sample 25-k230-top-left-offset
./benchmark.sh --sample 37-imx6ull-top-left-offset
./benchmark.sh --sample 49-t113s3-top-left-offset
./benchmark.sh --sample 61-am3352-top-left-offset
./benchmark.sh --concurrency 8 --sample-timeout-seconds 300

Before timing the solver, the benchmark renders the selected upstream TSX/core circuits and captures their exact fanout-solver constructor inputs into benchmark-results/inputs/<sample-id>.json. Each case retains its complete SoC fanout workload and the original clearance, differential-pair, and length-skew constraints:

SoC Cases Signal connections Plane drops Total connections Pad obstacles
AM62L 12 33 102 135 573
RK3308 12 49 113 162 451
K230 12 65 106 171 790
i.MX6ULL 12 49 53 102 385
T113-S3 12 106 22 128 235
AM3352 12 205 117 322 529

AM62L, RK3308, and i.MX6ULL have nine DDR signal buses each. The RK3308 samples use a 355-ball SoC and 96-ball DDR3L RAM. The i.MX6ULL samples use the 289-ball MCIMX6Y2CVM08AB and 96-ball DDR3L RAM, retaining 47 ground and six DDR-supply plane drops. The K230 samples use a 390-ball SoC and two 200-ball x16 LPDDR4 RAM packages, with 17 signal buses and six differential pairs. These four families place their RAM on all four sides at three offsets per side. K230 retains both physical RAM endpoints of its shared RESET net; the two RAM packages have separate breakout regions. All 790 pads in each K230 case remain obstacles, including unused signal and supply pads.

T113-S3 uses a 128-lead QFP with an exposed ground pad. Every non-NC lead and the exposed pad is connected: 106 signals and 22 plane drops, with three differential pairs. Its 12 configurations rotate the package and shift bus bands; each configuration preserves compact bus-specific exits on all four edges. Signals use top, inner6, and bottom; five separate voltage/ground planes occupy inner1 through inner5.

AM3352 uses the 324-ball AM3352BZCZD80 BGA. Its 322 operational balls connect to 205 signal destinations and 117 plane drops; the two NC balls remain pad obstacles. Its 12 configurations rotate the package and offset external terminals while preserving bus-specific exits on all four edges. The ten-layer board uses top, inner7, inner8, and bottom for signals, with six separate voltage/ground planes on inner1 through inner6 and five differential pairs.

The timed workers run this checkout's solver, not the upstream package's released solver. To capture the inputs without solving, use bun run generate:dataset31. The optional --dataset dataset31 flag is accepted for explicit CI invocation; other dataset selections are rejected.

To isolate a failure without changing pads or clearance rules, reduce a captured input by bus or connection count. This is a diagnostic, not a benchmark score:

bun scripts/debug-dataset31.ts --input benchmark-results/inputs/10-left-bottom-offset.json --buses DDR_ADDR_CTRL --connection-limit 7 --output /tmp/address-seven
bun scripts/debug-dataset31.ts --input benchmark-results/inputs/10-left-bottom-offset.json --buses DDR_ADDR_CTRL --output /tmp/address-eight

Each run has a hard process deadline and saves JSON progress and an SVG preview. Use --dump-input <path> --capture-only to save the exact reduced solver input as a regression fixture. Retained buses keep their original targets and timing limits; only removed connections and their differential-pair metadata are pruned.

Each sample runs in an isolated process, with up to four concurrent processes locally and a 120-second hard timeout by default. A synchronous solver hang, exception, or unsolved case does not prevent later samples from running. Assignment budgets and circuit constraints remain at each sample's defaults; --max-layer-combinations explicitly overrides only the search budget.

The ordered benchmark-results/benchmark.json and benchmark.md reports contain the solver commit, dataset revision, configuration, solve totals, every sample's status and timing, and partial routing/validation counts. Reports are saved after every completed sample, including the total selected count to identify incomplete runs. Timed-out workers do not retain their in-flight routing counts. Every solved case also writes benchmark-results/<sample-id>.svg. These SVGs are committed so route changes can be reviewed in Git. A run replaces the selected cases' snapshots and removes their stale SVGs if they no longer solve; filtered runs preserve unselected snapshots. The latest JSON and Markdown reports are also committed; captured inputs remain ignored. CI includes the reports, inputs, and SVGs in its benchmark artifacts. Compare reports with the same dataset revision and budgets to track progress. A case is solved only when every SoC connection has validated fanout: all 135 connections for AM62L, all 162 for RK3308, all 171 for K230, all 102 for i.MX6ULL, all 128 for T113-S3, or all 322 for AM3352. This covers the SoC fanout phase; RAM fanout and downstream inter-chip routing are separate phases. Partial, error, and timeout rows are benchmark results (exit 0); invalid CLI arguments or report I/O failures are command failures (nonzero exit).

PR comment trigger

Once .github/workflows/benchmark.yml is on the default branch, a repository writer can comment /benchmark on an open PR. The workflow captures that PR's exact head SHA, runs all 72 dataset 31 samples on a 32-vCPU Blacksmith ARM runner, then updates a status comment with solve totals, per-sample results, and a link to the complete JSON/Markdown reports and captured inputs. The Actions UI also supports a manual run, optionally supplying an open PR number. No custom bot token is required.

The runner defaults to 32 processes and a 120-second per-sample deadline; set repository variables BENCHMARK_CONCURRENCY and BENCHMARK_SAMPLE_TIMEOUT_SECONDS to change these. PR code runs with a read-only token and no persisted checkout credentials. A separate job uses the trusted workflow revision to validate report data and post comments; it never executes PR code. The trusted renderer rejects legacy or mixed-dataset reports, so PR comments contain only dataset 31 results. Only exact commands from non-bot users with current write, maintain, or admin access are accepted.

Dataset 02

datasets/dataset02.ts is the four-layer BGA400 stress benchmark. It routes every ball in the exact footprinter string bga400_grid20x20_p0.8mm_pad0.3mm_circularpads; the debugger includes that string in both the visible sample heading and browser title. The sample uses JLCPCB's published 0.10/0.10 mm trace and spacing capability, 0.10 mm pad/copper clearance, and standard 0.25/0.15 mm vias.

Exactly 100 balls and ten buses escape through each package edge. The four perimeter buses (76 balls) stay via-free on top. The remaining 36 buses use 324 bus-atomic vias. Matching opposite-edge depths cycle through inner1, inner2, and bottom, so every escape layer carries twelve buses instead of receiving one easy depth band.

The earlier 0.4 mm corner-interstitial case remains a dedicated regression test. It cannot honestly route the full BGA400 on four layers with the retained 0.10 mm rules: adjacent 0.15 mm via centers are 0.40 mm apart, but a crossing 0.10 mm trace needs 0.45 mm center-to-center capacity after both clearances are included. The repeated via row is therefore a physical copper wall. The 0.8 mm BGA400 leaves real reusable channels while still forcing a four-layer solution.

Sample Footprints Pads Buses Vias Layers
sample001 1 400 40 324 4

Every bus exits the shared component boundary and uses only straight or 45° segments. Top, inner1, inner2, and bottom traces use distinct red, blue, green, and purple colors in Cosmos and the verification PNG.

Dataset 03

datasets/dataset03.ts contains four two-layer mixed-footprint samples. Every sample uses the exact footprinter strings qfn50_p0.4mm, res0603, and cap0603, for 54 routed pads across three footprints and one shared boundary. The QFN rotates through 0°, 90°, 180°, and 270° while the two 0603 packages alternate between tangential and radial placement.

The close tangential samples deliberately block two opposite top-layer QFN escape corridors. The solver moves each obstructed QFN side as one atomic bus to bottom while keeping the surrounding 0603 terminals independently routable. The radial samples offset the passives toward package corners to create asymmetric channels without relaxing JLCPCB's 0.10 mm copper clearance or standard 0.25/0.15 mm via constraints.

Sample Footprints Pads Buses Layers
sample001 3 54 8 2
sample002 3 54 8 2
sample003 3 54 8 2
sample004 3 54 8 2

Dataset 04

datasets/dataset04.ts contains five top-copper-only package-plus-decoupling stress cases. Every sample places exactly eight cap0603 footprints at the cardinal and diagonal positions around one central package, then uses push-and-shove bends to move complete ordered bundles through one shared boundary. The "even" border-distribution option makes the exit lanes consume their available border interval consistently, and the four diagonal capacitor pairs explicitly request their matching corners. No Dataset 04 route contains a via or a non-top-layer wire.

The BGA cases use the exact footprinter strings bga16_grid4x4_p0.8mm_pad0.3mm_circularpads, bga25_grid5x5_p1.75mm_pad0.3mm_circularpads, bga36_grid6x6_p1.5mm_pad0.3mm_circularpads, and bga64_grid8x8_p1.5mm_pad0.3mm_circularpads. Every inner ball is connected, grid-line buses remain atomic, and a sweep-line channel router pushes already allocated traces when a new pad row needs corridor capacity.

The final sample uses the RP2040-class footprinter string qfn56_w7.8_h7.8_p0.4mm_pw0.23mm_pl0.8mm_thermalpad3.2x3.2_startingpin(topside,rightpin)_ccw. Those compensated footprinter dimensions reproduce Raspberry Pi's reference land pattern exactly: perimeter centers at ±3.4 mm, 0.4 mm pitch, 0.8×0.23 mm pads, and a 3.2×3.2 mm exposed pad, with no overlapping copper. It routes all 56 perimeter pins, the exposed thermal pad, and all 16 capacitor pads. The thermal-pad trace leaves on a 45° diagonal through a package corner, centered between the outermost pads on its two adjacent edges. That diagonal channel clears both rectangular pad corners under the same 0.10 mm trace and 0.10 mm edge-clearance rules.

All five regressions independently verify JLCPCB's 0.10 mm trace width and 0.10 mm copper-clearance rules, top-only routing, shared-boundary exits, inner BGA pad coverage, ordered push-and-shove bends, and the absence of 90° corners.

Sample Footprints Routed pads Buses Vias Layers
sample001 9 32 24 0 1
sample002 9 41 25 0 1
sample003 9 52 28 0 1
sample004 9 80 32 0 1
sample005 9 73 73 0 1

Dataset 05

datasets/dataset05.ts uses the attached Rockchip RK3588 V1.1 ball-assignment data as its checked-in source of truth. It preserves the exact 34×34 published orientation, all 1,088 populated ball coordinates and names, and all 68 unpopulated positions. Every generated connection and pad obstacle carries its complete source assignment as rk3588BallAssignment metadata.

The six-layer sample dedicates inner1 to the 422 ground balls and inner2 to the 167 power balls. Those 589 connections end at unique 0.25/0.15 mm local dogbone vias. The remaining 499 signal balls are divided into short, direction-consistent geometric buses and escape to the shared boundary on top, inner3, inner4, and bottom. All copper uses the same 0.10 mm trace and clearance values as the JLCPCB regressions.

Sample Package Balls Plane terminations Boundary signals Layers
sample001 FCBGA1088L 1088 589 499 6

Dataset 06

datasets/dataset06.ts preserves the 132-connection, 265-obstacle, single-layer mixed-footprint input from the clad1 RP2040 board:

clad1 RP2040 fanout reproduction

The original reproduction failed for three independent reasons:

  • several serialized source_trace_* names belong to the same canonical connectivity_net…, so treating those names as foreign nets creates false clearance conflicts;
  • the RP2040 exposed pad is enclosed and must merge into a same-net perimeter pad before following that pad's escape;
  • all 132 outward-facing exit preferences cannot coexist without crossings on one layer.

Dataset 06 enables singleLayerAdaptiveExits. After the preferred push-and-shove attempt fails, this pass reserves short pad-escape stubs, routes the remaining physical terminals together, locally merges the few multi-terminal pads that do not need independent channels, and chooses alternate sides of the same shared boundary. The result routes all 132 connections on top copper with the configured 0.1 mm trace width and 0.1 mm clearance.

Development

bun install
bun run typecheck
bun test
bun run benchmark
bun run render:dataset
bun run start

The benchmark runs all 72 dataset 31 AM62L, RK3308, K230, i.MX6ULL, T113-S3, and AM3352 cases and reports solve counts, validation, and timing. bun run start opens all regression datasets in the standard tscircuit solver debugger. bun run render:dataset writes graphics-debug PNGs under one subdirectory per dataset, with a red shared boundary, gray component courtyards, and green fanout-exit markers. Pass an output directory and dataset id to render one dataset, for example bun scripts/render-dataset-pngs.ts docs/images dataset06. Failed regressions render their best partial attempt with a visible INCOMPLETE label.

Scope

This package owns the BGA pad-to-breakout prefix. It does not replace the board-level autorouter or route arbitrary obstacles between the breakout boundary and the final destination. Its maxLengthSkew matching applies to the local fanout prefix; end-to-end delay matching across multiple routing phases still belongs to a board-level coordinator.

About

BGA fanout solver with coordinated bus escapes for SimpleRouteJson

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages