Exemplo n.º 1
0
    def __filter___Cell____(self, item):
        from spira.yevon.utils import clipping
        from spira.yevon.gdsii.cell import Cell

        ports = PortList()
        elems = ElementList()

        for e in item.elements.polygons:
            e.shape = clipping.simplify_points(e.points)
            elems += e

            # points = clipping.simplify_points(e.points)
            # elems += e.copy(shape=points)

            # p = e.__class__(shape=points, layer=e.layer, transformation=e.transformation)
            # elems += e.__class__(shape=points, layer=e.layer, transformation=e.transformation)

        for e in item.elements.sref:
            elems += e
        for e in item.elements.labels:
            elems += e
        for p in item.ports:
            ports += p

        cell = Cell(elements=elems, ports=ports)
        # cell = item.__class__(elements=elems, ports=ports)
        return cell
Exemplo n.º 2
0
def Route180(port1, port2, layer, width=None, corners='miter', bend_radius=1):
    """  """

    if port1.orientation == 0:
        p1 = [port1.midpoint[0], port1.midpoint[1]]
        p2 = [port2.midpoint[0], port2.midpoint[1]]
    if port1.orientation == 90:
        p1 = [port1.midpoint[1], -port1.midpoint[0]]
        p2 = [port2.midpoint[1], -port2.midpoint[0]]
    if port1.orientation == 180:
        p1 = [-port1.midpoint[0], -port1.midpoint[1]]
        p2 = [-port2.midpoint[0], -port2.midpoint[1]]
    if port1.orientation == 270:
        p1 = [-port1.midpoint[1], port1.midpoint[0]]
        p2 = [-port2.midpoint[1], port2.midpoint[0]]

    if width is None:
        width = port1.width

    dx = (p2[0] - p1[0]) / 2

    p3 = np.array(p2) - np.array(p1) - np.array([dx, 0])
    p4 = np.array(p2) - np.array(p1)

    path = gdspy.FlexPath([(0, 0), (dx, 0)],
                          width=width,
                          corners=corners,
                          bend_radius=bend_radius)
    path.segment(end_point=p3)
    path.segment(end_point=p4)

    if ug.angle_diff(port2.orientation, port1.orientation) != 180:
        raise ValueError(
            "Route error: Ports do not face each other (orientations must be 180 apart)"
        )
    else:
        pl = PortList()
        pl += Port(name='I1',
                   midpoint=(0, 0),
                   width=port1.width,
                   orientation=180,
                   process=layer.process)
        pl += Port(name='I2',
                   midpoint=list(np.subtract(p2, p1)),
                   width=port2.width,
                   orientation=0,
                   process=layer.process)

    route_shape = RouteShape(path=path)
    R = Route(shape=route_shape, p1=pl[0], p2=pl[1], layer=layer)
    T = vector_match_transform(v1=R.ports[0], v2=port1)
    R.transform(T)
    return R
Exemplo n.º 3
0
    def __init__(self,
                 name=None,
                 elements=None,
                 ports=None,
                 library=None,
                 **kwargs):
        super().__init__(**kwargs)

        if name is not None:
            s = '{}_{}'.format(name, Cell._next_uid)
            self.__dict__['__name__'] = s
            Cell.name.__set__(self, s)

        self.uid = Cell._next_uid
        Cell._next_uid += 1

        if library is not None:
            self.library = library
        if elements is not None:
            self.elements = ElementList(elements)
        if ports is not None:
            self.ports = PortList(ports)
