Esempio n. 1
0
class PCell(Cell):
    """  """

    pcell = BoolParameter(default=True)
    routes = ElementListParameter(
        doc='List of `Route` elements connected to the cell.')
    structures = ElementListParameter(
        doc='List of cell structures that coalesces the top-level cell.')
Esempio n. 2
0
class PCell(Cell):
    """  """

    pcell = BoolParameter(default=True)
    routes = ElementListParameter(
        doc='List of `Route` elements connected to the cell.')
    structures = ElementListParameter(
        doc='List of cell structures that coalesces the top-level cell.')
    extract_netlist = Parameter(fdef_name='create_extract_netlist')

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
Esempio n. 3
0
class __Group__(ParameterInitializer):

    elements = ElementListParameter(
        fdef_name='__create_elements__',
        doc='List of elements added to cell instance.')

    def __create_elements__(self, elems):
        return self.create_elements(elems)

    def create_elements(self, elems):
        return elems

    def __iter__(self):
        return self.elements.__iter__()

    def __iadd__(self, element):
        from spira.yevon.geometry.ports.base import __Port__
        """ Add element and reduce the class to a simple compound elements. """
        if isinstance(element, (list, Group, spira.ElementList)):
            self.extend(element)
        elif issubclass(type(element), __Element__):
            self.append(element)
        elif element is None:
            return self
        else:
            raise TypeError("Invalid type " + str(type(element)) +
                            " in __Group__.__iadd__().")
        return self

    @property
    def bbox_info(self):
        return self.elements.bbox_info

    def append(self, element):
        el = self.elements
        el.append(element)
        self.elements = el

    def extend(self, elems):
        from spira.yevon.gdsii.group import Group
        el = self.elements
        if isinstance(elems, Group):
            el.extend(elems.elemetals)
        else:
            el.extend(elems)
        self.elements = el

    def flatten(self, level=-1):
        self.elements = self.elements.flatten(level=level)
        return self

    def is_empty(self):
        return self.elements.is_empty()
Esempio n. 4
0
class PolygonPortAspects(TransformablePortAspects):

    edge_ports = ElementListParameter()

    def create_edge_ports(self, edge_ports):
        # shape = self.shape
        shape = self.shape.transform_copy(self.transformation)
        layer = RDD.GDSII.IMPORT_LAYER_MAP[self.layer]
        if layer.purpose.symbol in ['METAL', 'DEVICE_METAL', 'CIRCUIT_METAL']:
            edge_ports = shapes.shape_edge_ports(shape, self.layer, self.id_string(), center=shape.bbox_info.center, loc_name=self.alias + ':')
        # if isinstance(self.transformation, ReversibleTransform):
        #     edge_ports.reverse_transform(self.transformation)
        return edge_ports
Esempio n. 5
0
class DerivedElements(__Aspects__):
    """ Convert the cell elements into a new set
    of elements for every active process. """

    derived_merged_elements = ElementListParameter()
    derived_overlap_elements = ElementListParameter()
    derived_diff_elements = ElementListParameter()

    def create_derived_merged_elements(self, elems):
        elems += get_process_polygons(self.elements, 'or')
        return elems

    def create_derived_overlap_elements(self, elems):
        elems += get_process_polygons(self.elements, 'and')
        return elems

    def create_derived_diff_elements(self, elems):
        elems += get_process_polygons(self.elements, 'not')
        return elems

    def view_derived_merged_elements(self, **kwargs):
        elems = ElementList()
        for pg in self.derived_merged_elements:
            for e in pg.elements:
                elems += e
        name = '{}_{}'.format(self.name, 'DERIVED_MERGED_ELEMENTS')
        D = Cell(name=name, elements=elems)
        D.gdsii_view()

    def view_derived_overlap_elements(self, **kwargs):
        elems = ElementList()
        for pg in self.derived_overlap_elements:
            for e in pg.elements:
                elems += e
        name = '{}_{}'.format(self.name, 'DERIVED_OVERLAP_ELEMENTS')
        D = Cell(name=name, elements=elems)
        D.gdsii_view()
Esempio n. 6
0
class ElementsForModelling(__Aspects__):
    """
    Convert the cell elements into a new set
    of elements for every active process.
    """

    process_elements = ElementListParameter()
    overlap_elements = ElementListParameter()

    def create_process_elements(self, elems):
        elems += get_process_polygons(self.elements, 'or')
        return elems

    def create_overlap_elements(self, elems):
        elems += get_process_polygons(self.elements, 'and')
        return elems

    def write_gdsii_mask(self, **kwargs):
        elems = ElementList()
        for pg in self.process_elements:
            for e in pg.elements:
                elems += e
        D = Cell(name=self.name + '_VMODEL', elements=elems)
        D.gdsii_output()
