Bundle Routing with Waveguides

Introduction

Routing a set of ports from one side of your design to another is not always straightforward, especially if there is limited space or you need to avoid other components. In Designing a splitter tree, an introduction is given on how to connect two ports with each other using a single connector.

Connecting multiple ports in a similar fashion, with a certain waveguide separation or pitch, can be done in Luceda IPKISS with the i3.ConnectManhattanBundle connector. Connectors are usually provided in the context of placement and routing of instances using i3.place_and_route (or i3.Circuit, which internally calls i3.place_and_route).

Simple bundle routing

Let’s look into an example of how to use i3.ConnectManhattanBundle. Imagine you have a design with a splitter tree that you want to connect to a number of grating couplers.

../../../_images/bundle_empty.png

Starting with a bundle with simple S-bend fanouts and a waveguide array with a pitch of 5.0 micron and a bend radius of 10 micron:

bend_radius = 10.0
pitch = 5.0

luceda-academy/training/topical_training/waveguide_bundle/example_waveguide_bundle.py
# Manhattan Bundle to connect the outputs of the splitter tree to the output grating couplers

bundle = [
    i3.ConnectManhattanBundle(
        connections=[(f"tree:out{16 - n}", f"gr_out_{n}:out") for n in range(16)],
        start_fanout=i3.SBendFanout(max_sbend_angle=80.0),
        end_fanout=i3.SBendFanout(max_sbend_angle=80.0),
        pitch=pitch,
        bend_radius=bend_radius,
    )
]

Here you specify the connections, i.e. which port of the splitter tree is connected to which grating’s output port. You can also specify what kind of fanout should be at the start and end of the bundle. In this case, we use i3.SBendFanout. This fanout can be customized by setting its properties, such as the pitch of the waveguide array, the max_sbend_angle the bend_radius, the min_spacing, etc.

The result looks as follows:

../../../_images/bundle_no_obstacles.png

Bundle routing with obstacles avoidance

Now, imagine that there are a couple of other components in your design that the bundle needs to avoid. For instance:

../../../_images/bundle_default.png

The parameters of the bundle need to be adjusted so that all the other components can be avoided. Let’s see how to do that, starting with the fanouts.

Fanouts

i3.ConnectManhattanBundle allows us to specify the start and the end fanouts independently.

The start_fanout is the fanout at the output of the splitter tree. Instead of having a symmetric fanout, the end needs to be shifted completely to the top. Ideally, the waveguide connected to the topmost port of the splitter tree (tree:out16) should go straight as indicated by the red line on the image below. This can be achieved by defining the reference port. This parameter determines which port the fanout should be aligned with. If it isn’t defined, the center point of the input ports is used as the reference. In addition, we need to tweak the max_sbend_angle parameter to increase the maximum angle the S-bends are allowed to make. This ensures that the bundle is more compact and that the waveguides don’t overlap with the obstacle.

For the end_fanout, the center of the fanout needs to be between the two obstacles at the top. Or rather, the end_position of the fanout needs to be at (150, 600) indicated by the blue cross on the image below.

bend_radius = 10.0
pitch = 5.0

luceda-academy/training/topical_training/waveguide_bundle/example_waveguide_bundle_obstacles.py
# First, let's fix the fanouts

bundle = [
    i3.ConnectManhattanBundle(
        connections=[(f"tree:out{16 - n}", f"gr_out_{n}:out") for n in range(16)],
        start_fanout=i3.SBendFanout(max_sbend_angle=85.0, reference="tree:out16"),
        end_fanout=i3.SBendFanout(max_sbend_angle=80, end_position=(150, 600)),
        pitch=pitch,
        bend_radius=bend_radius,
    )
]

This results in the following.

../../../_images/bundle_fanouts.png

Next, let’s see how to avoid the obstacles by modifying the route of the Manhattan waveguide array.

Waveguide Array

Controlling the route of the Manhattan waveguide array can be done with horizontal and vertical control_points (see i3.H and i3.V). You can also choose which of the waveguides these control_points apply to with control_point_reference. The control_point_reference is the port connecting to the waveguide that will be used as a reference. These minimal adjustments will result in a bundle that follows the route that you want.

The waveguide connected to the topmost port of the splitter (tree:out16) needs to first go vertically to the right of obstacle1 and then horizontally above obstacle1 as indicated by the vertical and horizontal dashed lines in the image below.

luceda-academy/training/topical_training/waveguide_bundle/example_waveguide_bundle_obstacles.py
# Next, the array of waveguides
# We use the properties control_point and control_point reference to adjust the routing

bundle = [
    i3.ConnectManhattanBundle(
        connections=[(f"tree:out{16 - n}", f"gr_out_{n}:out") for n in range(16)],
        start_fanout=i3.SBendFanout(max_sbend_angle=85.0, reference="tree:out16"),
        end_fanout=i3.SBendFanout(max_sbend_angle=80, end_position=(150, 600)),
        pitch=pitch,
        bend_radius=bend_radius,
        control_points=[i3.V(12.5, relative_to="obstacle1@E"), i3.H(15, relative_to="obstacle1@N")],
        control_point_reference="tree:out16",
    )
]

This results in the following:

../../../_images/bundle_array.png

Finally, by tweaking the bundle’s fanouts and array, we have obtained a bundle connector that carefully avoids obstacles.