Ejemplo n.º 1
0
def add_electrical_pads_top(component: Component, **kwargs) -> Component:
    """connects component electrical ports with pad array at the top

    Args:
        component:
        pad: pad element
        spacing: pad array (x, y) spacing
        width: pad width
        height: pad height
        layer: pad layer
    """
    c = Component(f"{component.name}_e")
    ports = component.get_ports_list(port_type="dc")
    c << component
    pads = c << pad_array(n=len(ports), port_list=["S"], **kwargs)
    pads.x = component.x
    pads.y = component.ymax + 100
    ports_pads = list(pads.ports.values())
    for p1, p2 in zip(ports_pads, ports):
        c.add(connect_electrical_shortest_path(p1, p2))

    c.ports = component.ports
    for port in ports:
        c.ports.pop(port.name)
    return c
Ejemplo n.º 2
0
def pad(
    width: int = 100, height: int = 100, layer: Tuple[int, int] = LAYER.M3
) -> Component:
    """rectangular pad with 4 ports (N, S, E, W)

    Args:
        width: pad width
        height: pad height
        layer: pad layer


    .. plot::
      :include-source:

      import pp

      c = pp.c.pad(width=100, height=100, layer=pp.LAYER.M3)
      pp.plotgds(c)

    """
    c = Component()
    _c = compass(size=(width, height), layer=layer).ref()
    c.add(_c)
    c.absorb(_c)
    c.ports = _c.ports
    return c
Ejemplo n.º 3
0
def add_labels(
    component: Component,
    port_type: str = "dc",
    get_label_function: Callable = get_input_label_electrical,
    layer_label: Layer = pp.LAYER.LABEL,
    gc: Optional[Component] = None,
) -> Component:
    """Add labels a particular type of ports

    Args:
        component: to add labels to
        port_type: type of port ('dc', 'optical', 'electrical')
        get_label_function: function to get label
        layer_label: layer_label

    Returns:
        original component with labels

    """
    ports = component.get_ports_list(port_type=port_type)

    for i, port in enumerate(ports):
        label = get_label_function(
            port=port,
            gc=gc,
            gc_index=i,
            component_name=component.name,
            layer_label=layer_label,
        )
        component.add(label)

    return component
Ejemplo n.º 4
0
def add_grating_couplers(
    component: Component,
    grating_coupler=grating_coupler_te,
    layer_label=pp.LAYER.LABEL,
    gc_port_name: str = "W0",
    get_input_labels_function=get_input_labels,
):
    """Return component with grating couplers and labels."""

    cnew = Component(name=component.name + "_c")
    cnew.add_ref(component)
    grating_coupler = pp.call_if_func(grating_coupler)

    io_gratings = []
    for port in component.ports.values():
        gc_ref = grating_coupler.ref()
        gc_ref.connect(list(gc_ref.ports.values())[0], port)
        io_gratings.append(gc_ref)
        cnew.add(gc_ref)

    labels = get_input_labels_function(
        io_gratings,
        list(component.ports.values()),
        component_name=component.name,
        layer_label=layer_label,
        gc_port_name=gc_port_name,
    )
    cnew.add(labels)
    return cnew
Ejemplo n.º 5
0
def add_trenches(
    c: Component,
    sstw: float = 2.0,
    trench_width: float = 0.5,
    trench_keep_out: float = 2.0,
    trenches: List[Dict[str, int]] = [
        {
            "nb_segments": 2,
            "lane": 1,
            "x_start_offset": 0
        },
        {
            "nb_segments": 2,
            "lane": -1,
            "x_start_offset": 0
        },
    ],
    layer_trench: Tuple[int, int] = LAYER.DEEPTRENCH,
) -> Component:
    """
    Add trenches to a waveguide-heater-like component
    """

    heater_width = c.settings["heater_width"]
    heater_spacing = c.settings["heater_spacing"]
    width = c.settings["width"]
    length = c.settings["length"]

    a = heater_spacing + (width + heater_width) / 2

    # Add trenches
    if trench_width and trench_width > 0:
        tko = trench_keep_out

        for trench in trenches:
            lane = trench["lane"]
            td = tko + a + (trench_width + heater_width) / 2
            y = np.sign(lane) * (td + (abs(lane) - 1) * (trench_width + tko))
            x_start_offset = trench["x_start_offset"]

            if "segments" not in trench:
                nb_segments = trench["nb_segments"]
                trench_length = (length -
                                 (nb_segments - 1) * sstw) / nb_segments
                segments = [trench_length] * nb_segments
            else:
                segments = trench["segments"]
            x = x_start_offset
            for i, trench_length in enumerate(segments):
                trench = hline(length=trench_length,
                               width=trench_width,
                               layer=layer_trench)
                _trench = trench.ref(port_id="W0",
                                     position=c.ports["W0"].position + (x, y))
                c.add(_trench)
                c.absorb(_trench)
                x += trench_length + sstw

    return c
Ejemplo n.º 6
0
def tlm(
    width: float = 11.0,
    height: float = 11.0,
    layers: List[Tuple[int, int]] = [LAYER.M1, LAYER.M2, LAYER.M3],
    vias: List[Any] = [via2, via3],
) -> Component:
    """
    Rectangular transition thru metal layers

    Args:
        name: component name
        width, height: rectangle parameters
        layers: layers on which to draw rectangles
        vias: vias to use to fill the rectangles

    Returns
        <Component>
    """

    # assert len(layers) - 1 == len(vias), "tlm: There should be N layers for N-1 vias"

    a = width / 2
    b = height / 2
    rect_pts = [(-a, -b), (a, -b), (a, b), (-a, b)]

    c = Component()
    # Add metal rectangles
    for layer in layers:
        c.add_polygon(rect_pts, layer=layer)

    # Add vias
    for via in vias:
        via = via() if callable(via) else via

        w = via.info["width"]
        h = via.info["height"]
        g = via.info["clearance"]
        period = via.info["period"]

        nb_vias_x = (width - w - 2 * g) / period + 1
        nb_vias_y = (height - h - 2 * g) / period + 1

        nb_vias_x = int(floor(nb_vias_x))
        nb_vias_y = int(floor(nb_vias_y))

        cw = (width - (nb_vias_x - 1) * period - w) / 2
        ch = (height - (nb_vias_y - 1) * period - h) / 2

        x0 = -a + cw + w / 2
        y0 = -b + ch + h / 2

        for i in range(nb_vias_x):
            for j in range(nb_vias_y):
                c.add(via.ref(position=(x0 + i * period, y0 + j * period)))

    return c
Ejemplo n.º 7
0
def test_connect_bundle_u_indirect(dy=-200, angle=180):
    xs1 = [-100, -90, -80, -55, -35] + [200, 210, 240]
    axis = "X" if angle in [0, 180] else "Y"

    pitch = 10.0
    N = len(xs1)
    xs2 = [50 + i * pitch for i in range(N)]

    a1 = angle
    a2 = a1 + 180

    if axis == "X":
        ports1 = [
            Port("top_{}".format(i), (0, xs1[i]), 0.5, a1) for i in range(N)
        ]

        ports2 = [
            Port("bottom_{}".format(i), (dy, xs2[i]), 0.5, a2)
            for i in range(N)
        ]

    else:
        ports1 = [
            Port("top_{}".format(i), (xs1[i], 0), 0.5, a1) for i in range(N)
        ]

        ports2 = [
            Port("bottom_{}".format(i), (xs2[i], dy), 0.5, a2)
            for i in range(N)
        ]

    top_cell = Component("connect_bundle_u_indirect")
    routes = connect_bundle(ports1, ports2)
    lengths = [
        341.41592653589794,
        341.41592653589794,
        341.41592653589794,
        326.41592653589794,
        316.41592653589794,
        291.41592653589794,
        291.41592653589794,
        311.41592653589794,
    ]

    for route, length in zip(routes, lengths):
        # print(route.parent.length)
        assert np.isclose(route.parent.length, length)

    top_cell.add(routes)

    return top_cell