Esempio n. 7
0
class ReferenceBlocks(__Aspects__):
    """ Create a boundary block around the cell 
    references in the current cell structure. """

    block_elements = ElementListParameter()

    def create_block_elements(self, elems):
        for e in self.elements.sref:
            for layer in RDD.get_physical_layers_by_purpose(purposes=['METAL', 'GND']):
                if e.reference.is_layer_in_cell(layer):
                    bbox_shape = e.bbox_info.bounding_box()
                    elems += Polygon(shape=bbox_shape, layer=layer)
        return elems

    def write_gdsii_blocks(self, **kwargs):
        D = Cell(name=self.name + '_BLOCKS', elements=self.block_elements)
        D.gdsii_output()
Esempio n. 8
0
class NetProcessLabelFilter(__NetFilter__):
    """  """

    process_polygons = ElementListParameter()

    def filter_Net(self, item):
        triangles = item.process_triangles()
        for key, nodes in triangles.items():
            for n in nodes:
                for e in self.process_polygons:
                    if e.encloses(item.g.node[n]['position']):
                        item.g.node[n]['process_polygon'] = e
                        item.g.node[n]['display'] = RDD.DISPLAY.STYLE_SET[
                            e.layer]
        return [item]

    def __repr__(self):
        return "[SPiRA: NetLabelFilter] (layer count {})".format(0)
Esempio n. 9
0
class NetBlockLabelFilter(__NetFilter__):
    """  """

    from spira.yevon.vmodel.boundary import reference_metal_blocks

    references = ElementListParameter()

    def filter_Net(self, item):
        for S in self.references:
            for e in reference_metal_blocks(S):
                for n in item.g.nodes():
                    if e.encloses(item.g.node[n]['position']):
                        item.g.node[n]['device_reference'] = S
                        item.g.node[n]['display'] = RDD.DISPLAY.STYLE_SET[
                            e.layer]
        return item

    def __repr__(self):
        return "[SPiRA: NetLabelFilter] (layer count {})".format(0)
Esempio n. 10
0
class PolygonPortProperty(TransformablePortProperty):
# class PolygonPortProperty(PortProperty):

    edge_ports = ElementListParameter()

    def create_edge_ports(self, edges):
        shape = self.shape
        # FIXME: Cannot apply transforms when stretching.
        # shape = self.shape.transform_copy(self.transformation)
        s = deepcopy(self.shape).transform_copy(self.transformation)
        return shapes.shape_edge_ports(shape, self.layer, self.id_string(), center=s.bbox_info.center, loc_name=self.location_name)

    def create_ports(self, ports):
        layer = RDD.GDSII.IMPORT_LAYER_MAP[self.layer]
        if layer.purpose.symbol == 'METAL':
            for edge in self.edge_ports:
                ports += edge
        # FIXME: This fails with CompoundTransforms, i.e. when stretching.
        # ports.transform(-self.transformation)
        return ports
