Exemplo n.º 1
0
    def draw(self, cell):
        layout = cell.layout()

        cp = self.get_cell_params()
        lay = self.get_layers(layout)
        origin, ex, ey = self.origin_ex_ey()

        w_mh = cp.mh_width
        length = cp.mh_length
        w_contacts = cp.w_contacts

        input_port_position = origin - length / 2 * ex
        output_port_postion = origin + length / 2 * ex
        x_off = length / 2 - w_contacts / 2
        y_off = w_mh / 2 + w_contacts / 2

        input_contact_position = origin - x_off * ex + y_off * ey
        output_contact_position = origin + x_off * ex + y_off * ey

        # draw metal heater
        layout_waveguide(cell, lay.M_Heater,
                         [input_port_position, output_port_postion], w_mh)

        # draw metal contacts

        # Left contacts
        contact_points = [
            origin - x_off * ex + (y_off - w_contacts / 2) * ey,
            origin - x_off * ex + (y_off + w_contacts / 2) * ey,
        ]

        layout_waveguide(cell, lay.M_Heater, contact_points, w_contacts)
        layout_waveguide(cell, lay.ML, contact_points, w_contacts)

        # Right contacts
        contact_points = [
            origin + x_off * ex + (y_off - w_contacts / 2) * ey,
            origin + x_off * ex + (y_off + w_contacts / 2) * ey,
        ]
        layout_waveguide(cell, lay.M_Heater, contact_points, w_contacts)
        layout_waveguide(cell, lay.ML, contact_points, w_contacts)

        ports = [
            Port("el_contact_1", input_contact_position, ey, w_contacts),
            Port("el_contact_2", output_contact_position, ey, w_contacts),
        ]

        return cell, {port.name: port for port in ports}
Exemplo n.º 2
0
 def layout_mzi_curve(P0, P1):
     curve = bezier_optimal(P0, P1, cp.angle_ex, cp.angle_ex)
     return layout_waveguide(cell,
                             lay.Si,
                             curve,
                             cp.wg_width,
                             smooth=True)
Exemplo n.º 3
0
def layout_connect_ports(cell, layer, port_from, port_to, smooth=True):
    """ Places an "optimal" bezier curve from port_from to port_to.
    """

    if port_from.name.startswith("el"):
        assert port_to.name.startswith("el")
        P0 = port_from.position + port_from.direction * port_from.width / 2
        P3 = port_to.position + port_to.direction * port_to.width / 2
        smooth = smooth and True
    else:
        dbu = cell.layout().dbu
        P0 = port_from.position - dbu * port_from.direction
        P3 = port_to.position - dbu * port_to.direction
        smooth = smooth or True
    angle_from = np.arctan2(port_from.direction.y,
                            port_from.direction.x) * 180 / pi
    angle_to = np.arctan2(-port_to.direction.y,
                          -port_to.direction.x) * 180 / pi

    curve = bezier_optimal(P0, P3, angle_from, angle_to)
    if debug:
        for point in curve:
            print(point)
        print(f"bezier_optimal({P0}, {P3}, {angle_from}, {angle_to})")
    return layout_waveguide(cell,
                            layer,
                            curve, [port_from.width, port_to.width],
                            smooth=smooth)
Exemplo n.º 4
0
def main():
    layout = pya.Layout()
    TOP = layout.create_cell("TOP")

    layer = pya.LayerInfo(1, 0)  # First layer

    origin = pya.DPoint(0, 0)
    ex = pya.DVector(1, 0)
    ey = pya.DVector(0, 1)

    angles = np.linspace(-170, 170, 13)

    for i, angle_0 in enumerate(angles):
        for j, angle_3 in enumerate(angles):
            curve = bezier_curve(origin + ey * i * 150 + ex * j * 150, angle_0,
                                 angle_3, ex, ey)
            layout_waveguide(TOP, layer, curve, width=0.5)

    layout.write("bezier_waveguides.gds")