Exemplo n.º 4
0
def shape_edge_ports(shape, layer, local_pid='None', center=(0,0), loc_name=''):

    # FIXME: Integrate with edges.
    from spira.yevon.geometry.ports.port import Port
    from spira.yevon.process.gdsii_layer import Layer
    
    shape = shape.remove_straight_angles()
    # shape = shape.reverse_points()

    edges = PortList()

    xpts = list(shape.x_coords)
    ypts = list(shape.y_coords)

    n = len(xpts)

    xpts.append(xpts[0])
    ypts.append(ypts[0])

    clockwise = 0
    for i in range(0, n):
        clockwise += ((xpts[i+1] - xpts[i]) * (ypts[i+1] + ypts[i]))

    if layer.name == 'BBOX': bbox = True
    else: bbox = False

    layer = RDD.GDSII.IMPORT_LAYER_MAP[layer]

    for i in range(0, n):
        # name = 'E{}_{}'.format(i, layer.process.symbol)
        # name = 'E{}_{}_{}'.format(i, layer.process.symbol, shape.bbox_info.center)
        # print(loc_name)
        name = '{}E{}'.format(loc_name, i)
        # print(name)
        x = np.sign(clockwise) * (xpts[i+1] - xpts[i])
        y = np.sign(clockwise) * (ypts[i] - ypts[i+1])
        orientation = (np.arctan2(x, y) * constants.RAD2DEG)
        midpoint = [(xpts[i+1] + xpts[i])/2, (ypts[i+1] + ypts[i])/2]
        width = np.abs(np.sqrt((xpts[i+1] - xpts[i])**2 + (ypts[i+1]-ypts[i])**2))
        P = Port(
            name=name,
            process=layer.process,
            purpose=RDD.PURPOSE.PORT.OUTSIDE_EDGE_DISABLED,
            midpoint=midpoint,
            orientation=orientation,
            width=width,
            length=0.2,
            local_pid=local_pid
        )
        edges += P
    return edges
Exemplo n.º 5
0
def Route90(port1, port2, layer, width=None, corners='miter', bend_radius=1):
    """  """

    if port1.orientation == 0:
        p1 = [port1.midpoint[0], port1.midpoint[1]]
        p2 = [port2.midpoint[0], port2.midpoint[1]]
    if port1.orientation == 90:
        p1 = [port1.midpoint[1], -port1.midpoint[0]]
        p2 = [port2.midpoint[1], -port2.midpoint[0]]
    if port1.orientation == 180:
        p1 = [-port1.midpoint[0], -port1.midpoint[1]]
        p2 = [-port2.midpoint[0], -port2.midpoint[1]]
    if port1.orientation == 270:
        p1 = [-port1.midpoint[1], port1.midpoint[0]]
        p2 = [-port2.midpoint[1], port2.midpoint[0]]

    if width is None:
        width = port1.width

    dx = abs(p2[0] - p1[0])
    dy = abs(p2[1] - p1[1])

    p3 = np.array(p2) - np.array(p1)

    path = gdspy.FlexPath([(0, 0), (dx, 0)],
                          width=width,
                          corners=corners,
                          bend_radius=bend_radius)
    path.segment(end_point=p3)

    pl = PortList()
    pl += Port(name='I1',
               midpoint=(0, 0),
               width=port1.width,
               orientation=180,
               process=layer.process)
    pl += Port(name='I2',
               midpoint=list(np.subtract(p2, p1)),
               width=port2.width,
               orientation=90,
               process=layer.process)

    route_shape = RouteShape(path=path)
    R = Route(shape=route_shape, p1=pl[0], p2=pl[1], layer=layer)
    T = vector_match_transform(v1=R.ports[0], v2=port1)
    R.transform(T)
    return R
Exemplo n.º 6
0
    def filter_Cell(self, item):
        from spira.yevon.utils import clipping
        from spira.yevon.gdsii.cell import Cell

        ports = PortList()
        elems = ElementList()

        for e in item.elements.polygons:
            e.shape = clipping.simplify_points(e.points)
            elems += e

        for e in item.elements.sref:
            elems += e
        for e in item.elements.labels:
            elems += e
        for p in item.ports:
            ports += p

        cell = Cell(elements=elems, ports=ports)
        return cell
Exemplo n.º 7
0
    def filter_Cell(self, item):
        from spira.yevon.gdsii.cell import Cell

        ports = PortList()
        elems = ElementList()

        for e in item.derived_merged_elements:
            elems += e
        for e in item.elements.sref:
            elems += e
        for e in item.elements.labels:
            elems += e
        for p in item.ports:
            if p.purpose.symbol == 'P':
                ports += p
            if p.purpose.symbol == 'T':
                ports += p

        cell = Cell(elements=elems, ports=ports)
        return cell
