Exemple #1
0
def _via_iterable(via_spacing, wire_width, wiring1_layer, wiring2_layer,
                  via_layer, via_width):
    VI = pp.Component()
    wire1 = VI.add_ref(
        pc.compass(size=(via_spacing, wire_width), layer=wiring1_layer))
    wire2 = VI.add_ref(
        pc.compass(size=(via_spacing, wire_width), layer=wiring2_layer))
    via1 = VI.add_ref(pc.compass(size=(via_width, via_width), layer=via_layer))
    via2 = VI.add_ref(pc.compass(size=(via_width, via_width), layer=via_layer))
    wire1.connect(port="E", destination=wire2.ports["W"], overlap=wire_width)
    via1.connect(port="W",
                 destination=wire1.ports["E"],
                 overlap=(wire_width + via_width) / 2)
    via2.connect(port="W",
                 destination=wire2.ports["E"],
                 overlap=(wire_width + via_width) / 2)
    VI.add_port(name="W", port=wire1.ports["W"])
    VI.add_port(name="E", port=wire2.ports["E"])
    VI.add_port(
        name="S",
        midpoint=[(1 * wire_width) + wire_width / 2, -wire_width / 2],
        width=wire_width,
        orientation=-90,
    )
    VI.add_port(
        name="N",
        midpoint=[(1 * wire_width) + wire_width / 2, wire_width / 2],
        width=wire_width,
        orientation=90,
    )

    return VI
Exemple #2
0
def grating_coupler_uniform(
    num_teeth: int = 20,
    period: float = 0.75,
    fill_factor: float = 0.5,
    width_grating: float = 11.0,
    length_taper: float = 150.0,
    width: float = 0.5,
    partial_etch: bool = False,
    layer: Tuple[int, int] = pp.LAYER.WG,
    layer_partial_etch: Tuple[int, int] = pp.LAYER.SLAB150,
    polarization="te",
    wavelength=1500,
) -> Component:
    """Grating coupler uniform

    Args:
        num_teeth: 20
        period: 0.75
        fill_factor: 0.5
        width_grating: 11
        length_taper: 150
        width: 0.5
        partial_etch: False

    .. plot::
      :include-source:

      import pp

      c = pp.c.grating_coupler_uniform()
      pp.plotgds(c)

    """
    # returns a fiber grating
    G = Component()

    if partial_etch:
        partetch_overhang = 5
        _compass = compass(
            size=[period * (1 - fill_factor), width_grating + partetch_overhang * 2],
            layer=layer_partial_etch,
        )

        # make the etched areas (opposite to teeth)
        for i in range(num_teeth):
            cgrating = G.add_ref(_compass)
            cgrating.x += i * period

        # draw the deep etched square around the grating
        deepbox = G.add_ref(
            compass(size=[num_teeth * period, width_grating], layer=layer)
        )
        deepbox.movex(num_teeth * period / 2)
    else:
        for i in range(num_teeth):
            cgrating = G.add_ref(
                compass(size=[period * fill_factor, width_grating], layer=layer)
            )
            cgrating.x += i * period
    # make the taper
    tgrating = G.add_ref(
        taper(
            length=length_taper,
            width1=width_grating,
            width2=width,
            port=None,
            layer=layer,
        )
    )
    tgrating.xmin = cgrating.xmax
    G.add_port(port=tgrating.ports["2"], name="W0")
    G.polarization = polarization
    G.wavelength = wavelength
    G.rotate(180)
    return G