Exemplo n.º 5
0
def connect_ports_L(cell, cplayer, ports_from, ports_to, ex):
    """ Connects ports ports_from to ports_to, always leaving vertically"""

    ey = rotate90(ex)
    for port_from, port_to in zip(ports_from, ports_to):
        assert port_from.direction == ey or port_from.direction == -ey
        o_y = ey if port_to.position * ey > port_from.position * ey else -ey
        o_x = ex if port_to.position * ex > port_from.position * ex else -ex

        middle_point = manhattan_intersection(port_from.position,
                                              port_to.position, ex)
        layout_waveguide(
            cell,
            ensure_layer(cell.layout(), cplayer),
            [port_from.position, middle_point + port_to.width * 0.5 * o_y],
            port_from.width,
        )
        layout_waveguide(
            cell,
            ensure_layer(cell.layout(), cplayer),
            [middle_point - port_from.width * 0.5 * o_x, port_to.position],
            port_to.width,
        )
Exemplo n.º 6
0
def layout_waveguide_from_points(
    cell, layer, points, width, radius, taper_width=None, taper_length=None
):

    assert radius > width / 2, "Please use a radius larger than the half-width"
    points = unique_points(points)

    if len(points) < 2:
        # Nothing to do
        return cell

    # First, get the list of lines and arcs
    try:
        rounded_path = compute_rounded_path(points, radius)
    except Exception as e:
        print("ERROR:", e)
        print("Continuing...")
        layout_waveguide(cell, layer, points, 0.1)
        return cell

    # Taper path if necessary
    if taper_width is not None and taper_length is not None:
        waveguide_path = compute_tapered_path(
            rounded_path, width, taper_width, taper_length
        )
    else:
        waveguide_path = compute_untapered_path(rounded_path, width)

    # creating a single path
    _draw_points = []
    _draw_widths = []
    for element in waveguide_path:
        points, width = element.points, element.widths
        n_points = len(points)
        try:
            if len(width) == n_points:
                _draw_points.extend(points)
                _draw_widths.extend(width)
            elif len(width) == 2:
                _draw_widths.extend(np.linspace(width[0], width[1], n_points))
                _draw_points.extend(points)
            else:
                raise RuntimeError("Internal error detected. Debug please.")
        except TypeError:
            _draw_points.extend(points)
            _draw_widths.extend(np.ones(n_points) * width)

    # deleting repeated points
    _cur_point = None
    _draw_points2 = []
    _draw_widths2 = []
    for p, w in zip(_draw_points, _draw_widths):
        if _cur_point and p == _cur_point:
            continue
        _draw_points2.append(p)
        _draw_widths2.append(w)
        _cur_point = p

    layout_waveguide(cell, layer, _draw_points2, _draw_widths2, smooth=False)

    return cell
Exemplo n.º 7
0
 def layout(self, cell, layer):
     layout_waveguide(cell, layer, self.points, self.widths, smooth=False)