Exemplo n.º 8
0
    def __filter___Cell____(self, item):
        from spira.yevon.gdsii.cell import Cell

        ports = PortList()
        elems = ElementList()

        # for pg in item.process_elements:
        # for e in pg.elements:
        # elems += e

        for e in item.process_elements:
            elems += e
        for e in item.elements.sref:
            elems += e
        for e in item.elements.labels:
            elems += e
        for p in item.ports:
            ports += p

        cell = Cell(elements=elems, ports=ports)
        return cell
Exemplo n.º 9
0
    def __filter___Cell____(self, item):
        from spira.yevon.gdsii.cell import Cell
        from spira.yevon.utils import clipping
        from spira.yevon.vmodel.virtual import virtual_connect
        from shapely.geometry import Polygon as ShapelyPolygon

        ports = PortList()
        elems = ElementList()

        v_model = virtual_connect(device=item)
        for e in v_model.connected_elements:
            elems += e

        for e in item.elements.sref:
            elems += e
        for e in item.elements.labels:
            elems += e
        for p in item.ports:
            ports += p

        cell = Cell(elements=elems, ports=ports)
        return cell
Exemplo n.º 10
0
    def filter_Cell(self, item):
        from spira.yevon.gdsii.cell import Cell

        ports = PortList()
        elems = ElementList()

        c2dmap, devices = {}, {}

        for cell in item.dependencies():
            # FIXME: Why can I not use Cell?
            # ERC Port doesn't connect.
            D = item.__class__(name=cell.name,
                               elements=deepcopy(cell.elements.polygons),
                               ports=deepcopy(cell.ports))
            c2dmap.update({cell: D})

        for cell in item.dependencies():
            self.wrap_references(cell, c2dmap, devices)

        D = c2dmap[item]

        for e in D.elements.polygons:
            if e.layer.purpose.symbol == 'METAL':
                e.layer.purpose = RDD.PURPOSE.CIRCUIT_METAL
                # e.layer.purpose = RDD.PURPOSE.METAL

        for d in D.dependencies():
            if d in devices.keys():
                d.elements = devices[d]

                for e in d.elements.polygons:
                    if e.layer.purpose.symbol == 'METAL':
                        e.layer.purpose = RDD.PURPOSE.DEVICE_METAL
                        # e.layer.purpose = RDD.PURPOSE.METAL

        return D
