Skip to content

Bundle From Corners

add_bundle_manual is the bundle (multi-wire) counterpart of add_route_manual. It performs a fan-in at each end so the N wires converge onto a single bundle line, then routes that bundle through user-specified corners or steps.

Reach for it when:

  • the floorplan dictates an exact route shape (a routing channel, fence regions, hand-drawn paths),
  • the same routing recipe needs to apply to many similarly-shaped layouts (use steps= for placement-independent recipes), or
  • A* routing is overkill for a route you already know the shape of.

This is optical routing: bends are bend_euler at the PDK minimum radius (5 µm for gdsfactory.gpdk).

Imports

import gdsfactory as gf
from gdsfactory.gpdk import PDK

import gdsfactoryplus as gfp
dr = gfp.routing.doroutes

PDK.activate()

A 5-Port Test Frame

dr.pcells.fanout_frame2(transition="ew") puts 5 east-facing inputs on the left edge and 5 west-facing outputs on the right edge of a 100 × 200 µm frame — the same layout used in the A* bundle routing tutorial, so you can compare the algorithmic and corner-based approaches side by side.

c = gf.Component()
ref = c << dr.pcells.fanout_frame2(transition="ew", add_frame=True)
c.add_ports(ref)
dr.util.show_cell(c)

Bundle Through Explicit Corners

Pass corners=[(x1, y1), (x2, y2), ...] to route the bundle through a sequence of absolute coordinate points (in microns).

The bundle's fan-in anchors at the port centroid by default — for this 5-port frame that's (1, 100) on the input side, so the bundle exits the input fan-in at roughly (13, 100) heading east. Each corner you list must be axis-aligned with the previous (manhattan routing), so corners describe a sequence of 90° turns from the bundle exit to the bundle stop on the other side.

The 4-corner Z-shape below detours the bundle through y=30: south at x=50, east at y=30, north at x=80 back to the output bundle line.

c = gf.Component()
ref = c << dr.pcells.fanout_frame2(transition="ew", add_frame=True)
c.add_ports(ref)

# Bundle exits at (~13, 100, east) and stops at (~87, 75, east).
# 4-corner Z: south, east, south, then back up to the output centroid y=75.
result = dr.add_bundle_manual(
    component=c,
    ports1=[p for p in c.ports if str(p.name).startswith("in")],
    ports2=[p for p in c.ports if str(p.name).startswith("out")],
    corners=[
        (50, 100),  # turn south at (50, 100) µm
        (50, 30),  # turn east at (50, 30)
        (80, 30),  # turn north at (80, 30)
        (80, 75),  # back to output centroid y=75; final east leg is implicit
    ],
    spacing=1.0,
    straight="straight",
    bend={"component": "bend_euler", "settings": {"radius": 5}},
)
dr.util.show_cell(c)