Exemplo n.º 8
0
    def draw(self, cell):
        layout = cell.layout()

        cp = self.get_cell_params()
        lay = self.get_layers(layout)
        origin, ex, ey = self.origin_ex_ey()

        YBranch_te1550_Cell_0, YBranch_te1550_Ports_0 = YBranch_te1550(
            "Broadband_DC", params={
                "angle_ex": cp.angle_ex
            }).new_cell(layout)
        YBranch_te1550_Ports_0 = place_cell(cell, YBranch_te1550_Cell_0,
                                            YBranch_te1550_Ports_0, origin)

        Broadband_DC_Cell, Broadband_DC_Ports = Broadband_DC_te1550(
            "Broadband_DC", cp).new_cell(layout)
        Broadband_DC_Ports = place_cell(
            cell,
            Broadband_DC_Cell,
            Broadband_DC_Ports,
            origin + (cp.waveguide_length_MZI + 100) * ex,
        )

        top_arm_left = (YBranch_te1550_Ports_0["opt2"].position + 25 * ex +
                        cp.MZI_height / 2 * ey)
        top_arm_right = top_arm_left + cp.waveguide_length_MZI * ex
        layout_waveguide(cell, lay.Si, [top_arm_left, top_arm_right], 0.5)

        Heater_1_MZI_Cell, Heater_1_MZI_Ports = Waveguide_heater(
            "waveguide heater",
            params={
                "wg_length": cp.waveguide_length_MZI,
                "angle_ex": cp.angle_ex
            },
        ).new_cell(layout)
        Heater_1_MZI_Ports = place_cell(
            cell,
            Heater_1_MZI_Cell,
            Heater_1_MZI_Ports,
            YBranch_te1550_Ports_0["opt2"].position + 25 * ex +
            cp.MZI_height / 2 * ey + cp.waveguide_length_MZI / 2 * ex,
        )

        bottom_arm_left = (YBranch_te1550_Ports_0["opt3"].position + 25 * ex -
                           cp.MZI_height / 2 * ey)
        bottom_arm_right = bottom_arm_left + cp.waveguide_length_MZI * ex
        layout_waveguide(cell, lay.Si, [bottom_arm_left, bottom_arm_right],
                         0.5)

        from zeropdk.layout.geometry import bezier_optimal

        def layout_mzi_curve(P0, P1):
            curve = bezier_optimal(P0, P1, cp.angle_ex, cp.angle_ex)
            return layout_waveguide(cell,
                                    lay.Si,
                                    curve,
                                    cp.wg_width,
                                    smooth=True)

        layout_mzi_curve(YBranch_te1550_Ports_0["opt2"].position, top_arm_left)
        layout_mzi_curve(YBranch_te1550_Ports_0["opt3"].position,
                         bottom_arm_left)

        layout_mzi_curve(top_arm_right, Broadband_DC_Ports["opt1"].position)
        layout_mzi_curve(bottom_arm_right, Broadband_DC_Ports["opt2"].position)

        ports = []

        ports.append(YBranch_te1550_Ports_0["opt1"].rename("opt_in"))
        ports.append(Broadband_DC_Ports["opt3"].rename("opt_out_1"))
        ports.append(Broadband_DC_Ports["opt4"].rename("opt_out_2"))
        ports.extend(Heater_1_MZI_Ports.values())

        if cp.layout_ports:
            for port in ports:
                port.draw(cell, lay.PinRec)
            insert_shape(cell, lay.DevRec, cell.bbox())

        return cell, {port.name: port for port in ports}
Exemplo n.º 9
0
def common_layout_manhattan_traces(cell,
                                   layer1,
                                   layer2,
                                   layervia,
                                   via_cell_placer,
                                   path,
                                   ex,
                                   initiate_with_via=False):
    """Lays out a manhattan trace, potentially with vias

    Args:
        layer1 and layer2 are given to layout.LayerInfo(layer), generally
            layer2 is on top
        via_cell_placer: returns a cell when called with
            via_cell_placer(parent_cell, pya.DPoint origin, width, layer1, layer2, layervia, ex)
        path: list of tuples containing necessary info ((x, y) or pya.DPoint, layer, width)

    Returns:
        path

    Algorithm places a via when there is a change of layers. To terminate with a via,
    have the last layer be different than the penultimate one.
    """

    assert isinstance(ex, (pya.DPoint, pya.DVector))
    ey = rotate90(ex)

    first_point, _, first_width = path[0]
    if initiate_with_via:
        via_cell_placer(cell, first_point, first_width, layer1, layer2,
                        layervia, ex)

    points_list = list()
    widths_list = list()
    _, previous_layer, _ = path[0]
    layout = cell.layout()

    for point, layer, width in path:
        if isinstance(point, tuple):  # point are (x, y) coordinates
            x, y = point
            point = x * ex + y * ey
        else:
            assert isinstance(point, (pya.DPoint, pya.DVector))
            if isinstance(point, pya.DVector):
                point = pya.DPoint(point)

        if layer == previous_layer:
            points_list.append(point)  # store points
            widths_list.append(width)
        else:  # time to place a via and layout
            points_list.append(point)
            widths_list.append(width)
            layout_waveguide(
                cell,
                ensure_layer(layout, previous_layer),
                points_list,
                widths_list,
                smooth=True,
            )

            via_cell_placer(cell, point, width, layer1, layer2, layervia, ex)

            # delete all but the last point
            del points_list[:-1]
            del widths_list[:-1]
        previous_layer = layer

    # layout last trace
    if len(points_list) >= 2:
        layout_waveguide(
            cell,
            ensure_layer(layout, previous_layer),
            points_list,
            widths_list,
            smooth=True,
        )

    return path