Ejemplo n.º 8
0
def demo_connect_bundle():
    """ combines all the connect_bundle tests """

    y = 400.0
    x = 500
    y0 = 900
    dy = 200.0
    c = Component("connect_bundle")
    for j, s in enumerate([-1, 1]):
        for i, angle in enumerate([0, 90, 180, 270]):
            c2 = test_connect_bundle_u_indirect(dy=s * dy, angle=angle)
            c2ref = c2.ref(position=(i * x, j * y))
            c.add(c2ref)

            c2 = test_connect_bundle_udirect(dy=s * dy, angle=angle)
            c2ref = c2.ref(position=(i * x, j * y + y0))
            c.add(c2ref)

    for i, config in enumerate(["A", "B", "C", "D"]):
        c2 = test_connect_corner(config=config)
        c2ref = c2.ref(position=(i * x, 1700))
        c.add(c2ref)

    c2 = test_facing_ports()
    c2ref = c2.ref(position=(800, 1820))
    c.add(c2ref)

    return c
 def top_level():
     cmp = Component()
     _dummy_t = dummy()
     sides = ["north", "south", "east", "west"]
     positions = [(0, 0), (400, 0), (400, 400), (0, 400)]
     for pos, side in zip(positions, sides):
         dummy_ref = _dummy_t.ref(position=pos)
         cmp.add(dummy_ref)
         conns, ports = route_ports_to_side(dummy_ref, side)
         for e in conns:
             cmp.add(e)
         for i, p in enumerate(ports):
             cmp.add_port(name="{}{}".format(side[0], i), port=p)
     return cmp
Ejemplo n.º 10
0
def test_connect_bundle_udirect(dy=200, angle=270):

    xs1 = [-100, -90, -80, -55, -35, 24, 0] + [200, 210, 240]

    axis = "X" if angle in [0, 180] else "Y"

    pitch = 10.0
    N = len(xs1)
    xs2 = [50 + i * pitch for i in range(N)]

    if axis == "X":
        ports1 = [
            Port("top_{}".format(i), (0, xs1[i]), 0.5, angle) for i in range(N)
        ]

        ports2 = [
            Port("bottom_{}".format(i), (dy, xs2[i]), 0.5, angle)
            for i in range(N)
        ]

    else:
        ports1 = [
            Port("top_{}".format(i), (xs1[i], 0), 0.5, angle) for i in range(N)
        ]

        ports2 = [
            Port("bottom_{}".format(i), (xs2[i], dy), 0.5, angle)
            for i in range(N)
        ]

    top_cell = Component(name="connect_bundle_udirect")
    routes = connect_bundle(ports1, ports2)
    lengths = [
        237.4359265358979,
        281.4359265358979,
        336.4359265358979,
        376.4359265358979,
        421.4359265358979,
        451.4359265358979,
        481.4359265358979,
        271.4359265358979,
    ]

    for route, length in zip(routes, lengths):
        # print(route.parent.length)
        assert np.isclose(route.parent.length, length)

    top_cell.add(routes)
    return top_cell
def add_electrical_pads(component: Component, rotation=180, **kwargs):
    """add compnent with top electrical pads and routes
    Args:
        component: Component,
        pad_spacing: float = 150.,
        pad: Callable = pad,
        fanout_length: Optional[int] = None,
        max_y0_optical: None = None,
        waveguide_separation: float = 4.0,
        bend_radius: float = 0.1,
        connected_port_list_ids: None = None,
        n_ports: int = 1,
        excluded_ports: List[Any] = [],
        pad_indices: None = None,
        route_filter: Callable = connect_elec_waypoints,
        port_name: str = "W",
        pad_rotation: int = -90,
        x_pad_offset: int = 0,
        port_labels: None = None,
        select_ports: Callable = select_electrical_ports,

    """

    c = Component(f"{component.name}_pad")
    cr = rotate(component, rotation)

    elements, pads, _ = route_pad_array(
        component=cr,
        **kwargs,
    )

    c << cr
    for e in elements:
        c.add(e)
    for e in pads:
        c.add(e)

    for pname, p in cr.ports.items():
        if p.port_type == "optical":
            c.add_port(pname, port=p)

    return c.rotate(angle=-rotation)
Ejemplo n.º 12
0
def _arbitrary_straight_waveguide(length, windows):
    """
    Args:
        length: length
        windows: [(y_start, y_stop, layer), ...]
    """
    md5 = hashlib.md5()
    for e in windows:
        md5.update(str(e).encode())

    component = Component()
    component.name = "ARB_SW_L{}_HASH{}".format(length, md5.hexdigest())
    y_min, y_max, layer0 = windows[0]
    y_min, y_max = min(y_min, y_max), max(y_min, y_max)

    # Add one port on each side centered at y=0
    for y_start, y_stop, layer in windows:
        w = abs(y_stop - y_start)
        y = (y_stop + y_start) / 2
        _wg = hline(length=length, width=w, layer=layer).ref()
        _wg.movey(y)
        component.add(_wg)
        component.absorb(_wg)
        y_min = min(y_stop, y_start, y_min)
        y_max = max(y_stop, y_start, y_max)
    width = y_max - y_min

    component.add_port(name="W0",
                       midpoint=[0, 0],
                       width=width,
                       orientation=180,
                       layer=layer0)
    component.add_port(name="E0",
                       midpoint=[length, 0],
                       width=width,
                       orientation=0,
                       layer=layer0)

    return component
Ejemplo n.º 13
0
def import_phidl_component(component: Device, **kwargs) -> Component:
    """ returns a gdsfactory Component from a phidl Device or function
    """
    D = call_if_func(component, **kwargs)
    D_copy = Component(name=D._internal_name)
    D_copy.info = copy.deepcopy(D.info)
    for ref in D.references:
        new_ref = ComponentReference(
            device=ref.parent,
            origin=ref.origin,
            rotation=ref.rotation,
            magnification=ref.magnification,
            x_reflection=ref.x_reflection,
        )
        new_ref.owner = D_copy
        D_copy.add(new_ref)
        for alias_name, alias_ref in D.aliases.items():
            if alias_ref == ref:
                D_copy.aliases[alias_name] = new_ref

    for p in D.ports.values():
        D_copy.add_port(
            port=Port(
                name=p.name,
                midpoint=p.midpoint,
                width=p.width,
                orientation=p.orientation,
                parent=p.parent,
            )
        )
    for poly in D.polygons:
        D_copy.add_polygon(poly)
    for label in D.labels:
        D_copy.add_label(
            text=label.text,
            position=label.position,
            layer=(label.layer, label.texttype),
        )
    return D_copy