Esempio n. 11
0
class NetEdgeFilter(__NetFilter__):
    """  """

    process_polygons = ElementListParameter()

    def _triangles_containing_line(self, item, line):
        nodes = []
        for n, triangle in enumerate(item.triangles):
            if (line[0] in triangle) and (line[1] in triangle):
                nodes.append(n)
        return nodes

    def filter_Net(self, item):

        ELM_TYPE = {1: 'line', 2: 'triangle'}

        # print('\n---------------------------------\n')

        # print('Triangles:')
        # print(item.triangles)
        # print('Lines:')
        # print(item.lines)
        # print('Physical Lines:')
        # print(item.physical_lines)

        # print('\n---------------------------------\n')

        # print('Parameter Data:')
        # for k, v in item.mesh_data.field_data.items():
        #     print(k, v)

        # print('\n---------------------------------\n')

        # print('Process Lines')
        # print(item.process_lines())
        # print('Process Triangles')
        # print(item.process_triangles())

        # print('\n---------------------------------\n')

        import re
        from spira.yevon.geometry.coord import Coord

        for key, value in item.mesh_data.field_data.items():

            line_keys = key.split('*')

            if len(line_keys) > 1:
                if line_keys[1] != 'None':

                    ply_string = key.split('*')[0]
                    ply_hash = key.split('*')[1]

                    elm_type = ELM_TYPE[value[1]]
                    if elm_type == 'line':

                        for i, physical_line_id in enumerate(
                                item.physical_lines):
                            if physical_line_id == value[0]:
                                for n in self._triangles_containing_line(
                                        item, item.lines[i]):

                                    name = 'P' + ply_string.split(' ')[0]
                                    pos = re.search(r'\((.*?)\)',
                                                    ply_string).group(1)
                                    pos = pos.split(',')
                                    pos = [float(p) for p in pos]
                                    midpoint = Coord(pos).snap_to_grid()
                                    item.g.node[n]['device_reference'] = Port(
                                        name=name,
                                        midpoint=midpoint,
                                        process=self.process_polygons.layer.
                                        process)
                                    item.g.node[n][
                                        'display'] = RDD.DISPLAY.STYLE_SET[
                                            RDD.PLAYER.I5.VIA]
                                    # item.g.node[n]['display'] = RDD.DISPLAY.STYLE_SET[RDD.PLAYER.M1.HOLE]

        return [item]

    # def __filter_Net__(self, item):

    #     ELM_TYPE = {1: 'line', 2: 'triangle'}

    #     # print('\n---------------------------------\n')

    #     # print('Triangles:')
    #     # print(item.triangles)
    #     # print('Lines:')
    #     # print(item.lines)
    #     # print('Physical Lines:')
    #     # print(item.physical_lines)

    #     # print('\n---------------------------------\n')

    #     # print('Parameter Data:')
    #     # for k, v in item.mesh_data.field_data.items():
    #     #     print(k, v)

    #     # print('\n---------------------------------\n')

    #     # print('Process Lines')
    #     # print(item.process_lines())
    #     # print('Process Triangles')
    #     # print(item.process_triangles())

    #     # print('\n---------------------------------\n')

    #     for key, value in item.mesh_data.field_data.items():

    #         line_keys = key.split('*')

    #         if len(line_keys) > 1:
    #             if line_keys[1] != 'None':

    #                 ply_string = key.split('*')[0]
    #                 ply_hash = key.split('*')[1]
    #                 print(ply_hash)

    #                 elm_type = ELM_TYPE[value[1]]
    #                 if elm_type == 'line':

    #                     for e in self.process_polygons:
    #                         for i, physical_line_id in enumerate(item.physical_lines):
    #                             if physical_line_id == value[0]:
    #                                 for n in self._triangles_containing_line(item, item.lines[i]):

    #                                     # item.g.node[n]['process_polygon'] = ply_string
    #                                     # # item.g.node[n]['display'] = RDD.DISPLAY.STYLE_SET[RDD.PLAYER.I5.VIA]
    #                                     # item.g.node[n]['display'] = RDD.DISPLAY.STYLE_SET[RDD.PLAYER.M1.HOLE]

    #                                     # shape = e.shape.transform_copy(e.transformation)
    #                                     print(e.shape.hash_string)
    #                                     if ply_hash == e.shape.hash_string:
    #                                         item.g.node[n]['process_polygon'] = e
    #                                         # FIXME: Change to equal the overlapping edge display.
    #                                         # item.g.node[n]['display'] = RDD.DISPLAY.STYLE_SET[RDD.PLAYER.I5.VIA]
    #                                         item.g.node[n]['display'] = RDD.DISPLAY.STYLE_SET[RDD.PLAYER.M1.HOLE]

    #                 print('')

    #     return [item]

    def __repr__(self):
        return "[SPiRA: NetLabelFilter] (layer count {})".format(0)
Esempio n. 12
0
class NetEdgeFilter(__NetFilter__):
    """  """

    process_polygons = ElementListParameter()

    def __filter___Net____(self, item):

        ELM_TYPE = {1: 'line', 2: 'triangle'}

        # print('Triangles:')
        # print(item.triangles)
        # print('Lines:')
        # print(item.lines)
        # print('Physical Lines:')
        # print(item.physical_lines)
        # print('Parameter Data:')
        # for k, v in item.mesh_data.field_data.items():
        #     print(k, v)

        # for e in self.process_polygons:
        #     item.g.node[3]['process_polygon'] = e
        #     item.g.node[3]['display'] = RDD.DISPLAY.STYLE_SET[e.layer]

        for key, value in item.mesh_data.field_data.items():

            # line_id = key.split('_')[0]
            # line_id = key[:-2]
            line_id = key[0]

            elm_type = ELM_TYPE[value[1]]
            if elm_type == 'line':

                for e in self.process_polygons:
                    pid = e.shape.hash_string

                    # if line_id == pid:
                    if line_id == '[':
                        for i, pl in enumerate(item.physical_lines):
                            if pl == value[0]:
                                for n in get_triangles_containing_line(
                                        item, item.lines[i]):
                                    item.g.node[n]['process_polygon'] = e
                                    # FIXME: Change to equal the overlapping edge display.
                                    # item.g.node[n]['display'] = RDD.DISPLAY.STYLE_SET[RDD.PLAYER.I5.VIA]
                                    item.g.node[n][
                                        'display'] = RDD.DISPLAY.STYLE_SET[
                                            RDD.PLAYER.M1.HOLE]

                                # line = item.lines[i]
                                # for n, triangle in enumerate(item.triangles):
                                #     if (line[0] in triangle) and (line[1] in triangle):
                                #         item.g.node[n]['process_polygon'] = e
                                #         item.g.node[n]['display'] = RDD.DISPLAY.STYLE_SET[e.layer]

                        # i = item.physical_lines.index(value[0])
                        # # i = item.physical_lines[value[0]]
                        # line = item.lines[i]
                        # for n, triangle in enumerate(item.triangles):
                        #     if (line[0] in triangle) and (line[1] in triangle):
                        #         item.g.node[n]['process_polygon'] = e
                        #         item.g.node[n]['display'] = RDD.DISPLAY.STYLE_SET[e.layer]

                        # triangles = item.process_triangles()
                        # for key, nodes in triangles.items():
                        #     for n in nodes:
                        #         if (line[0] in triangle) and (line[1] in triangle):
                        #         # if (n == line[0] or (n == line[1])):
                        #             print('YESSSSSSS')
                        #             # print(triangle)
                        #             print(n)

                        #             item.g.node[3]['process_polygon'] = e
                        #             item.g.node[3]['display'] = RDD.DISPLAY.STYLE_SET[e.layer]

        return [item]

    def __repr__(self):
        return "[SPiRA: NetLabelFilter] (layer count {})".format(0)
