Example #1
0
def extend_port(port, width, length, layer):
    '''Create a rectangle extending perpendicularly from the port.

    Attributes:
    ----------
        port : dl.Port

        width : float

        length : float

        layer : int, tuple or set

    Returns:
    -------
        dl.Device.
    '''

    p1 = Point(port.midpoint)

    dir = Point(port.normal[1]) - Point(port.normal[0])

    p2 = p1 + dir * length

    p = path.smooth(points=[p1.coord, p2.coord])

    return p.extrude(width=width, layer=layer)
Example #2
0
def get_corners(device: Device):
    ''' get corners of a device.

    Parameters
    ---------
    device : phidl.Device

    Returns:
    ll : pt.Point
        lower left

    lr : pt.Point
        lower right

    ul : pt.Point
        upper left

    ur : pt.Point

    c : pt.Point

    n : pt.point

    s : pt.point

    w : pt.Point

    e : pt.Point.
    '''
    bbox = device.bbox
    ll = Point(bbox[0, 0], bbox[0, 1])
    lr = Point(bbox[1, 0], bbox[0, 1])
    ul = Point(bbox[0, 0], bbox[1, 1])
    ur = Point(bbox[1, 0], bbox[1, 1])
    n = Point(device.center[0], bbox[1, 1])
    s = Point(device.center[0], bbox[0, 1])
    w = Point(bbox[0, 0], device.center[1])
    e = Point(bbox[1, 0], device.center[1])
    c = Point(device.center)

    class ReferencePoints():
        pass

    r = ReferencePoints()
    r.ll = ll
    r.lr = lr
    r.ul = ul
    r.ur = ur
    r.c = c
    r.n = n
    r.s = s
    r.w = w
    r.e = e
    return r
Example #3
0
def move_relative_to_cell(cell_to_be_moved,
                          cell_ref,
                          anchor_source='ll',
                          anchor_dest='ll',
                          offset=(0, 0)):
    '''Move cell_to_be_moved relative to cell_ref, by specifying anchors.

        Anchors are specified as described in get_corners().
        Offset is specified as normalized to cell_ref size.

        Attributes:
        ---------
            cell_to_be_moved: dl.Device

            cell_ref:dl.Device

            anchor_source: string

            anchor_dest: string

            offset : tuple.
    '''

    a_origin = get_anchor(anchor_source, cell_to_be_moved)

    a_end = get_anchor(anchor_dest, cell_ref)

    dx = cell_ref.xmax - cell_ref.xmin
    dy = cell_ref.ymax - cell_ref.ymin

    offset = Point(dx * offset[0], dy * offset[1])

    cell_to_be_moved.move(origin=a_origin.coord, destination=a_end.coord)
    cell_to_be_moved.move(destination=offset.coord)
Example #4
0
def get_centroid_ports(*ports):
    '''Calculate port with matching orientation and with as input ports, and midpoint at the
        centroid of the input ports midpoint.

    Attributes:
    ----------
        *ports : dl.Port

    Returns:
    -------
        dl.Port.
    '''

    if not ports:

        raise ValueError(f"st.get_centroid_ports(): no ports passed")

    if isinstance(ports, Port):

        return ports

    else:

        ports_centroid = get_centroid(*[Point(x.midpoint) for x in ports])

        ports_width = np.average([x.width for x in ports])

        ports_orientation = np.average([x.orientation for x in ports])

        return Port(orientation=ports_orientation,
                    width=ports_width,
                    midpoint=ports_centroid.coord)
Example #5
0
def shift_port(port, dist):
    '''Returns new port with translated midpoint.

    Attributes:
    ----------
        port : dl.Port

        dist : float

    Returns:
        dl.Port.
    '''

    port_mid_norm = Point(port.normal[1]) - Point(port.normal[0])

    midpoint_projected = Point(port.midpoint) + port_mid_norm * dist

    new_port = Port(name=port.name + 'shifted',
                    orientation=port.orientation,
                    width=port.width,
                    midpoint=midpoint_projected.coord)

    return new_port
