Skip to content

Path-Length Matching

Path-length matching equalises the optical path lengths of a group of routes by splicing squiggle loops into the shorter routes until all routes are equally long.

DoRoutes matches exact placed lengths — the sum of every straight and bend cell's info["length"] along a route — rather than backbone scalar approximations. That matters because routes with different bend counts but identical backbone extents are not the same length: bend arclengths differ from the corner-to-corner straight they replace. DoRoutes also supports group-index–weighted optical lengths for PDKs where bends and straights of different widths have different group indices, so that matching can equalise group delay rather than geometric length.

The implementation reuses kfactory's loop-insertion geometry via an adapter layer, then rips and re-places each route's cells along the updated backbone. All mutations happen in place so caller-held Route references stay valid.

Imports

import gdsfactory as gf
from gdsfactory.gpdk import PDK

import gdsfactoryplus as gfp
dr = gfp.routing.doroutes
from gdsfactoryplus.routing.doroutes.pathlength import LoopPosition, LoopSide

PDK.activate()

STRAIGHT = "straight"
BEND = {"component": "bend_euler", "settings": {"radius": 5}}

Baseline — unmatched routes

We start with two U-shaped Manhattan routes that share the same start-x and stop-x and the same number of interior corners (4 bends each), but take different-depth detours south so their total lengths differ by 30 µm. r1 dips 25 µm below y = 0; r2 dips 40 µm below y = −60 µm.

Coordinates: start/stop are (x, y) tuples in database units (1 dbu = 1 nm for gdsfactory.gpdk, so 100 µm = 100 000 dbu). corners are (x, y) floats in microns.

c_base = gf.Component()

r1_base = dr.add_route_manual(
    c_base,
    (0, 0),
    (100_000, 0),
    corners=[(30.0, 0.0), (30.0, -25.0), (60.0, -25.0), (60.0, 0.0)],
    straight=STRAIGHT,
    bend=BEND,
)
r2_base = dr.add_route_manual(
    c_base,
    (0, -60_000),
    (100_000, -60_000),
    corners=[(30.0, -60.0), (30.0, -100.0), (60.0, -100.0), (60.0, -60.0)],
    straight=STRAIGHT,
    bend=BEND,
)

print(f"r1 length: {r1_base.length:.3f} µm  (n_bend90={r1_base.n_bend90})")
print(f"r2 length: {r2_base.length:.3f} µm  (n_bend90={r2_base.n_bend90})")
print(f"Δ = {abs(r1_base.length - r2_base.length):.3f} µm — unmatched")

dr.util.show_cell(c_base)
r1 length: 143.272 µm  (n_bend90=4)
r2 length: 173.272 µm  (n_bend90=4)
Δ = 30.000 µm — unmatched