Exemple #3
0
def test_comb(
    pad_size=(200, 200),
    wire_width=1,
    wire_gap=3,
    comb_layer=0,
    overlap_zigzag_layer=1,
    comb_pad_layer=None,
    comb_gnd_layer=None,
    overlap_pad_layer=None,
):
    """ Superconducting heater device from phidl.geometry

    Args:
        pad_size=(200, 200)
        wire_width=1
        wire_gap=3
        comb_layer=0
        overlap_zigzag_layer=1
        comb_pad_layer=None
        comb_gnd_layer=None
        overlap_pad_layer=None

    """
    CI = pp.Component()

    if comb_pad_layer is None:
        comb_pad_layer = comb_layer
    if comb_gnd_layer is None:
        comb_gnd_layer = comb_layer
    if overlap_pad_layer is None:
        overlap_pad_layer = overlap_zigzag_layer
    wire_spacing = wire_width + wire_gap * 2

    # %% pad overlays
    overlay_padb = CI.add_ref(
        pc.rectangle(size=(pad_size[0] * 9 / 10, pad_size[1] * 9 / 10),
                     layer=overlap_pad_layer))
    overlay_padl = CI.add_ref(
        pc.rectangle(size=(pad_size[0] * 9 / 10, pad_size[1] * 9 / 10),
                     layer=comb_pad_layer))
    overlay_padt = CI.add_ref(
        pc.rectangle(size=(pad_size[0] * 9 / 10, pad_size[1] * 9 / 10),
                     layer=comb_pad_layer))
    overlay_padr = CI.add_ref(
        pc.rectangle(size=(pad_size[0] * 9 / 10, pad_size[1] * 9 / 10),
                     layer=comb_gnd_layer))

    overlay_padl.xmin = 0
    overlay_padl.ymin = 0
    overlay_padb.ymax = 0
    overlay_padb.xmin = overlay_padl.xmax + pad_size[1] / 5
    overlay_padr.ymin = overlay_padl.ymin
    overlay_padr.xmin = overlay_padb.xmax + pad_size[1] / 5
    overlay_padt.xmin = overlay_padl.xmax + pad_size[1] / 5
    overlay_padt.ymin = overlay_padl.ymax

    # %% pads
    padl = CI.add_ref(pc.rectangle(size=pad_size, layer=comb_layer))
    padt = CI.add_ref(pc.rectangle(size=pad_size, layer=comb_layer))
    padr = CI.add_ref(pc.rectangle(size=pad_size, layer=comb_layer))
    padb = CI.add_ref(pc.rectangle(size=pad_size, layer=overlap_zigzag_layer))
    padl_nub = CI.add_ref(
        pc.rectangle(size=(pad_size[0] / 4, pad_size[1] / 2),
                     layer=comb_layer))
    padr_nub = CI.add_ref(
        pc.rectangle(size=(pad_size[0] / 4, pad_size[1] / 2),
                     layer=comb_layer))

    padl.xmin = overlay_padl.xmin
    padl.center = [padl.center[0], overlay_padl.center[1]]
    padt.ymax = overlay_padt.ymax
    padt.center = [overlay_padt.center[0], padt.center[1]]
    padr.xmax = overlay_padr.xmax
    padr.center = [padr.center[0], overlay_padr.center[1]]
    padb.ymin = overlay_padb.ymin
    padb.center = [overlay_padb.center[0], padb.center[1]]
    padl_nub.xmin = padl.xmax
    padl_nub.center = [padl_nub.center[0], padl.center[1]]
    padr_nub.xmax = padr.xmin
    padr_nub.center = [padr_nub.center[0], padr.center[1]]

    # %% connected zig

    head = CI.add_ref(
        pc.compass(size=(pad_size[0] / 12, wire_width), layer=comb_layer))
    head.xmin = padl_nub.xmax
    head.ymax = padl_nub.ymax
    connector = CI.add_ref(
        pc.compass(size=(wire_width, wire_width), layer=comb_layer))
    connector.connect(port="W", destination=head.ports["E"])
    old_port = connector.ports["S"]
    top = True
    obj = connector
    while obj.xmax + pad_size[0] / 12 < padr_nub.xmin:
        # long zig zag rectangle
        obj = CI.add_ref(
            pc.compass(size=(pad_size[1] / 2 - 2 * wire_width, wire_width),
                       layer=comb_layer))
        obj.connect(port="W", destination=old_port)
        old_port = obj.ports["E"]
        if top:
            # zig zag edge rectangle
            obj = CI.add_ref(
                pc.compass(size=(wire_width, wire_width), layer=comb_layer))
            obj.connect(port="N", destination=old_port)
            top = False
        else:
            # zig zag edge rectangle
            obj = CI.add_ref(
                pc.compass(size=(wire_width, wire_width), layer=comb_layer))
            obj.connect(port="S", destination=old_port)
            top = True
            # comb rectange
            comb = CI.add_ref(
                pc.rectangle(
                    size=(
                        (padt.ymin - head.ymax) + pad_size[1] / 2 -
                        (wire_spacing + wire_width) / 2,
                        wire_width,
                    ),
                    layer=comb_layer,
                ))
            comb.rotate(90)
            comb.ymax = padt.ymin
            comb.xmax = obj.xmax - (wire_spacing + wire_width) / 2
        old_port = obj.ports["E"]
        obj = CI.add_ref(
            pc.compass(size=(wire_spacing, wire_width), layer=comb_layer))
        obj.connect(port="W", destination=old_port)
        old_port = obj.ports["E"]
        obj = CI.add_ref(
            pc.compass(size=(wire_width, wire_width), layer=comb_layer))
        obj.connect(port="W", destination=old_port)
        if top:
            old_port = obj.ports["S"]
        else:
            old_port = obj.ports["N"]
    old_port = obj.ports["E"]
    if padr_nub.xmin - obj.xmax > 0:
        tail = CI.add_ref(
            pc.compass(size=(padr_nub.xmin - obj.xmax, wire_width),
                       layer=comb_layer))
    else:
        tail = CI.add_ref(
            pc.compass(size=(wire_width, wire_width), layer=comb_layer))
    tail.connect(port="W", destination=old_port)

    # %% disconnected zig

    dhead = CI.add_ref(
        pc.compass(
            size=(padr_nub.ymin - padb.ymax - wire_width, wire_width),
            layer=overlap_zigzag_layer,
        ))
    dhead.rotate(90)
    dhead.ymin = padb.ymax
    dhead.xmax = tail.xmin - (wire_spacing + wire_width) / 2
    connector = CI.add_ref(
        pc.compass(size=(wire_width, wire_width), layer=overlap_zigzag_layer))
    connector.connect(port="S", destination=dhead.ports["E"])
    old_port = connector.ports["N"]
    right = True
    obj = connector
    while obj.ymax + wire_spacing + wire_width < head.ymax:
        obj = CI.add_ref(
            pc.compass(size=(wire_spacing, wire_width),
                       layer=overlap_zigzag_layer))
        obj.connect(port="W", destination=old_port)
        old_port = obj.ports["E"]
        if right:
            obj = CI.add_ref(
                pc.compass(size=(wire_width, wire_width),
                           layer=overlap_zigzag_layer))
            obj.connect(port="W", destination=old_port)
            right = False
        else:
            obj = CI.add_ref(
                pc.compass(size=(wire_width, wire_width),
                           layer=overlap_zigzag_layer))
            obj.connect(port="E", destination=old_port)
            right = True
        old_port = obj.ports["N"]
        obj = CI.add_ref(
            pc.compass(
                size=(
                    dhead.xmin - (head.xmax + head.xmin + wire_width) / 2,
                    wire_width,
                ),
                layer=overlap_zigzag_layer,
            ))
        obj.connect(port="E", destination=old_port)
        old_port = obj.ports["W"]
        obj = CI.add_ref(
            pc.compass(size=(wire_width, wire_width),
                       layer=overlap_zigzag_layer))
        obj.connect(port="S", destination=old_port)
        if right:
            old_port = obj.ports["W"]
        else:
            old_port = obj.ports["E"]

    return CI