Example #6
0
def get_centroid(*points):
    ''' Calculates centroid of passed points.

    Arguments:
    ---------
        *points : pt.Point

    Returns:
    --------
        pt.Point.
    '''
    x_c = 0
    y_c = 0

    if isinstance(points, Point):

        return points

    for p in points:

        x_c = x_c + p.x
        y_c = y_c + p.y

    return Point(x_c, y_c) / len(points)
Example #7
0
def connect_ports(cell: Device,
                  tag: str = 'top',
                  layers: tuple = (LayoutDefault.layerTop, ),
                  distance: float = 10.0,
                  metal_width: float = None):
    ''' connects all the ports in the cell with name matching a tag.

    Parameters:
    -----------
        cell : Device

        tag: str

        conn_dist: pt.Point
            offset from port location

        layer : tuple.


    Returns:
    ----------

        cell : Device
            contains routings and connection port

    '''

    import pirel.pcells as pc

    ports = pt._find_ports(cell, tag, depth=0)

    ports.sort(key=lambda x: x.midpoint[0])

    ports_centroid = pt._get_centroid_ports(ports)

    if len(ports) == 1:

        raise ValueError("pm.connect_ports() : len(ports) must be >1 ")

    if metal_width is None:

        metal_width = ports_centroid.width

    port_mid_norm = pt.Point(ports_centroid.normal[1]) - pt.Point(
        ports_centroid.normal[0])

    midpoint_projected = Point(
        ports_centroid.midpoint) + port_mid_norm * (distance + metal_width)

    pad_side = ports_centroid.width

    new_port = Port(name=tag,
                    orientation=ports_centroid.orientation,
                    width=ports_centroid.width,
                    midpoint=midpoint_projected.coord)

    output_cell = Device()

    for p in ports:

        straight_conn = output_cell << pt._draw_multilayer(
            'compass',
            layers,
            size=(p.width, abs(midpoint_projected.y - p.midpoint[1])))

        straight_conn.connect("S", p)

    cross_conn = output_cell << pt._draw_multilayer(
        'compass', layers, size=(output_cell.xsize, metal_width))

    cross_conn.connect('S', new_port, overlap=metal_width)

    output = pt.join(output_cell)

    output.add_port(new_port)

    return output
Example #8
0
def draw_array(
    cell : Device,
    x : int, y : int,
    row_spacing : float = 0 ,
    column_spacing : float = 0 ) -> Device:
    ''' returns a spaced matrix of identical cells, including ports in the output cell.

    Parameters
    ----------
    cell : phidl.Device

    x : int
        columns of copies

    y : int
        rows of copies

    row_spacing: float

    column_spacing: float

    Returns
    -------
    cell : phidl.Device.
    '''

    new_cell=pg.Device(cell.name+"array")

    cell_size=Point(cell.size)+Point(column_spacing,row_spacing)

    for j in range(y):

        for i in range(x):

            if y==1 and x==1:

                ref=new_cell.add_ref(cell,alias=cell.name)

            elif y==1:

                ref=new_cell.add_ref(cell,alias=cell.name+'_'+str(i))

            elif x==1:

                ref=new_cell.add_ref(cell,alias=cell.name+'_'+str(j))

            else:

                ref=new_cell.add_ref(cell,alias=cell.name+'_'+str(i)+'_'+str(j))

            ref.move(
                destination=(Point(cell_size.x*i,cell_size.y*j)).coord)

            if y==1 and x==1:

                ppt.copy_ports(ref,new_cell)

            elif y==1:

                ppt.copy_ports(ref,new_cell,suffix='_'+str(i))

            elif x==1:

                ppt.copy_ports(ref,new_cell,suffix='_'+str(j))

            else:

                ppt.copy_ports(ref,new_cell,suffix='_'+str(i)+'_'+str(j))

    return new_cell