Ejemplo n.º 14
0
def test_facing_ports():
    dy = 200.0
    xs1 = [-500, -300, -100, -90, -80, -55, -35, 200, 210, 240, 500, 650]

    pitch = 10.0
    N = len(xs1)
    xs2 = [-20 + i * pitch for i in range(N // 2)]
    xs2 += [400 + i * pitch for i in range(N // 2)]

    a1 = 90
    a2 = a1 + 180

    ports1 = [Port("top_{}".format(i), (xs1[i], 0), 0.5, a1) for i in range(N)]
    ports2 = [
        Port("bottom_{}".format(i), (xs2[i], dy), 0.5, a2) for i in range(N)
    ]

    top_cell = Component("test_facing_ports")
    routes = connect_bundle(ports1, ports2)
    lengths = [
        671.4159265358979,
        481.41592653589794,
        291.41592653589794,
        291.41592653589794,
        291.41592653589794,
        276.41592653589794,
        626.4159265358979,
        401.41592653589794,
        401.41592653589794,
        381.41592653589794,
        251.41592653589794,
        391.41592653589794,
    ]
    for route, length in zip(routes, lengths):
        # print(route.parent.length)
        assert np.isclose(route["settings"]["length"], length)
        top_cell.add(route["references"])

    return top_cell
Ejemplo n.º 15
0
def test_connect_bundle_u_indirect(dy=-200, angle=180):

    xs1 = [-100, -90, -80, -55, -35] + [200, 210, 240]

    axis = "X" if angle in [0, 180] else "Y"

    pitch = 10.0
    N = len(xs1)
    xs2 = [50 + i * pitch for i in range(N)]

    a1 = angle
    a2 = a1 + 180

    if axis == "X":
        ports1 = [
            Port("top_{}".format(i), (0, xs1[i]), 0.5, a1) for i in range(N)
        ]

        ports2 = [
            Port("bottom_{}".format(i), (dy, xs2[i]), 0.5, a2)
            for i in range(N)
        ]

    else:
        ports1 = [
            Port("top_{}".format(i), (xs1[i], 0), 0.5, a1) for i in range(N)
        ]

        ports2 = [
            Port("bottom_{}".format(i), (xs2[i], dy), 0.5, a2)
            for i in range(N)
        ]

    top_cell = Component("connect_bundle_u_indirect")
    elements = connect_bundle(ports1, ports2)
    for e in elements:
        top_cell.add(e)

    return top_cell
def add_electrical_pads_top(
    component: Component,
    component_top_to_pad_bottom_distance: float = 100.0,
    route_filter=connect_elec_waypoints,
    **kwargs,
) -> Component:
    """connects component electrical ports with pad array at the top

    Args:
        component:
        pad: pad element
        spacing: pad array (x, y) spacing
        width: pad width
        height: pad height
        layer: pad layer
    """
    c = Component(f"{component.name}_e")
    ports = component.get_ports_list(port_type="dc")
    # for port in ports:
    #     print(port.name)
    # print(len(ports))
    c << component
    pads = c << pad_array(n=len(ports), port_list=["S"], **kwargs)
    pads.x = component.x
    pads.ymin = component.ymax + component_top_to_pad_bottom_distance

    ports_pads = list(pads.ports.values())

    ports_pads.sort(key=lambda p: p.x)
    ports.sort(key=lambda p: p.x)

    for p1, p2 in zip(ports_pads, ports):
        c.add(connect_electrical_shortest_path(p1, p2))

    c.ports = component.ports.copy()
    for port in ports:
        c.ports.pop(port.name)
    return c
Ejemplo n.º 17
0
def test_facing_ports():
    dy = 200.0
    xs1 = [-500, -300, -100, -90, -80, -55, -35, 200, 210, 240, 500, 650]

    pitch = 10.0
    N = len(xs1)
    xs2 = [-20 + i * pitch for i in range(N // 2)]
    xs2 += [400 + i * pitch for i in range(N // 2)]

    a1 = 90
    a2 = a1 + 180

    ports1 = [Port("top_{}".format(i), (xs1[i], 0), 0.5, a1) for i in range(N)]
    ports2 = [
        Port("bottom_{}".format(i), (xs2[i], dy), 0.5, a2) for i in range(N)
    ]

    top_cell = Component("test_facing_ports")
    elements = connect_bundle(ports1, ports2)
    # elements = link_ports_path_length_match(ports1, ports2)
    top_cell.add(elements)

    return top_cell
Ejemplo n.º 18
0
def test_connect_bundle():

    xs_top = [-100, -90, -80, 0, 10, 20, 40, 50, 80, 90, 100, 105, 110, 115]

    pitch = 127.0
    N = len(xs_top)
    xs_bottom = [(i - N / 2) * pitch for i in range(N)]

    top_ports = [Port(f"top_{i}", (xs_top[i], 0), 0.5, 270) for i in range(N)]

    bottom_ports = [
        Port(f"bottom_{i}", (xs_bottom[i], -400), 0.5, 90) for i in range(N)
    ]

    top_cell = Component(name="connect_bundle")
    routes = connect_bundle(top_ports, bottom_ports)
    lengths = [
        1180.4159265358978,
        1063.4159265358978,
        946.4159265358978,
        899.4159265358979,
        782.4159265358979,
        665.4159265358979,
        558.4159265358979,
        441.41592653589794,
        438.41592653589794,
        555.4159265358979,
        672.4159265358979,
        794.4159265358979,
        916.415926535898,
        1038.415926535898,
    ]
    for route, length in zip(routes, lengths):
        # print(route.parent.length)
        top_cell.add(route["references"])
        assert np.isclose(route["settings"]["length"], length)
    return top_cell
Ejemplo n.º 19
0
def test_connect_bundle():

    xs_top = [-100, -90, -80, 0, 10, 20, 40, 50, 80, 90, 100, 105, 110, 115]

    pitch = 127.0
    N = len(xs_top)
    xs_bottom = [(i - N / 2) * pitch for i in range(N)]

    top_ports = [
        Port("top_{}".format(i), (xs_top[i], 0), 0.5, 270) for i in range(N)
    ]

    bottom_ports = [
        Port("bottom_{}".format(i), (xs_bottom[i], -400), 0.5, 90)
        for i in range(N)
    ]

    top_cell = Component(name="connect_bundle")
    elements = connect_bundle(top_ports, bottom_ports)
    for e in elements:
        top_cell.add(e)
    top_cell.name = "connect_bundle"

    return top_cell
Ejemplo n.º 20
0
def add_electrical_pads_shortest(component,
                                 pad=pad,
                                 pad_port_spacing=50,
                                 **kwargs):
    """add a pad to each closest electrical port
    Args:
        component:
        pad: pad element or function
        pad_port_spacing: between pad and port
        width: pad width
        height: pad height
        layer: pad layer

    """
    c = Component(f"{component.name}_e")
    ports = component.get_ports_list(port_type="dc")
    c << component

    pad = pad(**kwargs) if callable(pad) else pad
    pad_port_spacing += pad.settings["width"] / 2

    for port in ports:
        p = c << pad
        if port.orientation == 0:
            p.x = port.x + pad_port_spacing
            p.y = port.y
            c.add(connect_electrical_shortest_path(port, p.ports["W"]))
        elif port.orientation == 180:
            p.x = port.x - pad_port_spacing
            p.y = port.y
            c.add(connect_electrical_shortest_path(port, p.ports["E"]))
        elif port.orientation == 90:
            p.y = port.y + pad_port_spacing
            p.x = port.x
            c.add(connect_electrical_shortest_path(port, p.ports["S"]))
        elif port.orientation == 270:
            p.y = port.y - pad_port_spacing
            p.x = port.x
            c.add(connect_electrical_shortest_path(port, p.ports["N"]))

    c.ports = component.ports
    for port in ports:
        c.ports.pop(port.name)
    return c
Ejemplo n.º 21
0
def component_from_yaml(
    yaml_str: Union[str, pathlib.Path, IO[Any]],
    component_factory=None,
    route_factory=route_factory,
    link_factory=link_factory,
    label_instance_function=_add_instance_label,
    **kwargs,
) -> Component:
    """Returns a Component defined in YAML file or string.

    Args:
        yaml: YAML IO describing Component file or string (with newlines)
            (instances, placements, routes, ports, connections, names)
        component_factory: dict of {factory_name: factory_function}
        route_factory: for routes
        link_factory: for links
        label_instance_function: to label each instance
        kwargs: cache, pins ... to pass to all factories

    Returns:
        Component

    .. code::

        valid properties:
        name: name of Component
        instances:
            name:
                component:
                settings (Optional)
        placements:
            x: Optional[float, str]  str can be instanceName,portName
            y: Optional[float, str]
            rotation: Optional[float]
            mirror: Optional[bool, float] float is x mirror axis
            port: Optional[str] port anchor
        connections (Optional): between instances
        ports (Optional): defines ports to expose
        routes (Optional): defines bundles of routes
            routeName:
            factory: optical
            links:
                instance1,port1: instance2,port2


    .. code::

        instances:
            mmi_bot:
              component: mmi1x2
              settings:
                width_mmi: 4.5
                length_mmi: 10
            mmi_top:
              component: mmi1x2
              settings:
                width_mmi: 4.5
                length_mmi: 5

        placements:
            mmi_top:
                port: W0
                x: 0
                y: 0
            mmi_bot:
                port: W0
                x: mmi_top,E1
                y: mmi_top,E1
                dx: 30
                dy: -30
        routes:
            optical:
                factory: optical
                links:
                    mmi_top,E0: mmi_bot,W0

    """
    yaml_str = (io.StringIO(yaml_str) if isinstance(yaml_str, str)
                and "\n" in yaml_str else yaml_str)
    component_factory = component_factory or component_factory_default

    conf = OmegaConf.load(
        yaml_str)  # nicer loader than conf = yaml.safe_load(yaml_str)
    for key in conf.keys():
        assert key in valid_keys, f"{key} not in {list(valid_keys)}"

    instances = {}
    routes = {}
    name = conf.get("name", "Unnamed")
    c = Component(name)
    placements_conf = conf.get("placements")
    routes_conf = conf.get("routes")
    ports_conf = conf.get("ports")
    connections_conf = conf.get("connections")
    instances_dict = conf["instances"]

    for instance_name in instances_dict:
        instance_conf = instances_dict[instance_name]
        component_type = instance_conf["component"]
        assert (component_type in component_factory
                ), f"{component_type} not in {list(component_factory.keys())}"
        component_settings = instance_conf["settings"] or {}
        component_settings.update(**kwargs)
        ci = component_factory[component_type](**component_settings)
        ref = c << ci
        instances[instance_name] = ref

    while placements_conf:
        place(
            placements_conf=placements_conf,
            instances=instances,
            encountered_insts=list(),
        )

    if connections_conf:
        for port_src_string, port_dst_string in connections_conf.items():
            instance_src_name, port_src_name = port_src_string.split(",")
            instance_dst_name, port_dst_name = port_dst_string.split(",")

            instance_src_name = instance_src_name.strip()
            instance_dst_name = instance_dst_name.strip()
            port_src_name = port_src_name.strip()
            port_dst_name = port_dst_name.strip()

            assert (instance_src_name in instances
                    ), f"{instance_src_name} not in {list(instances.keys())}"
            assert (instance_dst_name in instances
                    ), f"{instance_dst_name} not in {list(instances.keys())}"
            instance_src = instances[instance_src_name]
            instance_dst = instances[instance_dst_name]

            assert port_src_name in instance_src.ports, (
                f"{port_src_name} not in {list(instance_src.ports.keys())} for"
                f" {instance_src_name} ")
            assert port_dst_name in instance_dst.ports, (
                f"{port_dst_name} not in {list(instance_dst.ports.keys())} for"
                f" {instance_dst_name}")
            port_dst = instance_dst.ports[port_dst_name]
            instance_src.connect(port=port_src_name, destination=port_dst)

    for instance_name in instances_dict:
        label_instance_function(component=c,
                                instance_name=instance_name,
                                reference=instances[instance_name])

    if routes_conf:
        for route_alias in routes_conf:
            route_names = []
            ports1 = []
            ports2 = []
            routes_dict = routes_conf[route_alias]
            if not hasattr(routes_dict, "__items__"):
                print(f"Unvalid syntax for {routes_dict}\n", sample_mmis)
                raise ValueError(f"Unvalid syntax for {routes_dict}")
            for key in routes_dict.keys():
                if key not in valid_route_keys:
                    raise ValueError(
                        f"`{route_alias}` has a key=`{key}` not in valid {valid_route_keys}"
                    )

            if "factory" not in routes_dict:
                raise ValueError(
                    f"`{route_alias}` route needs `factory` : {list(route_factory.keys())}"
                )
            route_type = routes_dict.pop("factory")
            assert isinstance(route_factory,
                              dict), "route_factory needs to be a dict"
            assert (
                route_type in route_factory
            ), f"factory `{route_type}` not in route_factory {list(route_factory.keys())}"
            route_filter = route_factory[route_type]
            route_settings = routes_dict.pop("settings", {})

            link_function_name = routes_dict.pop("link_factory", "link_ports")
            assert (
                link_function_name in link_factory
            ), f"function `{link_function_name}` not in link_factory {list(link_factory.keys())}"
            link_function = link_factory[link_function_name]
            link_settings = routes_dict.pop("link_settings", {})

            if "links" not in routes_dict:
                raise ValueError(
                    f"You need to define links for the `{route_alias}` route")
            links_dict = routes_dict["links"]

            for port_src_string, port_dst_string in links_dict.items():
                # print(port_src_string)

                if ":" in port_src_string:
                    src, src0, src1 = [
                        s.strip() for s in port_src_string.split(":")
                    ]
                    dst, dst0, dst1 = [
                        s.strip() for s in port_dst_string.split(":")
                    ]
                    instance_src_name, port_src_name = [
                        s.strip() for s in src.split(",")
                    ]
                    instance_dst_name, port_dst_name = [
                        s.strip() for s in dst.split(",")
                    ]

                    src0 = int(src0)
                    src1 = int(src1)
                    dst0 = int(dst0)
                    dst1 = int(dst1)

                    if src1 > src0:
                        ports1names = [
                            f"{port_src_name}{i}"
                            for i in range(src0, src1 + 1, 1)
                        ]
                    else:
                        ports1names = [
                            f"{port_src_name}{i}"
                            for i in range(src0, src1 - 1, -1)
                        ]

                    if dst1 > dst0:
                        ports2names = [
                            f"{port_dst_name}{i}"
                            for i in range(dst0, dst1 + 1, 1)
                        ]
                    else:
                        ports2names = [
                            f"{port_dst_name}{i}"
                            for i in range(dst0, dst1 - 1, -1)
                        ]

                    # print(ports1names)
                    # print(ports2names)

                    assert len(ports1names) == len(ports2names)
                    route_names += [
                        f"{instance_src_name},{i}:{instance_dst_name},{j}"
                        for i, j in zip(ports1names, ports2names)
                    ]

                    instance_src = instances[instance_src_name]
                    instance_dst = instances[instance_dst_name]

                    for port_src_name in ports1names:
                        assert port_src_name in instance_src.ports, (
                            f"{port_src_name} not in {list(instance_src.ports.keys())}"
                            f"for {instance_src_name} ")
                        ports1.append(instance_src.ports[port_src_name])

                    for port_dst_name in ports2names:
                        assert port_dst_name in instance_dst.ports, (
                            f"{port_dst_name} not in {list(instance_dst.ports.keys())}"
                            f"for {instance_dst_name}")
                        ports2.append(instance_dst.ports[port_dst_name])

                    # print(ports1)
                    # print(ports2)
                    print(route_names)

                else:
                    instance_src_name, port_src_name = port_src_string.split(
                        ",")
                    instance_dst_name, port_dst_name = port_dst_string.split(
                        ",")

                    instance_src_name = instance_src_name.strip()
                    instance_dst_name = instance_dst_name.strip()
                    port_src_name = port_src_name.strip()
                    port_dst_name = port_dst_name.strip()
                    assert (
                        instance_src_name in instances
                    ), f"{instance_src_name} not in {list(instances.keys())}"
                    assert (
                        instance_dst_name in instances
                    ), f"{instance_dst_name} not in {list(instances.keys())}"

                    instance_src = instances[instance_src_name]
                    instance_dst = instances[instance_dst_name]

                    assert port_src_name in instance_src.ports, (
                        f"{port_src_name} not in {list(instance_src.ports.keys())} for"
                        f" {instance_src_name} ")
                    assert port_dst_name in instance_dst.ports, (
                        f"{port_dst_name} not in {list(instance_dst.ports.keys())} for"
                        f" {instance_dst_name}")

                    ports1.append(instance_src.ports[port_src_name])
                    ports2.append(instance_dst.ports[port_dst_name])
                    route_name = f"{port_src_string}:{port_dst_string}"
                    route_names.append(route_name)

            if link_function_name in [
                    "link_electrical_waypoints",
                    "link_optical_waypoints",
            ]:
                route = link_function(
                    route_filter=route_filter,
                    **route_settings,
                    **link_settings,
                )
                routes[route_name] = route

            else:
                route = link_function(
                    ports1,
                    ports2,
                    route_filter=route_filter,
                    **route_settings,
                    **link_settings,
                )
                for i, r in enumerate(route):
                    routes[route_names[i]] = r

            c.add(route)

    if ports_conf:
        assert hasattr(ports_conf, "items"), f"{ports_conf} needs to be a dict"
        for port_name, instance_comma_port in ports_conf.items():
            instance_name, instance_port_name = instance_comma_port.split(",")
            instance_name = instance_name.strip()
            instance_port_name = instance_port_name.strip()
            assert (instance_name in instances
                    ), f"{instance_name} not in {list(instances.keys())}"
            instance = instances[instance_name]
            assert instance_port_name in instance.ports, (
                f"{instance_port_name} not in {list(instance.ports.keys())} for"
                f" {instance_name} ")
            c.add_port(port_name, port=instance.ports[instance_port_name])
    c.instances = instances
    c.routes = routes
    return c
Ejemplo n.º 22
0
def wg_heater_connector(
    heater_ports: List[Port],
    metal_width: float = 10.0,
    tlm_layers: List[Tuple[int, int]] = [
        LAYER.VIA1,
        LAYER.M1,
        LAYER.VIA2,
        LAYER.M2,
        LAYER.VIA3,
        LAYER.M3,
    ],
) -> Component:
    """
    Connects together a pair of wg heaters and connect to a M3 port
    """

    cmp = Component()
    assert len(heater_ports) == 2
    assert (heater_ports[0].orientation == heater_ports[1].orientation
            ), "both ports should be facing in the same direction"
    angle = heater_ports[0].orientation
    angle = angle % 360
    assert angle in [0, 180], "angle should be 0 or 180, got {}".format(angle)

    dx = 0.0
    dy = 0.0

    angle_to_dps = {0: [(-dx, -dy), (-dx, dy)], 180: [(dx, -dy), (dx, dy)]}
    ports = heater_ports
    hw = heater_ports[0].width

    if angle in [0, 180]:
        ports.sort(key=lambda p: p.y)
    else:
        ports.sort(key=lambda p: p.x)

    _heater_to_metal = tlm(width=0.5, height=0.5, layers=tlm_layers, vias=[])

    tlm_positions = []
    for port, dp in zip(ports, angle_to_dps[angle]):
        # Extend heater
        p = port.midpoint

        # Add via/metal transitions
        tlm_pos = p + dp
        hm = _heater_to_metal.ref(position=tlm_pos)
        tlm_positions += [tlm_pos]
        cmp.add(hm)

    ss = 1 if angle == 0 else -1

    # Connect both sides with top metal
    edge_metal_piece_width = 7.0
    x = ss * edge_metal_piece_width / 2
    top_metal_layer = tlm_layers[-1]
    cmp.add_polygon(
        line(
            tlm_positions[0] + (x, -hw / 2),
            tlm_positions[1] + (x, hw / 2),
            edge_metal_piece_width,
        ),
        layer=top_metal_layer,
    )

    # Add metal port
    cmp.add_port(
        name="0",
        midpoint=0.5 * sum(tlm_positions) +
        (ss * edge_metal_piece_width / 2, 0),
        orientation=angle,
        width=metal_width,
        layer=top_metal_layer,
        port_type="dc",
    )

    return cmp
Ejemplo n.º 23
0
    p2x1 = port2.endpoints[1][0]
    p2y1 = port2.endpoints[1][1]

    if port1.orientation in [90, 270]:
        c.add_polygon(([(p1x1, p1y0), (p1x0, p1y1), (p2x1, p2y1),
                        (p2x0, p2y0)]),
                      layer=layer)
    else:
        c.add_polygon(([(p1x0, p1y1), (p1x1, p1y0), (p2x1, p2y1),
                        (p2x0, p2y0)]),
                      layer=layer)
    return c.ref()


if __name__ == "__main__":
    import pp
    from pp.components.electrical.pad import pad_array

    c = Component("mzi_with_pads")
    mzi = pp.c.mzi2x2(with_elec_connections=True)
    pads = pad_array(n=3, port_list=["S"])
    p = c << pads
    c << mzi
    p.move((-150, 200))
    ports_pads = list(p.ports.values())
    ports_mzi = mzi.get_ports_list(port_type="dc")

    for p1, p2 in zip(ports_pads, ports_mzi):
        c.add(connect_electrical_shortest_path(p1, p2))
    pp.show(c)
Ejemplo n.º 24
0
def netlist_to_component(
        instances: Dict[str, Tuple[Component, str]],
        connections: List[Tuple[str, str, str, str]],
        ports_map: Dict[str, Tuple[str, str]] = None,
        position: Tuple[float, float] = (0.0, 0.0),
) -> Component:
    """ Netlist_to_component is deprecated! use pp.componet_from_yaml instead
    Returns a component from a netlist (instances, connections and ports map)

    Args:
        instances:
            list of (instance_id <str>, component <Component>, transform <tuple>)

        connections:
            list of (component_id1, port_name1, component_id2, port_name2)
            Has to be ordered such that any component refered to in the connections
            has already been placed (except for the first component)

        ports_map:
            {port_name: (instance_id, port_name)}

    Returns: component with netlist stored in component.netlist

    ```

    [
        {
            "name": "CP2x2",
            "rank": 0,
            "ports": ["in1", "in2", "out1", "out2"],
            "type": "CPBIDIR",
            "settings": {"R": 0.5},
        },
        {
            "name": "WG_CAVITY",
            "rank": 0,
            "ports": ["in", "out"],
            "type": "WG",
            "settings": {"length": 50, "loss_dB_m": 60000, "width": 0.5},
        },
        {
            "name": "ring_resonator",
            "rank": 1,
            "type": "COMPOUND",
            "settings": {},
            "instances": [
                "CP1, CP2x2, None, None, 0.0, 0.0",
                "WG1, WG_CAVITY, None, None, 0.0, 0.0",
            ],
            "connections": ["CP1, out1, WG1, in", "WG1, out, CP1, in1"],
            "ports": {"in1": "CP1, in2", "out1": "CP1, out2"},
        },
    ]
    ```

    mirror, rotation, x, y
    """

    if len(connections) == 0:
        raise ValueError("no connections defined")

    instance_id, port, _, _ = connections[0]
    assert instance_id in instances, f"{instance_id} not in {list(instances.keys())}"
    component, transform_name = instances[instance_id]

    # First component reference
    sref_start = gen_sref(component, transform_name, port, position)
    cmp_name_to_sref = {instance_id: sref_start}

    # Iterate over all connections: create and place instances
    for cmp1_name, port1, cmp2_name, port2 in connections:
        if cmp1_name not in cmp_name_to_sref:
            cmp1_name, port1, cmp2_name, port2 = cmp2_name, port2, cmp1_name, port1

        if cmp2_name not in cmp_name_to_sref:
            component, transform_name = instances[cmp2_name]

            _ref = cmp_name_to_sref[cmp1_name]
            try:
                position = _ref.ports[port1].midpoint
            except Exception:
                print("{} has not port {}".format(cmp1_name, port1))

            sref = gen_sref(component, transform_name, port2, position)

            cmp_name_to_sref[cmp2_name] = sref

    c = Component()
    c.add(list(cmp_name_to_sref.values()))

    if ports_map:
        for port_name, (cmp_id, internal_port_name) in ports_map.items():
            component_ref = cmp_name_to_sref[cmp_id]
            component = component_ref.parent
            assert internal_port_name in component.ports, (
                f"{internal_port_name} not in {component_ref.ports.keys()} for"
                f" {component}")
            port = component_ref.ports[internal_port_name]
            c.add_port(port_name, port=port)
            ports_map = {k: ", ".join(v) for k, v in ports_map.items()}

    # Set aliases
    for cmp_id, ref in cmp_name_to_sref.items():
        c[cmp_id] = ref

    c.netlist = cmp_name_to_sref

    # add leaf cells to netlist
    netlist = []
    for name, (component, _) in instances.items():
        netlist.append(
            dict(
                name=name,
                rank=0,
                ports=list(component.ports.keys()),
                settings=component.settings,
            ))
    # add the compound cell to the netlist
    netlist.append(
        dict(
            name="component_name",
            rank=1,
            type="COMPOUND",
            settings={},
            connections=[", ".join(i) for i in connections],
            ports=ports_map,
        ))
    c.netlist = netlist
    return c
Ejemplo n.º 25
0
def add_io_optical(c,
                   grating_coupler=grating_coupler_te,
                   gc_port_name="W0",
                   component_name=None,
                   **kwargs):
    """ returns component with optical IO (tapers, south routes and grating_couplers)

    Args:
        component: to connect
        optical_io_spacing: SPACING_GC
        grating_coupler: grating coupler instance, function or list of functions
        bend_factory: bend_circular
        straight_factory: waveguide
        fanout_length: None,  # if None, automatic calculation of fanout length
        max_y0_optical: None
        with_align_ports: True, adds loopback structures
        waveguide_separation=4.0
        bend_radius: BEND_RADIUS
        list_port_labels: None, adds TM labels to port indices in this list
        connected_port_list_ids: None # only for type 0 optical routing
        nb_optical_ports_lines: 1
        force_manhattan: False
        excluded_ports:
        grating_indices: None
        routing_waveguide: None
        routing_method: connect_strip
        gc_port_name: W0
        optical_routing_type: None: autoselection, 0: no extension
        gc_rotation=-90
        layer_label=LAYER.LABEL
        input_port_indexes=[0]
        component_name: for the label

    """
    if not c.ports:
        return c
    cc = Component(
        settings=c.get_settings(),
        test_protocol=c.test_protocol,
        data_analysis_protocol=c.data_analysis_protocol,
    )
    cc.function_name = "add_io_optical"

    if isinstance(grating_coupler, list):
        gc = grating_coupler[0]
    else:
        gc = grating_coupler
    gc = pp.call_if_func(gc)

    if "polarization" in gc.settings:
        gc.polarization = gc.settings["polarization"]

    cc.name = "{}_{}".format(c.name, gc.polarization)

    port_width_gc = list(gc.ports.values())[0].width
    port_width_component = list(c.ports.values())[0].width

    if port_width_component != port_width_gc:
        c = add_tapers(
            c,
            taper(length=10, width1=port_width_gc,
                  width2=port_width_component))

    elements, io_gratings_lines, _ = _get_optical_io_elements(
        component=c,
        grating_coupler=grating_coupler,
        gc_port_name=gc_port_name,
        component_name=component_name,
        **kwargs)
    if len(elements) == 0:
        return c

    cc.add(elements)
    for io_gratings in io_gratings_lines:
        cc.add(io_gratings)
    cc.add(c.ref())
    cc.move(origin=io_gratings_lines[0][0].ports[gc_port_name],
            destination=(0, 0))

    return cc
Ejemplo n.º 26
0
def test_connect_corner(N=6, config="A"):
    d = 10.0
    sep = 5.0
    top_cell = Component(name="connect_corner")

    if config in ["A", "B"]:
        a = 100.0
        ports_A_TR = [
            Port("A_TR_{}".format(i), (d, a / 2 + i * sep), 0.5, 0)
            for i in range(N)
        ]
        ports_A_TL = [
            Port("A_TL_{}".format(i), (-d, a / 2 + i * sep), 0.5, 180)
            for i in range(N)
        ]
        ports_A_BR = [
            Port("A_BR_{}".format(i), (d, -a / 2 - i * sep), 0.5, 0)
            for i in range(N)
        ]
        ports_A_BL = [
            Port("A_BL_{}".format(i), (-d, -a / 2 - i * sep), 0.5, 180)
            for i in range(N)
        ]

        ports_A = [ports_A_TR, ports_A_TL, ports_A_BR, ports_A_BL]

        ports_B_TR = [
            Port("B_TR_{}".format(i), (a / 2 + i * sep, d), 0.5, 90)
            for i in range(N)
        ]
        ports_B_TL = [
            Port("B_TL_{}".format(i), (-a / 2 - i * sep, d), 0.5, 90)
            for i in range(N)
        ]
        ports_B_BR = [
            Port("B_BR_{}".format(i), (a / 2 + i * sep, -d), 0.5, 270)
            for i in range(N)
        ]
        ports_B_BL = [
            Port("B_BL_{}".format(i), (-a / 2 - i * sep, -d), 0.5, 270)
            for i in range(N)
        ]

        ports_B = [ports_B_TR, ports_B_TL, ports_B_BR, ports_B_BL]

    elif config in ["C", "D"]:
        a = N * sep + 2 * d
        ports_A_TR = [
            Port("A_TR_{}".format(i), (a, d + i * sep), 0.5, 0)
            for i in range(N)
        ]
        ports_A_TL = [
            Port("A_TL_{}".format(i), (-a, d + i * sep), 0.5, 180)
            for i in range(N)
        ]
        ports_A_BR = [
            Port("A_BR_{}".format(i), (a, -d - i * sep), 0.5, 0)
            for i in range(N)
        ]
        ports_A_BL = [
            Port("A_BL_{}".format(i), (-a, -d - i * sep), 0.5, 180)
            for i in range(N)
        ]

        ports_A = [ports_A_TR, ports_A_TL, ports_A_BR, ports_A_BL]

        ports_B_TR = [
            Port("B_TR_{}".format(i), (d + i * sep, a), 0.5, 90)
            for i in range(N)
        ]
        ports_B_TL = [
            Port("B_TL_{}".format(i), (-d - i * sep, a), 0.5, 90)
            for i in range(N)
        ]
        ports_B_BR = [
            Port("B_BR_{}".format(i), (d + i * sep, -a), 0.5, 270)
            for i in range(N)
        ]
        ports_B_BL = [
            Port("B_BL_{}".format(i), (-d - i * sep, -a), 0.5, 270)
            for i in range(N)
        ]

        ports_B = [ports_B_TR, ports_B_TL, ports_B_BR, ports_B_BL]

    if config in ["A", "C"]:
        for ports1, ports2 in zip(ports_A, ports_B):
            routes = connect_bundle(ports1, ports2)
            for route in routes:
                top_cell.add(route["references"])

    elif config in ["B", "D"]:
        for ports1, ports2 in zip(ports_A, ports_B):
            routes = connect_bundle(ports2, ports1)
            for route in routes:
                top_cell.add(route["references"])

    return top_cell
Ejemplo n.º 27
0
def netlist_to_component(components, connections, ports_map, position=(0, 0)):
    """
    Args:
        components:
            list of (component_id <str>, component <Component>, transform <tuple>)

        connections:
            list of (component_id1, port_name1, component_id2, port_name2)
            Has to be ordered such that any component refered to in the connections
            has already been placed (except for the first component)

        ports_map:
            {port_name: (component_id, port_name)}

    Returns: component
    the component has component.netlist

    [
        {
            "name": "CP2x2",
            "rank": 0,
            "ports": ["in1", "in2", "out1", "out2"],
            "type": "CPBIDIR",
            "settings": {"R": 0.5},
        },
        {
            "name": "WG_CAVITY",
            "rank": 0,
            "ports": ["in", "out"],
            "type": "WG",
            "settings": {"length": 50, "loss_dB_m": 60000, "width": 0.5},
        },
        {
            "name": "ring_resonator",
            "rank": 1,
            "type": "COMPOUND",
            "settings": {},
            "components": [
                "CP1, CP2x2, None, None, 0.0, 0.0",
                "WG1, WG_CAVITY, None, None, 0.0, 0.0",
            ],
            "connections": ["CP1, out1, WG1, in", "WG1, out, CP1, in1"],
            "ports": {"in1": "CP1, in2", "out1": "CP1, out2"},
        },
    ]

    mirror, rotation, x, y
    """
    if len(connections) == 0:
        raise ValueError("Error number of connections", len(connections),
                         len(components))

    component_id, cmp_port, _, _ = connections[0]

    component, transform_name = components[component_id]

    # First component reference
    sref_start = gen_sref(component, transform_name, cmp_port, position)
    cmp_name_to_sref = {component_id: sref_start}

    # Iterate over all connections: create and place components
    for cmp1_name, port1, cmp2_name, port2 in connections:
        if cmp1_name not in cmp_name_to_sref:
            cmp1_name, port1, cmp2_name, port2 = cmp2_name, port2, cmp1_name, port1

        if cmp2_name not in cmp_name_to_sref:
            component, transform_name = components[cmp2_name]

            _ref = cmp_name_to_sref[cmp1_name]
            try:
                position = _ref.ports[port1].midpoint
            except:
                print("{} has not port {}".format(cmp1_name, port1))

            sref = gen_sref(component, transform_name, port2, position)

            cmp_name_to_sref[cmp2_name] = sref

    c = Component()
    c.add(list(cmp_name_to_sref.values()))
    for port_name, (cmp_id, internal_port_name) in ports_map.items():
        c.add_port(port_name,
                   port=cmp_name_to_sref[cmp_id].ports[internal_port_name])

    # Set aliases
    for cmp_id, ref in cmp_name_to_sref.items():
        c[cmp_id] = ref

    c.info["components"] = cmp_name_to_sref
    # c.components = components
    # c.connections = connections
    # c.ports_map = ports_map
    # c.cells = {
    #     cname: c for cname, (c, transf) in components.items()
    # }  # "CP1": (cpl, "None"),

    # add leaf cells to netlist
    netlist = []
    for name, (component, _) in components.items():
        netlist.append(
            dict(
                name=name,
                rank=0,
                ports=list(component.ports.keys()),
                settings=component.settings,
            ))
    # add the compound cell to the netlist
    netlist.append(
        dict(
            name="component_name",
            rank=1,
            type="COMPOUND",
            settings={},
            connections=[", ".join(i) for i in connections],
            ports={k: ", ".join(v)
                   for k, v in ports_map.items()},
        ))
    c.netlist = netlist
    return c
Ejemplo n.º 28
0
def component_from_yaml(
    yaml: Union[str, pathlib.Path, IO[Any]],
    component_factory=None,
    route_factory=route_factory,
    **kwargs,
) -> Component:
    """Returns a Component defined from YAML


    Args:
        yaml: YAML IO describing Component (instances, placements, routing, ports, connections)
        component_factory: dict of {factory_name: factory_function}
        route_factory: for routes
        kwargs: cache, pins ... to pass to all factories

    Returns:
        Component

    valid properties:
    name: name of Component
    instances:
        name
        component
        settings
    placements: x, y and rotations
    connections: between instances
    ports (Optional): defines ports to expose
    routes (Optional): defines bundles of routes
    ports (Optional): defines ports to expose

    """
    yaml = io.StringIO(yaml) if isinstance(yaml, str) and "\n" in yaml else yaml
    component_factory = component_factory or component_factory_default

    conf = OmegaConf.load(yaml)
    for key in conf.keys():
        assert key in valid_keys, f"{key} not in {list(valid_keys)}"

    instances = {}
    routes = {}
    name = conf.get("name") or "Unnamed"
    c = Component(name)
    placements_conf = conf.get("placements")
    routes_conf = conf.get("routes")
    ports_conf = conf.get("ports")
    connections_conf = conf.get("connections")

    for instance_name in conf.instances:
        instance_conf = conf.instances[instance_name]
        component_type = instance_conf["component"]
        assert (
            component_type in component_factory
        ), f"{component_type} not in {list(component_factory.keys())}"
        component_settings = instance_conf["settings"] or {}
        component_settings.update(**kwargs)
        ci = component_factory[component_type](**component_settings)
        ref = c << ci
        instances[instance_name] = ref

        if placements_conf:
            placement_settings = placements_conf[instance_name] or {}
            for k, v in placement_settings.items():
                if k not in valid_placements:
                    raise ValueError(
                        f"`{k}` not valid placement {valid_placements} for"
                        f" {instance_name}"
                    )
                elif k == "rotation":
                    ref.rotate(v, (ci.x, ci.y))
                elif k == "mirror":
                    ref.mirror((v[0], v[1]), (v[2], v[3]))
                else:
                    setattr(ref, k, v)

    if connections_conf:
        for port_src_string, port_dst_string in connections_conf.items():
            instance_src_name, port_src_name = port_src_string.split(",")
            instance_dst_name, port_dst_name = port_dst_string.split(",")

            instance_src_name = instance_src_name.strip()
            instance_dst_name = instance_dst_name.strip()
            port_src_name = port_src_name.strip()
            port_dst_name = port_dst_name.strip()

            assert (
                instance_src_name in instances
            ), f"{instance_src_name} not in {list(instances.keys())}"
            assert (
                instance_dst_name in instances
            ), f"{instance_dst_name} not in {list(instances.keys())}"
            instance_src = instances[instance_src_name]
            instance_dst = instances[instance_dst_name]

            assert port_src_name in instance_src.ports, (
                f"{port_src_name} not in {list(instance_src.ports.keys())} for"
                f" {instance_src_name} "
            )
            assert port_dst_name in instance_dst.ports, (
                f"{port_dst_name} not in {list(instance_dst.ports.keys())} for"
                f" {instance_dst_name}"
            )
            port_dst = instance_dst.ports[port_dst_name]
            instance_src.connect(port=port_src_name, destination=port_dst)

    if routes_conf:
        for route_type in routes_conf:
            route_names = []
            ports1 = []
            ports2 = []
            routes_dict = routes_conf[route_type]
            assert (
                route_type in route_factory
            ), f"route_type `{route_type}` not in route_factory {list(route_factory.keys())}"
            route_filter = route_factory[route_type]
            for port_src_string, port_dst_string in routes_dict.items():
                instance_src_name, port_src_name = port_src_string.split(",")
                instance_dst_name, port_dst_name = port_dst_string.split(",")

                instance_src_name = instance_src_name.strip()
                instance_dst_name = instance_dst_name.strip()
                port_src_name = port_src_name.strip()
                port_dst_name = port_dst_name.strip()

                assert (
                    instance_src_name in instances
                ), f"{instance_src_name} not in {list(instances.keys())}"
                assert (
                    instance_dst_name in instances
                ), f"{instance_dst_name} not in {list(instances.keys())}"

                instance_in = instances[instance_src_name]
                instance_out = instances[instance_dst_name]

                assert port_src_name in instance_in.ports, (
                    f"{port_src_name} not in {list(instance_in.ports.keys())} for"
                    f" {instance_src_name} "
                )
                assert port_dst_name in instance_out.ports, (
                    f"{port_dst_name} not in {list(instance_out.ports.keys())} for"
                    f" {instance_dst_name}"
                )

                ports1.append(instance_in.ports[port_src_name])
                ports2.append(instance_out.ports[port_dst_name])
                route_names.append(f"{port_src_string}:{port_dst_string}")
            route = link_ports(ports1, ports2, route_filter=route_filter)
            for i, r in enumerate(route):
                routes[route_names[i]] = r

            c.add(route)

    if ports_conf:
        assert hasattr(ports_conf, "items"), f"{ports_conf} needs to be a dict"
        for port_name, instance_comma_port in ports_conf.items():
            instance_name, instance_port_name = instance_comma_port.split(",")
            instance_name = instance_name.strip()
            instance_port_name = instance_port_name.strip()
            assert (
                instance_name in instances
            ), f"{instance_name} not in {list(instances.keys())}"
            instance = instances[instance_name]
            assert instance_port_name in instance.ports, (
                f"{instance_port_name} not in {list(instance.ports.keys())} for"
                f" {instance_name} "
            )
            c.add_port(port_name, port=instance.ports[instance_port_name])
    c.instances = instances
    c.routes = routes
    return c
Ejemplo n.º 29
0
def _bend_circular_heater(
    radius: float = 10,
    wg_width: float = 0.5,
    theta: int = -90,
    start_angle: int = 0,
    angle_resolution: float = 2.5,
    heater_to_wg_distance: float = 1.2,
    heater_width: float = 0.5,
) -> Component:
    """ Creates an arc of arclength ``theta`` starting at angle ``start_angle``

    Args:
        radius
        width: of the waveguide
        theta: arc length
        start_angle:
        angle_resolution
    """
    component = Component()

    wg_bend = bend_circular(
        radius=radius,
        width=wg_width,
        theta=theta,
        start_angle=start_angle,
        angle_resolution=angle_resolution,
        layer=LAYER.WG,
    ).ref((0, 0))

    a = heater_to_wg_distance + wg_width / 2 + heater_width / 2

    heater_outer = bend_circular(
        radius=radius + a,
        width=heater_width,
        theta=theta,
        start_angle=start_angle,
        angle_resolution=angle_resolution,
        layer=LAYER.HEATER,
    ).ref((0, -a))

    heater_inner = bend_circular(
        radius=radius - a,
        width=heater_width,
        theta=theta,
        start_angle=start_angle,
        angle_resolution=angle_resolution,
        layer=LAYER.HEATER,
    ).ref((0, a))

    component.add(wg_bend)
    component.add(heater_outer)
    component.add(heater_inner)

    component.absorb(wg_bend)
    component.absorb(heater_outer)
    component.absorb(heater_inner)

    i = 0

    for device in [wg_bend, heater_outer, heater_inner]:
        for port in device.ports.values():
            component.ports["{}".format(i)] = port
            i += 1

    component.info["length"] = wg_bend.info["length"]
    component.radius = radius
    component.width = wg_width
    return component
def add_fiber_single(
    component: Component,
    grating_coupler: Callable = grating_coupler_te,
    layer_label: Tuple[int, int] = LAYER.LABEL,
    optical_io_spacing: int = 50,
    bend_factory: Callable = bend_circular,
    straight_factory: Callable = waveguide,
    taper_factory: Callable = taper,
    taper_length: float = 10.0,
    route_filter: Callable = connect_strip_way_points,
    min_input2output_spacing: int = 127,
    optical_routing_type: int = 2,
    with_align_ports: bool = True,
    component_name: Optional[str] = None,
    gc_port_name: str = "W0",
    **kwargs,
) -> Component:
    r"""returns component with grating ports and labels on each port
    can add align_ports reference structure

    Args:
        component: to connect
        grating_coupler: grating coupler instance, function or list of functions
        layer_label: LAYER.LABEL
        optical_io_spacing: SPACING_GC
        bend_factory: bend_circular
        straight_factory: waveguide
        fanout_length: None  # if None, automatic calculation of fanout length
        max_y0_optical: None
        with_align_ports: True, adds loopback structures
        waveguide_separation: 4.0
        bend_radius: BEND_RADIUS
        list_port_labels: None, adds TM labels to port indices in this list
        connected_port_list_ids: None # only for type 0 optical routing
        nb_optical_ports_lines: 1
        force_manhattan: False
        excluded_ports:
        grating_indices: None
        routing_method: connect_strip
        gc_port_name: W0
        optical_routing_type: None: autoselection, 0: no extension
        gc_rotation: -90
        component_name: name of component
        taper_factory: taper

    .. code::

              fiber
             ______
            /| | |
           / | | |
        W0|  | | |
           \ | | |
          | \|_|_|_

          |
         xmin = 0

    .. plot::
      :include-source:

       import pp
       from pp.routing import add_fiber_array

       c = pp.c.crossing()
       cc = add_fiber_array(c)
       pp.plotgds(cc)

    """
    component = component() if callable(component) else component
    gc = grating_coupler = (grating_coupler()
                            if callable(grating_coupler) else grating_coupler)
    gc_port_to_edge = abs(gc.xmax - gc.ports[gc_port_name].midpoint[0])
    port_width_gc = grating_coupler.ports[gc_port_name].width
    optical_ports = component.get_ports_list(port_type="optical")
    port_width_component = optical_ports[0].width

    if port_width_component != port_width_gc:
        component = add_tapers(
            component,
            taper_factory(length=taper_length,
                          width1=port_width_gc,
                          width2=port_width_component),
        )

    component_name = component_name or component.name
    name = f"{component_name}_{grating_coupler.name}"

    elements, grating_couplers = route_fiber_single(
        component,
        component_name=component_name,
        optical_io_spacing=optical_io_spacing,
        bend_factory=bend_factory,
        straight_factory=straight_factory,
        route_filter=route_filter,
        grating_coupler=grating_coupler,
        layer_label=layer_label,
        optical_routing_type=optical_routing_type,
        min_input2output_spacing=min_input2output_spacing,
        gc_port_name=gc_port_name,
        **kwargs,
    )

    c = Component(name=name)
    cr = c << component
    cr.rotate(90)

    for e in elements:
        c.add(e)
    for gc in grating_couplers:
        c.add(gc)

    for pname, p in component.ports.items():
        if p.port_type != "optical":
            c.add_port(pname, port=p)

    if isinstance(grating_coupler, list):
        grating_couplers = [call_if_func(g) for g in grating_coupler]
        grating_coupler = grating_couplers[0]
    else:
        grating_coupler = call_if_func(grating_coupler)
        grating_couplers = [grating_coupler]

    if with_align_ports:
        length = c.ysize - 2 * gc_port_to_edge
        wg = c << straight_factory(length=length)
        wg.rotate(90)
        wg.xmax = (c.xmin - optical_io_spacing
                   if abs(c.xmin) > abs(optical_io_spacing) else c.xmin -
                   optical_io_spacing)
        wg.ymin = c.ymin + gc_port_to_edge

        gci = c << grating_coupler
        gco = c << grating_coupler
        gci.connect(gc_port_name, wg.ports["W0"])
        gco.connect(gc_port_name, wg.ports["E0"])

        gds_layer_label, gds_datatype_label = pd._parse_layer(layer_label)

        port = wg.ports["E0"]
        text = get_optical_text(port,
                                grating_coupler,
                                0,
                                component_name=f"loopback_{component.name}")

        label = pd.Label(
            text=text,
            position=port.midpoint,
            anchor="o",
            layer=gds_layer_label,
            texttype=gds_datatype_label,
        )
        c.add(label)

        port = wg.ports["W0"]
        text = get_optical_text(port,
                                grating_coupler,
                                1,
                                component_name=f"loopback_{component.name}")
        label = pd.Label(
            text=text,
            position=port.midpoint,
            anchor="o",
            layer=gds_layer_label,
            texttype=gds_datatype_label,
        )
        c.add(label)

    return c