Exemplo n.º 11
0
class Cell(__Cell__):
    """ A Cell encapsulates a set of elements that
    describes the layout being generated. """

    _next_uid = 0

    lcar = NumberParameter(default=100)
    name = Parameter(fdef_name='create_name', doc='Name of the cell instance.')

    def get_alias(self):
        if not hasattr(self, '__alias__'):
            self.__alias__ = self.name.split('__')[0]
        return self.__alias__

    def set_alias(self, value):
        self.__alias__ = value

    alias = FunctionParameter(
        get_alias,
        set_alias,
        doc='Functions to generate an alias for cell name.')

    def __init__(self,
                 name=None,
                 elements=None,
                 ports=None,
                 nets=None,
                 library=None,
                 **kwargs):
        __Cell__.__init__(self, **kwargs)

        if name is not None:
            s = '{}_{}'.format(name, Cell._next_uid)
            self.__dict__['__name__'] = s
            Cell.name.__set__(self, s)

        self.uid = Cell._next_uid
        Cell._next_uid += 1

        if library is not None:
            self.library = library
        if elements is not None:
            self.elements = ElementList(elements)
        if ports is not None:
            self.ports = PortList(ports)

    def __repr__(self):
        class_string = "[SPiRA: Cell(\'{}\')] (elements {}, ports {})"
        return class_string.format(self.name, self.elements.__len__(),
                                   self.ports.__len__())

    def __str__(self):
        return self.__repr__()

    def create_name(self):
        if not hasattr(self, '__name__'):
            self.__name__ = self.__name_generator__(self)
        return self.__name__

    def expand_transform(self):
        for S in self.elements.sref:
            S.expand_transform()
            S.reference.expand_transform()
        return self

    def expand_flat_copy(self, exclude_devices=False):
        from spira.yevon.gdsii.pcell import Device
        from spira.yevon.gdsii.polygon import Polygon
        from spira.yevon.gdsii.sref import SRef
        from spira.core.transforms.translation import Translation

        name = ''
        S = self.expand_transform()
        C = Cell(name=S.name + '_ExpandedCell')

        def _traverse_polygons(subj, cell, name):
            c_name = deepcopy(name)
            # print(cell)
            for e in cell.elements:
                if isinstance(e, SRef):
                    if e.alias is not None:
                        c_name += e.alias + ':'
                    else:
                        c_name += ':'
                    subj = _traverse_polygons(subj=subj,
                                              cell=e.reference,
                                              name=c_name)
                    # if exclude_devices is True:
                    #     if isinstance(e.reference, Device):
                    #         subj += e
                    #     else:
                    #         subj = _traverse_polygons(subj=subj, cell=e.reference, name=c_name)
                    # else:
                    #     subj = _traverse_polygons(subj=subj, cell=e.reference, name=c_name)
                elif isinstance(e, Polygon):
                    e.location_name = c_name
                    # e.transform(expand_transform)
                    # e.shape.move(expand_transform)
                    subj += e
                    # print(e.transformation)
                c_name = name
            # print('')
            return subj

        D = _traverse_polygons(C, S, name)

        return D

    def move(self, midpoint=(0, 0), destination=None, axis=None):
        """  """
        from spira.yevon.geometry.ports.base import __Port__

        if destination is None:
            destination = midpoint
            midpoint = [0, 0]

        if issubclass(type(midpoint), __Port__):
            o = midpoint.midpoint
        elif isinstance(midpoint, Coord):
            o = midpoint
        elif np.array(midpoint).size == 2:
            o = midpoint
        elif midpoint in obj.ports:
            o = obj.ports[midpoint].midpoint
        else:
            raise ValueError("[PHIDL] [DeviceReference.move()] ``midpoint`` " +
                             "not array-like, a port, or port name")

        if issubclass(type(destination), __Port__):
            d = destination.midpoint
        elif isinstance(destination, Coord):
            d = destination
        elif np.array(destination).size == 2:
            d = destination
        elif destination in obj.ports:
            d = obj.ports[destination].midpoint
        else:
            raise ValueError(
                "[PHIDL] [DeviceReference.move()] ``destination`` " +
                "not array-like, a port, or port name")

        if axis == 'x':
            d = (d[0], o[1])
        if axis == 'y':
            d = (o[0], d[1])

        d = Coord(d[0], d[1])
        o = Coord(o[0], o[1])

        for e in self.elements:
            e.move(midpoint=o, destination=d)

        for p in self.ports:
            mc = np.array(p.midpoint) + np.array(d) - np.array(o)
            p.move(midpoint=p.midpoint, destination=mc)

        return self

    def stretch_p2p(self, port, destination):
        """
        The element by moving the subject port, without
        distorting the entire element. Note: The opposite
        port position is used as the stretching center.
        """
        from spira.core.transforms import stretching
        from spira.yevon.geometry import bbox_info
        from spira.yevon.gdsii.polygon import Polygon
        opposite_port = bbox_info.bbox_info_opposite_boundary_port(self, port)
        T = stretching.stretch_element_by_port(self, opposite_port, port,
                                               destination)
        if port.bbox is True:
            self = T(self)
        else:
            for i, e in enumerate(self.elements):
                if isinstance(e, Polygon):
                    if e.id_string() == port.local_pid:
                        self.elements[i] = T(e)
        return self

    def nets(self, lcar):
        return self.elements.nets(lcar=lcar)

    def create_netlist(self):
        net = self.nets(lcar=self.lcar).disjoint()
        return net
Exemplo n.º 12
0
 def flat_copy(self, level=-1):
     el = PortList()
     for e in self._list:
         el += e.flat_copy(level)
     return el