Esempio n. 13
0
class GmshGeometry(__Geometry__):
    """ Generate a geometry using the Gmsh library. """

    _ID = 0

    _uid = 0

    lcar = NumberParameter(default=100, doc='Mesh characteristic length.')
    algorithm = IntegerParameter(default=1, doc='Mesh algorithm used by Gmsh.')
    scale_Factor = NumberParameter(default=1e-6,
                                   doc='Mesh coord dimention scaling.')
    coherence_mesh = BoolParameter(defualt=True, doc='Merge similar points.')

    process = ProcessParameter()
    process_polygons = ElementListParameter()

    mesh_data = Parameter(fdef_name='create_mesh_data')

    def get_filename(self):
        if not hasattr(self, '__alias__'):
            self.__alias__ = '{}_{}'.format(self.process.symbol,
                                            GmshGeometry._uid)
            GmshGeometry._uid += 1
        return self.__alias__

    def set_filename(self, value):
        if value is not None:
            self.__alias__ = value

    filename = FunctionParameter(
        get_filename,
        set_filename,
        doc='Functions to generate an alias for cell name.')

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        self.geom = pygmsh.opencascade.Geometry(
            characteristic_length_min=self.lcar,
            characteristic_length_max=self.lcar)
        self.geom.add_raw_code('Mesh.Algorithm = {};'.format(self.algorithm))
        self.geom.add_raw_code('Mesh.ScalingFactor = {};'.format(
            self.scale_Factor))
        if self.coherence_mesh is True:
            self.geom.add_raw_code('Coherence Mesh;')

    def __physical_surfaces__(self):
        """ Creates physical surfaces that is compatible
        with the GMSH library for mesh generation. """
        import re

        surfaces = []
        for i, ply in enumerate(self.process_polygons):
            shape = ply.shape.transform_copy(ply.transformation)
            layer = RDD.GDSII.EXPORT_LAYER_MAP[ply.layer]
            pts = [[p[0], p[1], 0] for p in shape.points]
            surface_label = '{}_{}_{}_{}'.format(layer.number, layer.datatype,
                                                 GmshGeometry._ID, i)
            gp = self.geom.add_polygon(pts,
                                       lcar=self.lcar,
                                       make_surface=True,
                                       holes=None)

            for j, ll in enumerate(gp.lines):
                pid = ply.shape.segment_labels[j].split(' - hash ')
                if len(pid) > 1:
                    line_label = "{}*{}*{}".format(pid[0], pid[1], j)
                else:
                    line_label = "{}*{}*{}".format(pid[0], None, j)
                self.geom.add_physical(ll, label=line_label)
            self.geom.add_physical(gp.surface, label=surface_label)
            # surfaces.append([gp.surface, gp.line_loop])

            surfaces.append(gp)
            GmshGeometry._ID += 1
        return surfaces

    def create_mesh_data(self):
        """ Generates the mesh data from the created physical surfaces. """

        # if len(self.physical_surfaces) > 1:
        #     self.geom.boolean_union(self.physical_surfaces)

        self.__physical_surfaces__()

        directory = os.getcwd() + '/debug/gmsh/'

        mesh_file = '{}{}.msh'.format(directory, self.filename)
        geo_file = '{}{}.geo'.format(directory, self.filename)
        vtk_file = '{}{}.vtu'.format(directory, self.filename)

        if not os.path.exists(directory):
            os.makedirs(directory)

        mesh_data = pygmsh.generate_mesh(self.geom,
                                         verbose=False,
                                         dim=2,
                                         prune_vertices=False,
                                         remove_faces=False,
                                         geo_filename=geo_file)

        # meshio.write(mesh_file, mesh_data)
        # meshio.write(vtk_file, mesh_data)

        return mesh_data