Skip to content

About

M3D routing challenge: a reproducible EDA routing benchmark for a simplified monolithic-3D stack (generator, checker, scorer, baseline, visualization).

Resources

Contributing

Stars

52 stars

Watchers

1 watching

Forks

Repository files navigation

3D Routing Challenge

A small, reproducible EDA routing challenge for a simplified hybrid-bonded 3D integration stack. Two dies sit face to face with a shared vertical stack of routing layers between them. Participants connect cell pins across a 3D grid graph while minimizing total routing delay under a simple additive delay model.

Everything here is self-contained and pure standard library (only the visualization needs matplotlib). The repository ships a deterministic benchmark generator, six benchmark tiers (five generated, one built from real circuits) whose every case has a verified legal reference solution, an independent legality checker and scorer, a baseline router, a visualization tool, an example participant router, and tests.

layer sweep of a routed case

Sweeping the routing stack of one case (reference solution). Edge delay is lowest on the middle layers and highest next to the dies (see the strip at the bottom), so long connections dive to the cheap middle of the stack. Cells are shaded on the die layers; pins are dots colored by die; vias are open squares; nets are colored; the faint grey is the whole routing for context.

suite sweep

The intro 20-case size ladder (each case's reference solution, flattened top-down), growing grid, cell, pin and net counts from case_01 to case_20.

Leaderboard

Ranked per tier (each tier is normalized to its own baseline, so a higher aggregate is better and the baseline itself scores 1.0000). ✓ marks submissions on the runtime-vs-total-delay Pareto frontier; † marks derivative entries that start from another entry's routes. runtime (s) is the summed wall-clock time of one run per case, as reported in runtime.json (hardware and threads are in meta.json). It is required: entries still missing it on 2026-10-15 become unranked. verified is set by the maintainers once they have re-run an entry's router and reproduced its routes (verification.json); — means not yet. Submit by pull request; see CONTRIBUTING.md. Also in LEADERBOARD.md.

intro (20 cases)

rank submission author aggregate legal total delay runtime (s) Pareto verified
1 coordinated_refinement † jay-tau 1.1566 20/20 339328 missing —
2 leonid-popryho Leonid Popryho 1.1563 20/20 339406 missing —
3 cuda-have-been-shorter YJ Kim 1.1562 20/20 339546 missing —
4 pathfinder_lns Tazeem Mahashin 1.1514 20/20 341746 46476.76 ✓ —
5 warm_lns_refinement † kesudh 1.1509 20/20 342006 missing —
6 spt_lns James (IrwinJam) 1.1444 20/20 345066 missing —
7 iamparv7043 Parv (iamparv7043) 1.1254 20/20 353836 2213.60 ✓ —
8 anvesh anvesh 1.1069 20/20 360172 missing —
9 synapse-surge Sameer-Deepak 1.1004 20/20 368374 missing —
10 lns_negotiated adityuhkapoor 1.0937 20/20 367388 missing —
11 negotiated_delay Mantej Singh Gill 1.0906 20/20 368046 752.29 ✓ —
12 gavinoh-spt-lns Gavin Oh 1.0632 20/20 382210 1826.80 —
13 dw_metric_lns OpenCode (DeepSeek V4.1 Flash) 1.0584 20/20 393668 25289.93 —
14 shivaahir158 Shiva Ahir (PhD Candidate, Stony Brook University) 1.0274 20/20 388638 440.56 ✓ —

† derivative entry (refines another entry's routes): coordinated_refinement builds on drama3d-portfolio; leonid-popryho; pathfinder_lns; warm_lns_refinement (Leonid Popryho; Taz33m; Tazeem Mahashin; YJ Kim; kesudh); warm_lns_refinement builds on pathfinder_lns (Taz33m).

hard (9 cases)

rank submission author aggregate legal total delay runtime (s) Pareto verified
1 coordinated_refinement † jay-tau 1.4136 9/9 142321 missing —
2 leonid-popryho Leonid Popryho 1.4123 9/9 142413 missing —
3 cuda-have-been-shorter YJ Kim 1.4085 9/9 142989 missing —
4 spt_lns James (IrwinJam) 1.3971 9/9 144153 missing —
5 pathfinder_lns Tazeem Mahashin 1.3884 9/9 144991 missing —
6 warm_lns_refinement † kesudh 1.3874 9/9 145095 missing —
7 reubalink reubalink 1.3622 9/9 147825 missing —
8 iamparv7043 Parv (iamparv7043) 1.3019 9/9 155125 7333.40 ✓ —
9 erikqu_root_aware_portfolio erikqu 1.2745 9/9 158455 missing —
10 synapse-surge Sameer-Deepak 1.2569 9/9 161183 missing —
11 lns_negotiated adityuhkapoor 1.2267 9/9 165367 missing —
12 anvesh anvesh 1.1863 9/9 169737 missing reproduced
13 ly ly 1.1500 9/9 175329 822.57 ✓ —
14 negotiated_delay Mantej Singh Gill 1.1499 9/9 175879 105.39 ✓ —
15 shivaahir158 Shiva Ahir (PhD Candidate, Stony Brook University) 1.0508 9/9 192507 787.30 —
16 negotiated_x2 Anthropic (reference) 1.0168 9/9 198763 177.01 —
17 negotiated Anthropic (reference) 1.0000 9/9 201863 85.20 ✓ —
18 negotiated_fast Anthropic (reference) — 8/9 — 61.74 —

† derivative entry (refines another entry's routes): coordinated_refinement builds on drama3d-portfolio; leonid-popryho (Leonid Popryho; YJ Kim); warm_lns_refinement builds on pathfinder_lns (Taz33m).

scale (8 cases)

rank submission author aggregate legal total delay runtime (s) Pareto verified
1 coordinated_refinement † jay-tau 1.1399 8/8 531688 missing —
2 leonid-popryho Leonid Popryho 1.1397 8/8 531766 missing —
3 cuda-have-been-shorter YJ Kim 1.1391 8/8 532016 missing —
4 pathfinder_lns Tazeem Mahashin 1.1277 8/8 537468 62411.00 ✓ —
5 warm_lns_refinement † kesudh 1.1274 8/8 537576 7543.00 ✓ —
6 spt_lns James (IrwinJam) 1.1188 8/8 541966 missing —
7 iamparv7043 Parv (iamparv7043) 1.1010 8/8 550828 3094.50 ✓ —
8 anvesh anvesh 1.0821 8/8 559460 missing —
9 lns_negotiated adityuhkapoor 1.0682 8/8 567094 missing —
10 synapse-surge Sameer-Deepak 1.0496 8/8 579306 missing —
11 shivaahir158 Shiva Ahir (PhD Candidate, Stony Brook University) 1.0108 8/8 598244 2196.48 ✓ —

† derivative entry (refines another entry's routes): coordinated_refinement builds on leonid-popryho (Leonid Popryho); warm_lns_refinement builds on pathfinder_lns (Taz33m).

stress (1 cases)

rank submission author aggregate legal total delay runtime (s) Pareto verified
1 coordinated_refinement † jay-tau 1.0984 1/1 1042314 missing —
2 leonid-popryho Leonid Popryho 1.0984 1/1 1042322 missing —
3 cuda-have-been-shorter YJ Kim 1.0978 1/1 1042926 missing —
4 pathfinder_lns Tazeem Mahashin 1.0914 1/1 1048990 43262.89 ✓ —
5 warm_lns_refinement † kesudh 1.0911 1/1 1049332 2070.00 ✓ —
6 spt_lns James (IrwinJam) 1.0779 1/1 1062208 missing —
7 lns_negotiated adityuhkapoor 1.0669 1/1 1073124 missing —
8 synapse-surge Sameer-Deepak 1.0008 1/1 1143964 missing —

† derivative entry (refines another entry's routes): coordinated_refinement builds on leonid-popryho (Leonid Popryho); warm_lns_refinement builds on pathfinder_lns (Taz33m).

congested (4 cases)

rank submission author aggregate legal total delay runtime (s) Pareto verified
1 coordinated_refinement † jay-tau 1.3508 4/4 476231 missing —
2 leonid-popryho Leonid Popryho 1.3505 4/4 476333 missing —
3 cuda-have-been-shorter YJ Kim 1.3392 4/4 479359 missing —
4 spt_lns James (IrwinJam) 1.3156 4/4 489177 missing —
5 pathfinder_lns Tazeem Mahashin 1.3111 4/4 490499 61369.30 ✓ —
6 warm_lns_refinement † kesudh 1.3085 4/4 491467 3621.00 ✓ —
7 iamparv7043 Parv (iamparv7043) 1.1252 4/4 591707 4593.60 —
8 lns_negotiated adityuhkapoor 1.0981 4/4 590513 missing —
9 shivaahir158 Shiva Ahir (PhD Candidate, Stony Brook University) 1.0549 4/4 608243 8756.73 —
10 synapse-surge Sameer-Deepak 1.0518 4/4 616017 missing —

† derivative entry (refines another entry's routes): coordinated_refinement builds on leonid-popryho (Leonid Popryho); warm_lns_refinement builds on pathfinder_lns (Taz33m).

designs (3 cases)

rank submission author aggregate legal total delay runtime (s) Pareto verified
1 coordinated_refinement † jay-tau 1.4673 3/3 204497 missing —
2 leonid-popryho Leonid Popryho 1.4667 3/3 204581 missing —
3 cuda-have-been-shorter YJ Kim 1.4634 3/3 204963 missing —
4 pathfinder_lns Tazeem Mahashin 1.4354 3/3 209175 47267.61 ✓ —
5 spt_lns James (IrwinJam) 1.4347 3/3 209415 missing —
6 warm_lns_refinement † kesudh 1.4331 3/3 209509 3615.00 ✓ —
7 iamparv7043 Parv (iamparv7043) 1.3276 3/3 226581 1309.30 ✓ —
8 lns_negotiated adityuhkapoor 1.2533 3/3 240751 missing —
9 anvesh anvesh 1.2520 3/3 240501 missing —
10 negotiated_delay Mantej Singh Gill 1.1947 3/3 252901 636.11 ✓ —
11 synapse-surge Sameer-Deepak 1.1456 3/3 264847 missing —
12 shivaahir158 Shiva Ahir (PhD Candidate, Stony Brook University) 1.0593 3/3 288347 3728.39 —

† derivative entry (refines another entry's routes): coordinated_refinement builds on leonid-popryho (Leonid Popryho); warm_lns_refinement builds on pathfinder_lns (Taz33m).

Difficulty tiers

The challenge ships several tiers, from an easy on-ramp to genuinely hard, plus a tier built from real open-source circuits. Each is its own directory with its own manifest; each case is normalized against its own tier's baseline.

Tier Dir Cases Largest case Baseline (to beat) What makes it hard
intro benchmarks/ 20 92×92×6, 139 nets, 514 pins simple rip-up router On-ramp. Sparse (~6% of edges used); the simple baseline routes every case with 0 rip-ups, so it is easy and conventional — good for getting a submission working.
hard benchmarks_hard/ 9 40×40×6, 104 nets, 323 pins negotiated-congestion router Contended. Pins and nets crowd the cheap middle layers, so the delay-vs-detour tradeoff is the crux and legality itself needs a real router: the simple rip-up baseline fails or thrashes on most cases (thousands of rip-ups), while the negotiated router certifies a legal solution. Beating that baseline is the real contest.
scale benchmarks_scale/ 8 156×156×6, 265 nets, 766 pins simple router Large. Big enough that runtime is a first-class axis (the baseline itself takes ~10–70 s/case), which is what the runtime-vs-delay Pareto below measures.
stress benchmarks_stress/ 1 530×530×6, 901 nets, 2,612 pins simple router ~30-minute baseline (sparse). One giant sparse case for stress-testing router runtime and scaling; the reference (simple) baseline routes it in ~33 min. Baseline route time fits ≈ 7e-6 · nets · side², so you can dial any target wall time in m3d/suite.py.
congested benchmarks_congested/ 4 116×116×6, ~302 nets, ~950 pins negotiated router Large + contended stress. The congested counterpart of stress: net density and locality hold the cheap middle layers at ~35% utilization at every size, so the simple baseline is hopeless and even the negotiated router ramps ~80 s → ~9 min across the four cases (64/88/112/116).
designs benchmarks_designs/ 3 105×105×6, 344 nets, 888 pins negotiated router Real open-source circuits. Instances built from real gate-level netlists — the MIT-licensed EPFL combinational benchmark suite. Every gate, input and output becomes a cell and every signal a net, so fanout and connectivity are those of a real design; cells are placed by connectivity clustering (reverse Cuthill-McKee) and folded across the two dies. The negotiated router certifies each reference. Bring your own with m3d.cli import-design.

Is the intro tier "too easy / conventional"? Yes, deliberately — it is the on-ramp. The hard tier is where the 3D structure bites: the delay-graded layer stack is only interesting when the cheap layers are scarce and contended, and there the problem stops being a clean maze and becomes a real congestion-plus-delay optimization that a naive router cannot even legalize. The scale tier adds the runtime dimension. The designs tier grounds all of this in real silicon: the same model, checker and scorer applied to actual open-source netlists, where the fanout and connectivity are not synthetic. Everything is parametric (m3d/suite.py, m3d/generator.py::GenConfig, m3d/designs.py::DesignConfig), so you can push grids, nets, fanout, contention, layer count — and add more real designs — further.

Real designs (the designs tier)

The designs tier is built from real gate-level netlists, not the random generator. The sources are vendored under designs/blif/ from the MIT-licensed EPFL combinational benchmark suite (see designs/PROVENANCE.md). The mapping is direct:

  • every logic gate, primary input and primary output becomes a cell (footprint sized to its pin count);
  • every signal with a driver and ≥1 sink becomes a net — the driving terminal is the driver pin, the reading terminals are the sinks — so the fanout and connectivity are exactly the design's;
  • cells are ordered by reverse Cuthill-McKee (connectivity clustering) and spread on a lattice with a routing channel around each, then split across the two dies at a low-connectivity cut, so signals crossing the fold use vias;
  • the negotiated router certifies a legal reference, widening the channel until it succeeds — the same verified-feasible guarantee as every other tier.

Only the connectivity is used; the logic (the BLIF truth tables) is irrelevant to routing and is ignored. Build the tier with make generate-designs (resumable — re-run to finish if interrupted), or turn any BLIF into an instance:

python -m m3d.cli import-design --blif designs/blif/cavlc.blif --name cavlc \
    --out cavlc.json --reference cavlc.sol.json

1. The model

Physical model

  • Two dies — bottom = die 0, top = die 1 — share one rectangular, grid-aligned XY coordinate system of size width x height.
  • Between them is a stack of layers routing layers, z = 0 .. layers-1. The number of layers is configurable (default 6).
  • Rectangular, grid-aligned cells are placed without overlap on each die. Cells on opposite dies may overlap in XY. Each cell carries one or more grid-aligned pins.
  • Bottom-die pins live on layer z = 0; top-die pins live on layer z = layers-1.
  • Routing is a 3D grid graph. A vertex is (x, y, z). Legal moves:
    • one grid step in X or Y on the same layer, or
    • a via to an adjacent layer at the same XY. No diagonal moves, no skipped layers.
  • In this first model, cell footprints do not obstruct the routing layers. The only routing obstacles are other nets' pins (see legality).

Delay model (abstract, additive)

This is an abstract additive delay objective, not electrical timing analysis. There is no capacitance, slew, buffering, loading, or congestion-dependent delay.

  • Each routing layer has a constant positive integer delay per grid edge. The default profile is symmetric about the middle of the stack, lowest in the middle and highest next to either die: layer_delay[z] = center_delay + slope * |2z - (layers-1)|.
  • Each via between adjacent layers has a constant positive integer delay.
  • All delay values are stored explicitly in every instance (layer_delay, via_delay), and delays are integers so scoring is exact and deterministic.

Nets and the objective

  • Nets connect cell pins; a net may be same-die or cross-die (spanning both dies), two-pin or multi-pin. Proportions and fanout are configurable.
  • Each net has exactly one driver and one or more sinks. Every pin belongs to exactly one net.
  • A submitted route for a net must be a connected, acyclic tree that spans all of the net's pins, so every driver→sink path is unambiguous.
  • Total routing delay = the sum, over all sinks of all nets, of the delay of the driver→sink path through that net's tree. A shared segment contributes to each sink path that traverses it.
  • Objective: minimize total routing delay while routing every net legally.

Routing legality

  • Each routing-grid vertex and edge may belong to at most one net.
  • Branches of the same net may share vertices and edges (a tree already does).
  • Different nets may cross in XY on different layers, as long as they share no 3D vertex or edge.
  • A via occupies its two endpoint vertices and the edge between them.
  • A route may not pass through another net's pin.
  • All routes must stay within the grid and layer bounds and use only legal moves.

A submission is rejected (illegal, non-competitive) if it has any disconnected pin, missing net, short, resource conflict, cycle, invalid coordinate, or illegal layer transition. Partial routing does not earn a competitive score.


2. Repository layout

m3d/                 the toolkit (pure stdlib)
  model.py           data model, delay profile, JSON I/O
  grid.py            3D grid moves used by the router
  generator.py       deterministic, verified-feasible benchmark generator
  checker.py         independent legality checker + delay recomputation
  scorer.py          per-case scoring + normalized leaderboard
  baseline.py        baseline router (Dijkstra trees + rip-up-and-reroute)
  negotiated.py      negotiated-congestion router (PathFinder-style; hard tier)
  designs.py         BLIF netlist -> routing instance (the 'designs' tier)
  suite.py           the generated tiers (intro/hard/scale/stress/congested)
  scorer.py          per-case scoring, leaderboard, Pareto frontier
  viz.py             matplotlib visualization + Pareto plot
  anim.py            animated GIF renderers
  cli.py             command-line entry point
designs/             vendored open-source netlists (blif/) + license + provenance
benchmarks/          intro tier: 20 cases + suite.json + reference/
benchmarks_hard/     hard (contended) tier: 9 cases + suite.json + reference/
benchmarks_scale/    scale (large) tier: 8 cases + suite.json + reference/
benchmarks_stress/   stress tier: 1 giant sparse case + suite.json + reference/
benchmarks_congested/  congested tier: 4 large contended cases + reference/
benchmarks_designs/  designs tier: 3 real EPFL circuits + suite.json + reference/
submissions/         PR-based leaderboard entries: submissions/<tier>/<name>/
LEADERBOARD.md       generated leaderboard (python -m m3d.cli leaderboard-all)
CONTRIBUTING.md      how to submit results by pull request
scripts/             verify_submissions.py (the check CI runs on every PR)
.github/workflows/   CI: verify submissions + keep LEADERBOARD.md current
examples/            example participant router + example submissions
tests/               unit + end-to-end tests
docs/                images, the Pareto plot, and the format reference (FORMATS.md)

3. Quick start

Requires Python 3.9+ and nothing else — the toolkit is pure standard library, so it runs on macOS, Linux and Windows with no install. CI tests macOS and Linux on Python 3.9 and 3.12. Only the optional visualization needs matplotlib (pip install -r requirements.txt). Run all commands from the repository root.

Any language, any hardware. A submission is just JSON route files (see docs/FORMATS.md), so you can write your router in any language and run it on anything — CPU, GPU, a cluster, a Mac laptop. The toolkit only reads and scores your output; it never runs your solver. Scoring is deterministic across platforms: it recomputes delay with exact integer arithmetic on the committed benchmark instances, so your local score matches CI's exactly.

# regenerate a tier deterministically (intro -> benchmarks/, hard -> benchmarks_hard/,
# scale -> benchmarks_scale/, ...; `all` builds all six tiers, including the
# ~30-minute stress tier)
python -m m3d.cli generate --tier intro
python -m m3d.cli generate --tier all

# run the baseline router on one case
python -m m3d.cli baseline --case benchmarks/case_01.json --out my.sol.json

# evaluate a submission (legality + delay + ratio vs baseline)
python -m m3d.cli evaluate --case benchmarks/case_01.json --sol my.sol.json --suite benchmarks

# score a full submission for one tier (leaderboard; here the 20-case intro tier)
python -m m3d.cli score-suite --suite benchmarks --submission-dir examples/submissions

# visualize a case (all layers, or one layer with --layer N)
python -m m3d.cli visualize --case benchmarks/case_01.json --sol benchmarks/reference/case_01.sol.json --out case_01.png

# animate: sweep the stack of one case, or sweep the whole suite
python -m m3d.cli animate --mode layers --case benchmarks/case_12.json --sol benchmarks/reference/case_12.sol.json --out layer_sweep.gif
python -m m3d.cli animate --mode suite  --suite benchmarks --out suite_sweep.gif

# print a case summary
python -m m3d.cli info --case benchmarks/case_10.json

# run the tests
python -m unittest discover -s tests -t .

A Makefile wraps the common commands: make generate, make baseline, make score-example, make visualize, make test.


4. How to participate

  1. Read each instance (benchmarks/case_NN.json): grid, layers, delays, cells, pins, and nets.
  2. For each net, produce a tree of routing edges connecting the driver to all sinks, obeying the legality rules above.
  3. Write a submission JSON per case (case_NN.sol.json) in the submission format (below). Put one per case (all 20 for the intro tier) in one directory.
  4. Score locally: python -m m3d.cli score-suite --suite benchmarks --submission-dir <your_dir>.

A complete ranked submission must be legal on every case in the tier. See examples/example_submission.py for a minimal, self-contained router you can copy and replace with your own algorithm — it demonstrates loading, routing on the shared grid, self-checking, and writing a submission.

  1. To appear on the live leaderboard, open a pull request adding your results under submissions/<tier>/<name>/ — see CONTRIBUTING.md and section 5b below.

File formats (summary; full spec in docs/FORMATS.md)

Instance (case_NN.json, format: m3d-instance): grid {width,height,layers}, delay {layer_delay:[...], via_delay}, cells, pins (id, cell, die, x, y, z), nets (id, driver, sinks:[...]), plus generation params and seed.

Submission (format: m3d-submission): instance name and routes, a list of {net, edges} where each edge is a pair of vertices [[x1,y1,z1],[x2,y2,z2]].

Result (format: m3d-result): legal, total_delay, per-net {legal, delay, reasons}, global reasons, and conflict_vertices / conflict_edges for visualization of invalid submissions.

The evaluator independently reconstructs and validates every route and recomputes the delay from the instance; it never trusts participant-reported metrics.


5. Scoring

  • Per case the checker reports the raw total delay it recomputes.

  • The aggregate leaderboard normalizes each case against the baseline so the largest case cannot dominate by size. For a legal case with total s_c and baseline total b_c, the per-case ratio is b_c / s_c (a ratio above 1 beats the baseline). The aggregate is the geometric mean of the ratios:

    aggregate = ( product over cases of (baseline_total / submission_total) ) ** (1 / N)
    

    Higher is better; the baseline scores exactly 1.0. A submission must be legal on every case of the tier to be complete and ranked — otherwise it is marked incomplete with aggregate 0.0.

  • Runtime is recorded separately (pass a {case: seconds} JSON via --runtimes) and never affects the delay score. Leaderboard entries must report it: runtime.json holds the wall-clock seconds of the run that produced each case, with hardware and threads in meta.json (see CONTRIBUTING.md).

The baseline itself is the normalization reference; its per-case totals are in each tier's suite.json (e.g. benchmarks/suite.json).


5b. Leaderboard and the runtime-vs-delay Pareto

To compare several routers on a tier, put each one's solutions (plus an optional runtime.json of {case: seconds}) in its own subdirectory and rank them:

# produce a few submissions for the hard tier (each writes runtime.json)
python -m m3d.cli run-suite --suite benchmarks_hard --router negotiated_fast --out-dir subs/fast
python -m m3d.cli run-suite --suite benchmarks_hard --router negotiated      --out-dir subs/negotiated
python -m m3d.cli run-suite --suite benchmarks_hard --router negotiated2     --out-dir subs/negotiated_x2

# rank them (aggregate score; complete submissions first) and mark the Pareto set
python -m m3d.cli leaderboard --suite benchmarks_hard --submissions-root subs --md board.md

# plot total runtime vs total raw delay, with the Pareto frontier
python -m m3d.cli pareto --suite benchmarks_hard --submissions-root subs --out pareto.png

The ranked leaderboard sorts complete submissions by aggregate score (then by total delay); a submission that is not legal on every case is listed but not ranked. The Pareto plot shows one point per submission — total runtime vs total raw routing delay — and highlights the frontier (you cannot lower delay without spending more time).

runtime vs total delay Pareto

Hard tier: negotiated (faster, higher delay) and negotiated_x2 (best-of-two orders — ~2× the runtime for ~1.5% lower delay) are both Pareto-optimal; negotiated_fast is faster still but illegal on one case, so it is not ranked.

The live leaderboard (submit by PR)

The project leaderboard is at the top of this README and in LEADERBOARD.md; both are built from real, checker-verified entries under submissions/<tier>/<name>/. You get on it by opening a pull request that adds your results — see CONTRIBUTING.md for the step-by-step.

Scores are always recomputed from the submitted route files by the independent checker, so the board cannot be gamed by editing numbers — you rank higher only by submitting better legal routes. CI on every PR re-checks each solution, confirms LEADERBOARD.md and the README block are current (leaderboard-all --check), and blocks submission PRs that touch anything outside submissions/, LEADERBOARD.md and the README's generated leaderboard block. Entries that start from another entry's routes declare derived_from in meta.json and are marked †.

# self-check your submission, then regenerate the board before you commit
python -m m3d.cli score-suite --suite benchmarks_hard --submission-dir submissions/hard/<name>
python -m m3d.cli leaderboard-all          # writes LEADERBOARD.md + README block
make verify-submissions                    # CI's submission checks (CI also runs the tests)

The seed entries under submissions/hard/ are the three negotiated variants shown in the Pareto plot above.

6. The baseline router

m3d/baseline.py is a deliberately simple, deterministic reference: it routes nets one at a time (largest bounding box first), grows each net as a shortest (minimum-delay) tree with multi-source Dijkstra, enforces hard capacity, and uses rip-up-and-reroute when a net is blocked. It is not state of the art; it exists to establish a usable reference score and to certify that generated instances are routable. Beating it is the point.

For the contended hard tier, that simple router is not strong enough (it fails or thrashes), so a second reference — m3d/negotiated.py, a PathFinder-style negotiated-congestion router — certifies feasibility and provides the hard tier's baseline. It routes every net each round allowing temporary overuse, then raises a per-resource history cost on anything overused so nets negotiate away from contention, and (after the first pass) only reroutes the nets touching an overused resource. When uncongested it reduces to per-net shortest paths, so it preserves the delay objective on sparse instances. Both routers are deterministic.


7. Reproducibility and design choices

  • Determinism. The suite uses a fixed master seed (20260923) and a reproducible per-case seed schedule (m3d/suite.py). Generation uses Python's random.Random (Mersenne Twister), stable across CPython versions for a given seed and call sequence. Delays are integers, so scoring is exact.
  • Cross-platform and hardware-agnostic. The toolkit is pure standard library (Python 3.9+); CI runs the tests and submission checks on macOS and Linux across Python 3.9 and 3.12. Because scoring recomputes integer delay on the committed benchmark instances, a submission scores identically on every OS and on any hardware — so participants are free to use GPUs, other languages, or a cluster to produce their route files. (Regenerate benchmarks only if you intend to fork the suite; the released cases and baselines are what everyone is scored against.)
  • Verified feasibility. Every released instance is generated and then routed by the baseline and validated by the independent checker; candidates without a checker-verified legal solution are discarded and regenerated. The verified reference solution lives in benchmarks/reference/, separate from the participant inputs, and doubles as the scoring baseline. (A router's failure is not treated as proof of infeasibility — we only accept an instance once a legal solution is in hand.)
  • Documented simplifications. Cell footprints do not obstruct routing (only other nets' pins do); the delay model is abstract and additive (no electrical effects); capacity is a simple one-net-per-resource model. These keep the challenge correct and reproducible end to end; richer models are natural future extensions.
  • Configurable. Grid size, layer count, cell counts/sizes, pins per cell, net count, fanout distribution, cross-die fraction, locality, and all delays are configurable (m3d/generator.py::GenConfig, m3d/suite.py). The routing layer count and benchmark sizes are intentionally easy to change.

Contributing and issues

Found a bug, a broken case, unclear docs, or a rough edge? Please fix it and open a pull request. Improvements to the toolkit, generator, docs, tests, or tooling are all welcome — no need to ask first for small fixes.

  • Toolkit / bug-fix PRs may touch any file; please keep the tests green (make test) and add a test when you fix a bug.
  • Leaderboard-submission PRs only add your results under submissions/ — see CONTRIBUTING.md. CI keeps those two kinds of PR separate.

If you would rather just report something, open a GitHub issue describing the problem and, if you can, the case or command that triggers it.

License

MIT — see LICENSE.

About

M3D routing challenge: a reproducible EDA routing benchmark for a simplified monolithic-3D stack (generator, checker, scorer, baseline, visualization).

Resources

Contributing

Stars

52 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages