ConnectManhattan

class ipkiss3.all.ConnectManhattan

A connector that uses i3.RouteManhattan to connect two ports and returns an instance of i3.RoundedWaveguide (optical ports) or i3.ElectricalWire (electrical ports).

This connector is supposed to be used together with i3.place_and_route.

Note

Electrical ports need to have an angle (not None) for the routing algorithm to work.

Parameters
angle_step: float and number > 0, optional

angle step for rounding

bend_radius: float and number > 0, optional

bend radius for the auto-generated bends

control_points: list, optional

Control the routing by passing either a list of points through which the route has to pass,or a list of i3.H / i3.V instances.

end_straight: float and Real, number and number >= 0, optional

The length of the straight end section of the route

min_spacing: float and Real, number and number >= 0, optional

minimal spacing between parallel sections of the route

min_straight: float and Real, number and number >= 0, optional

The minimum length of any straight sections in the route

rounding_algorithm: optional

Rounding algorithm (ShapeRound, ShapeRoundAdiabaticSpline, …). Takes a shape as input and returns a new (rounded) shape.

start_straight: float and Real, number and number >= 0, optional

The length of the straight start section of the route

trace_template: ( PCell and _TraceTemplate ), optional, *None allowed*

Trace template to use for the waveguide between the two ports, when the ports have a different template, transitions will be added. When this property is left unspecified/None the trace_template of the start_port will be used

Examples

"""
This example illustrations how you can use the control_points property to guide
your waveguide around an obstacle.
"""
from technologies import silicon_photonics  # noqa: F401
from picazzo3.fibcoup.curved import FiberCouplerCurvedGrating
from ipkiss3 import all as i3
import matplotlib.pyplot as plt

# Placing the components in a circuit
gr = FiberCouplerCurvedGrating()
control_points = [(-40, 20), (0, 30), (50, 20)]
circuit = i3.Circuit(
    insts={"gr": gr, "grb1": gr, "grb2": gr},
    specs=[
        i3.Place("gr", position=(0, 0)),
        i3.Place("grb1", position=(-100, 0)),
        i3.Place("grb2", position=(+100, 0), angle=180),
        i3.ConnectManhattan(
            "grb1:out",
            "grb2:out",
            control_points=control_points,
        ),
    ],
)
circuit_layout = circuit.Layout()
circuit_layout.visualize(show=False)
plt.scatter([cp[0] for cp in control_points], [cp[1] for cp in control_points], c="C1", s=80, marker="x")
plt.show()
../../../_images/ipkiss3-all-ConnectManhattan-11.png
from technologies import silicon_photonics  # noqa: F401
from picazzo3.fibcoup.curved import FiberCouplerCurvedGrating
from ipkiss3 import all as i3
import matplotlib.pyplot as plt

class BondPad(i3.PCell):
    class Layout(i3.LayoutView):
        size = i3.Size2Property(default=(50.0, 50.0), doc="Size of the bondpad")
        metal_layer = i3.LayerProperty(default=i3.TECH.PPLAYER.M1.LINE, doc="Metal used for the bondpad")

        def _generate_elements(self, elems):
            elems += i3.Rectangle(layer=self.metal_layer, box_size=self.size)
            return elems

        def _generate_ports(self, ports):
            ports += i3.ElectricalPort(
                name="m1",
                position=(0.0, 0.0),
                shape=self.size,
                process=self.metal_layer.process,
                angle=0,  # adding dummy angles so that the connector functions work
            )
            return ports

# Placing the components in a circuit
bp = BondPad()
bp_layout = bp.Layout(size=(50, 50))
gr = FiberCouplerCurvedGrating()

control_points = [(-40, 20), (50, 0), (100, -50)]

wire_template = i3.ElectricalWireTemplate()
wire_template.Layout(width=5.0, layer=bp_layout.metal_layer)

circuit = i3.Circuit(
    insts={"gr": gr, "gr2": gr, "b1": bp, "b2": bp},
    specs=[
        i3.Place("gr", position=(0, 0)),
        i3.Place("gr2", position=(100, 0)),
        i3.Place("b1", position=(-75, 0)),
        i3.Place("b2", position=(+150, 0)),
        i3.ConnectManhattan(
            "b1:m1",
            "b2:m1",
            control_points=control_points,
            rounding_algorithm=None,
            trace_template=wire_template,
        ),
    ],
)

circuit_layout = circuit.Layout()
circuit_layout.visualize(show=False)
plt.scatter([cp[0] for cp in control_points], [cp[1] for cp in control_points], c="C1", s=80, marker="x")
plt.show()
../../../_images/ipkiss3-all-ConnectManhattan-21.png
from technologies import silicon_photonics  # noqa: F401
import ipkiss3.all as i3
from picazzo3.traces.rib_wg.trace import RibWaveguideTemplate

# Instantiate trace templates to use for the ports
tt1 = RibWaveguideTemplate()
tt1.Layout(core_width=0.5)

# Define some ports
port1 = i3.OpticalPort(position=(0.0, 0.0), angle=0.0, trace_template=tt1)
port2 = i3.OpticalPort(position=(100.0, 100.0), angle=180.0, trace_template=tt1)
# Ports with non-manhattan angles:
port3 = i3.OpticalPort(position=(0.0, 0.0), angle=-20.0, trace_template=tt1)
port4 = i3.OpticalPort(position=(50.0, 70.0), angle=100.0, trace_template=tt1)

# Create the connection
wg = i3.ConnectManhattan.connect(port1, port2, name="manhattan_connection", bend_radius=10.0)
lo = wg.get_default_view(i3.LayoutView)
lo.visualize()

wg = i3.ConnectManhattan.connect(port3, port4, name="manhattan_connection2", bend_radius=10.0)
lo = wg.get_default_view(i3.LayoutView)
lo.visualize()
../../../_images/ipkiss3-all-ConnectManhattan-3_001.png
../../../_images/ipkiss3-all-ConnectManhattan-3_011.png
import ipkiss3.all as i3

input_port = i3.OpticalPort(name="in", position=(0.0, 0.0), angle=0.0)
output_port = i3.OpticalPort(name="out", position=(-40.0, 40.0), angle=180.0)
bend_radius = 7.0

ra = i3.ShapeRound
wg = i3.ConnectManhattan.connect(
    start_port=input_port, end_port=output_port, bend_radius=bend_radius, rounding_algorithm=ra
)
wg.get_default_view(i3.LayoutView).visualize()

ra = i3.SplineRoundingAlgorithm(adiabatic_angles=(15, 15))
wg = i3.ConnectManhattan.connect(
    start_port=input_port, end_port=output_port, bend_radius=bend_radius, rounding_algorithm=ra
)
wg.get_default_view(i3.LayoutView).visualize()
../../../_images/ipkiss3-all-ConnectManhattan-4_001.png
../../../_images/ipkiss3-all-ConnectManhattan-4_011.png
from technologies import silicon_photonics  # noqa: F401
import ipkiss3.all as i3
from picazzo3.traces.rib_wg.trace import RibWaveguideTemplate

# Instantiate trace templates to use for the ports
tt1 = RibWaveguideTemplate()
tt1.Layout(core_width=0.5)

# Define some ports
port1 = i3.OpticalPort(position=(0.0, 0.0), angle=0.0, trace_template=tt1)
port2 = i3.OpticalPort(position=(100.0, 100.0), angle=180.0, trace_template=tt1)
# Ports with non-manhattan angles:
port3 = i3.OpticalPort(position=(0.0, 0.0), angle=-20.0, trace_template=tt1)
port4 = i3.OpticalPort(position=(50.0, 70.0), angle=100.0, trace_template=tt1)

# Create the connection with control_points.
# The route will go through point (50, 50):
wg = i3.ConnectManhattan.connect(
    port1, port2, name="manhattan_connection", control_points=[(50, 50)], bend_radius=10.0
)
lo = wg.get_default_view(i3.LayoutView)
lo.visualize()

# Another option for control_points is to describe the horizontal and vertical parts of the route.
# You can do this in the following way:
# [V(40)] describes that the route should be vertical at x = 40.
wg = i3.ConnectManhattan.connect(
    port1, port2, name="manhattan_connection2", control_points=[i3.V(40)], bend_radius=10.0
)
lo = wg.get_default_view(i3.LayoutView)
lo.visualize()

# [V(100), H(100)] determines that the route should be vertical at x = 100 and then horizontal at y = 100.
wg = i3.ConnectManhattan.connect(
    port3, port4, name="manhattan_connection3", control_points=[i3.V(100), i3.H(100)], bend_radius=10.0
)
lo = wg.get_default_view(i3.LayoutView)
lo.visualize()

# Note 1: These two types of control points don't mix: [V(20), (50, 50), H(10)] is not allowed.
# Note 2: When using more than one horizontal and/or vertical control points an H must always follow a V,
# and vice versa. You can't pass two of the same type right after each other. For instance:
# [V(20), V(30), H(10)] is not allowed, [V(20), H(20), V(30), H(10)] is allowed.
../../../_images/ipkiss3-all-ConnectManhattan-5_001.png
../../../_images/ipkiss3-all-ConnectManhattan-5_011.png
../../../_images/ipkiss3-all-ConnectManhattan-5_021.png
from technologies import silicon_photonics  # noqa: F401
import ipkiss3.all as i3
from picazzo3.traces.rib_wg.trace import RibWaveguideTemplate
from ipkiss3.all import START, END

# Instantiate trace templates to use for the ports
tt1 = RibWaveguideTemplate()
tt1.Layout(core_width=0.5)

# Define some ports
port1 = i3.OpticalPort(position=(0.0, 0.0), angle=0.0, trace_template=tt1)
port2 = i3.OpticalPort(position=(100.0, 100.0), angle=180.0, trace_template=tt1)

control_points = [
    START + (30, 10),  # control point at (30, 10) relative to the start port
    (50, 50),  # control point at (50, 50) relative to (0, 0)
    END - (30, 10),
]  # control point at (-30, -10) relative to the end port

wg = i3.ConnectManhattan.connect(
    port1, port2, name="manhattan_connection", control_points=control_points, bend_radius=5.0
)
lo = wg.get_default_view(i3.LayoutView)
lo.visualize()

# Similarily it is possible to define relative i3.H and i3.V control points
wg = i3.ConnectManhattan.connect(
    port1, port2, name="manhattan_connection2", control_points=[i3.H(END - 40)], bend_radius=5.0
)
lo = wg.get_default_view(i3.LayoutView)
lo.visualize()
../../../_images/ipkiss3-all-ConnectManhattan-6_001.png
../../../_images/ipkiss3-all-ConnectManhattan-6_011.png

When required ConnectManhattan will introduce transitions to create a valid connection.:

from technologies import silicon_photonics  # noqa: F401
import ipkiss3.all as i3
from picazzo3.traces.rib_wg.trace import RibWaveguideTemplate
from picazzo3.traces.wire_wg.trace import WireWaveguideTemplate

# Instantiate trace templates to use for the ports
tt_start = RibWaveguideTemplate()
tt_start.Layout(core_width=0.5)

tt_end = WireWaveguideTemplate()
tt_end.Layout(core_width=0.5)

start_port = i3.OpticalPort(position=(0.0, 0.0), angle=0.0, trace_template=tt_start)
end_port = i3.OpticalPort(position=(40.0, 40.0), angle=180.0, trace_template=tt_end)

# The connecting waveguide will use the trace_template specified
# on the start_port and introduce a transition at the end
# to connect properly with the end_port.
wg = i3.ConnectManhattan.connect(start_port, end_port, bend_radius=10.0)
lo = wg.get_default_view(i3.LayoutView)
lo.visualize(annotate=True)
../../../_images/ipkiss3-all-ConnectManhattan-71.png

By default ConnectManhattan will use the trace_template from the start_port for the connecting waveguide, but this can be changed using the trace_template property:

def __example7_transitioning(self):
    from technologies import silicon_photonics  # noqa: F401
    import ipkiss3.all as i3
    from picazzo3.traces.rib_wg.trace import RibWaveguideTemplate
    from picazzo3.traces.wire_wg.trace import WireWaveguideTemplate

    # Instantiate trace templates to use for the ports
    tt_start = RibWaveguideTemplate()
    tt_start.Layout(core_width=0.5)

    tt_end = WireWaveguideTemplate()
    tt_end.Layout(core_width=0.5)

    start_port = i3.OpticalPort(position=(0.0, 0.0), angle=0.0, trace_template=tt_start)
    end_port = i3.OpticalPort(position=(40.0, 40.0), angle=180.0, trace_template=tt_end)

    # use the trace_template of the end_port
    # this will add the transition at the start port rather
    # then at the end port.
    wg = i3.ConnectManhattan.connect(start_port, end_port, bend_radius=10.0, trace_template=tt_end)
    lo = wg.get_default_view(i3.LayoutView)
    lo.visualize(annotate=True)
from technologies import silicon_photonics  # noqa: F401
import ipkiss3.all as i3

# Define some trace templates
tt = i3.ElectricalWireTemplate()
tt.Layout(width=3.0)

tt2 = i3.ElectricalWireTemplate()
tt2.Layout(width=1.0)

# Define some ports
port1 = i3.ElectricalPort(position=(0.0, 0.0), angle=0.0, trace_template=tt)
port2 = i3.ElectricalPort(position=(50.0, 50.0), angle=180.0)

port3 = i3.ElectricalPort(position=(0.0, 0.0), angle=-90.0)
port4 = i3.ElectricalPort(position=(30.0, 20.0), angle=90.0)

# Make a manhattan connector
connector = i3.ConnectManhattan
# Create the connection
wg = connector.connect(port1, port2, name="manhattan_electrical", control_points=[(20, 20)])
lo = wg.get_default_view(i3.LayoutView)
lo.visualize()

wg = connector.connect(port3, port4, name="manhattan_electrical2", trace_template=tt2)
lo = wg.get_default_view(i3.LayoutView)
lo.visualize()
../../../_images/ipkiss3-all-ConnectManhattan-9_001.png
../../../_images/ipkiss3-all-ConnectManhattan-9_011.png