Exemple #4
0
def test_via(
    num_vias=100,
    wire_width=10,
    via_width=15,
    via_spacing=40,
    pad_size=(300, 300),
    min_pad_spacing=0,
    pad_layer=0,
    wiring1_layer=1,
    wiring2_layer=2,
    via_layer=3,
):
    """ Via cutback to extract via resistance
    from phidl.geometry

    Args:
        num_vias=100
        wire_width=10
        via_width=15
        via_spacing=40
        pad_size=(300, 300)
        min_pad_spacing=0
        pad_layer=0
        wiring1_layer=1
        wiring2_layer=2
        via_layer=3

    Usage:
        Call via_route_test_structure() by indicating the number of vias you want drawn. You can also change the other parameters however
        if you do not specifiy a value for a parameter it will just use the default value
        Ex::

            via_route_test_structure(num_vias=54)

        - or -::

            via_route_test_structure(num_vias=12, pad_size=(100,100),wire_width=8)

        total requested vias (num_vias) -> this needs to be even
        pad size (pad_size) -> given in a pair (width, height)
        wire_width -> how wide each wire should be
        pad_layer -> GDS layer number of the pads
        wiring1_layer -> GDS layer number of the top wiring
        wiring2_layer -> GDS layer number of the bottom wiring
        via_layer -> GDS layer number of the vias
        ex: via_route(54, min_pad_spacing=300)

    .. plot::
      :include-source:

      import pp

      c = pp.c.test_via()
      pp.plotgds(c)
    """

    VR = pp.Component()
    pad1 = VR.add_ref(pc.rectangle(size=pad_size, layer=pad_layer))
    pad1_overlay = VR.add_ref(pc.rectangle(size=pad_size, layer=wiring1_layer))
    pad2 = VR.add_ref(pc.rectangle(size=pad_size, layer=pad_layer))
    pad2_overlay = VR.add_ref(pc.rectangle(size=pad_size, layer=wiring1_layer))
    nub = VR.add_ref(
        pc.compass(size=(3 * wire_width, wire_width), layer=pad_layer))
    nub_overlay = VR.add_ref(
        pc.compass(size=(3 * wire_width, wire_width), layer=wiring1_layer))
    head = VR.add_ref(
        pc.compass(size=(wire_width, wire_width), layer=pad_layer))
    head_overlay = VR.add_ref(
        pc.compass(size=(wire_width, wire_width), layer=wiring1_layer))
    nub.ymax = pad1.ymax - 5
    nub.xmin = pad1.xmax
    nub_overlay.ymax = pad1.ymax - 5
    nub_overlay.xmin = pad1.xmax
    head.connect(port="W", destination=nub.ports["E"])
    head_overlay.connect(port="W", destination=nub_overlay.ports["E"])
    pad1_overlay.xmin = pad1.xmin
    pad1_overlay.ymin = pad1.ymin

    old_port = head.ports["S"]
    count = 0
    width_via_iter = 2 * via_spacing - 2 * wire_width

    pad2.xmin = pad1.xmax + min_pad_spacing
    up = False
    down = True
    edge = True
    current_width = 3 * wire_width + wire_width  # width of nub and 1 overlap
    obj_old = head
    obj = head
    via_iterable = _via_iterable(
        via_spacing=via_spacing,
        wire_width=wire_width,
        wiring1_layer=wiring1_layer,
        wiring2_layer=wiring2_layer,
        via_layer=via_layer,
        via_width=via_width,
    )
    while (count + 2) <= num_vias:
        obj = VR.add_ref(via_iterable)
        obj.connect(port="W", destination=old_port, overlap=wire_width)
        old_port = obj.ports["E"]
        edge = False
        if obj.ymax > pad1.ymax:
            obj.connect(port="W",
                        destination=obj_old.ports["S"],
                        overlap=wire_width)
            old_port = obj.ports["S"]
            current_width += width_via_iter
            down = True
            up = False
            edge = True

        elif obj.ymin < pad1.ymin:
            obj.connect(port="W",
                        destination=obj_old.ports["N"],
                        overlap=wire_width)
            old_port = obj.ports["N"]
            current_width += width_via_iter
            up = True
            down = False
            edge = True
        count = count + 2
        obj_old = obj

    if (current_width < min_pad_spacing
            and (min_pad_spacing - current_width) > 3 * wire_width):
        tail = VR.add_ref(
            pc.compass(
                size=(min_pad_spacing - current_width + wire_width,
                      wire_width),
                layer=wiring1_layer,
            ))
        tail_overlay = VR.add_ref(
            pc.compass(
                size=(min_pad_spacing - current_width + wire_width,
                      wire_width),
                layer=pad_layer,
            ))
    else:
        tail = VR.add_ref(
            pc.compass(size=(3 * wire_width, wire_width), layer=wiring1_layer))
        tail_overlay = VR.add_ref(
            pc.compass(size=(3 * wire_width, wire_width), layer=wiring1_layer))

    if up == True and edge != True:
        tail.connect(port="W", destination=obj.ports["S"], overlap=wire_width)
        tail_overlay.connect(port="W",
                             destination=obj.ports["S"],
                             overlap=wire_width)
    elif down == True and edge != True:
        tail.connect(port="W", destination=obj.ports["N"], overlap=wire_width)
        tail_overlay.connect(port="W",
                             destination=obj.ports["N"],
                             overlap=wire_width)
    else:
        tail.connect(port="W", destination=obj.ports["E"], overlap=wire_width)
        tail_overlay.connect(port="W",
                             destination=obj.ports["E"],
                             overlap=wire_width)

    pad2.xmin = tail.xmax
    pad2_overlay.xmin = pad2.xmin
    pad2_overlay.ymin = pad2.ymin

    return VR