Exemple #1
0
    def test_cif_options(self):

        opt = pya.LoadLayoutOptions()
        lm = pya.LayerMap()
        lm.map(pya.LayerInfo(1, 0), 2, pya.LayerInfo(42, 17))
        opt.cif_set_layer_map(lm, True)

        self.assertEqual(opt.cif_layer_map.to_string(), "1/0 : 42/17\n")
        self.assertEqual(opt.cif_create_other_layers, True)

        opt.cif_create_other_layers = False
        self.assertEqual(opt.cif_create_other_layers, False)

        opt.cif_select_all_layers()
        self.assertEqual(opt.cif_layer_map.to_string(), "")
        self.assertEqual(opt.cif_create_other_layers, True)

        opt.cif_keep_layer_names = True
        self.assertEqual(opt.cif_keep_layer_names, True)
        opt.cif_keep_layer_names = False
        self.assertEqual(opt.cif_keep_layer_names, False)

        opt.cif_wire_mode = 2
        self.assertEqual(opt.cif_wire_mode, 2)
        opt.cif_wire_mode = 4
        self.assertEqual(opt.cif_wire_mode, 4)

        opt.cif_dbu = 0.5
        self.assertEqual(opt.cif_dbu, 0.5)
Exemple #2
0
    def test_common_options(self):

        opt = pya.LoadLayoutOptions()
        lm = pya.LayerMap()
        lm.map(pya.LayerInfo(1, 0), 2, pya.LayerInfo(42, 17))
        opt.set_layer_map(lm, True)

        self.assertEqual(opt.layer_map.to_string(), "1/0 : 42/17\n")
        self.assertEqual(opt.create_other_layers, True)

        opt.create_other_layers = False
        self.assertEqual(opt.create_other_layers, False)

        opt.select_all_layers()
        self.assertEqual(opt.layer_map.to_string(), "")
        self.assertEqual(opt.create_other_layers, True)

        opt.text_enabled = True
        self.assertEqual(opt.text_enabled, True)
        opt.text_enabled = False
        self.assertEqual(opt.text_enabled, False)

        opt.properties_enabled = True
        self.assertEqual(opt.properties_enabled, True)
        opt.properties_enabled = False
        self.assertEqual(opt.properties_enabled, False)
Exemple #3
0
    def test_gds2_options(self):

        opt = pya.LoadLayoutOptions()
        lm = pya.LayerMap()
        lm.map(pya.LayerInfo(1, 0), 2, pya.LayerInfo(42, 17))
        opt.set_layer_map(lm, True)

        opt.gds2_allow_multi_xy_records = True
        self.assertEqual(opt.gds2_allow_multi_xy_records, True)
        opt.gds2_allow_multi_xy_records = False
        self.assertEqual(opt.gds2_allow_multi_xy_records, False)

        opt.gds2_resolve_skew_arrays = True
        self.assertEqual(opt.gds2_resolve_skew_arrays, True)
        opt.gds2_resolve_skew_arrays = False
        self.assertEqual(opt.gds2_resolve_skew_arrays, False)

        opt.gds2_allow_big_records = True
        self.assertEqual(opt.gds2_allow_big_records, True)
        opt.gds2_allow_big_records = False
        self.assertEqual(opt.gds2_allow_big_records, False)

        opt.gds2_box_mode = 1
        self.assertEqual(opt.gds2_box_mode, 1)
        opt.gds2_box_mode = 2
        self.assertEqual(opt.gds2_box_mode, 2)
Exemple #4
0
    def test_dxf_options(self):

        opt = pya.LoadLayoutOptions()
        lm = pya.LayerMap()
        lm.map(pya.LayerInfo(1, 0), 2, pya.LayerInfo(42, 17))
        opt.dxf_set_layer_map(lm, True)

        self.assertEqual(opt.dxf_layer_map.to_string(), "1/0 : 42/17\n")
        self.assertEqual(opt.dxf_create_other_layers, True)

        opt.dxf_create_other_layers = False
        self.assertEqual(opt.dxf_create_other_layers, False)

        opt.dxf_select_all_layers()
        self.assertEqual(opt.dxf_layer_map.to_string(), "")
        self.assertEqual(opt.dxf_create_other_layers, True)

        opt.dxf_dbu = 0.5
        self.assertEqual(opt.dxf_dbu, 0.5)

        opt.dxf_unit = 42
        self.assertEqual(opt.dxf_unit, 42)

        opt.dxf_text_scaling = 0.25
        self.assertEqual(opt.dxf_text_scaling, 0.25)

        opt.dxf_circle_points = 142
        self.assertEqual(opt.dxf_circle_points, 142)

        opt.dxf_circle_accuracy = 1.5
        self.assertEqual(opt.dxf_circle_accuracy, 1.5)

        opt.dxf_contour_accuracy = 0.75
        self.assertEqual(opt.dxf_contour_accuracy, 0.75)

        opt.dxf_render_texts_as_polygons = True
        self.assertEqual(opt.dxf_render_texts_as_polygons, True)
        opt.dxf_render_texts_as_polygons = False
        self.assertEqual(opt.dxf_render_texts_as_polygons, False)

        opt.dxf_keep_layer_names = True
        self.assertEqual(opt.dxf_keep_layer_names, True)
        opt.dxf_keep_layer_names = False
        self.assertEqual(opt.dxf_keep_layer_names, False)

        opt.dxf_keep_other_cells = True
        self.assertEqual(opt.dxf_keep_other_cells, True)
        opt.dxf_keep_other_cells = False
        self.assertEqual(opt.dxf_keep_other_cells, False)

        opt.dxf_polyline_mode = 2
        self.assertEqual(opt.dxf_polyline_mode, 2)
        opt.dxf_polyline_mode = 4
        self.assertEqual(opt.dxf_polyline_mode, 4)
Exemple #5
0
            def wrapper_pcell(self, layout, cell=None, params=None):
                global layer_map_dict
                try:
                    layer_map_dict[layout]
                except KeyError:
                    layer_map_dict[layout] = pya.LayerMap()
                if cell is None:
                    # copy source code of class and all its ancestors
                    source_code = "".join(
                        [inspect.getsource(klass) for klass in self.__class__.__mro__ if issubclass(klass, KLayoutPCell)])

                    # Default params before instantiation
                    original_default_params = {name: value["default"]
                                               for name, value in self.param_definition.items()}

                    # Updated params after instantiation and placement
                    # (could be bigger than the original default)
                    if params is not None:
                        default_params = dict(self.default_params, **params)
                    else:
                        default_params = self.default_params

                    # Differential parameters (non-default)
                    diff_params = {}
                    for name, value in original_default_params.items():
                        if default_params[name] != value:
                            diff_params[name] = default_params[name]

                    long_hash_pcell = sha256((source_code +
                                              str(diff_params) +
                                              self.name).encode()).hexdigest()
                    short_hash_pcell = long_hash_pcell[0:7]
                    cache_fname = f'cache_{self.__class__.__qualname__}_{short_hash_pcell}'
                    # if short_hash_pcell in cell_cache.keys():  # already loaded
                    #     print(f"Preloaded {self.__class__.__name__}: {diff_params}")
                    #     cached_cell, ports_bytecode, cellname = cell_cache[short_hash_pcell]
                    #     ports = pickle.loads(ports_bytecode)
                    #     # print('read:', cell_index, ports, cellname)
                    #     newcell = layout.create_cell(cellname)
                    #     newcell.copy_tree(cached_cell)
                    #     # newcell.insert(pya.DCellInstArray(cell.cell_index(),
                    #     #                                   pya.DTrans(pya.Trans.R0, pya.DPoint(0, 0))))
                    #     return newcell, deepcopy(ports)

                    def read_layout(layout, gds_filename):
                        global layer_map_dict
                        load_options = pya.LoadLayoutOptions()
                        load_options.text_enabled = True
                        load_options.set_layer_map(layer_map_dict[layout], True)

                        # store and take away the cell names of all cells read so far
                        # (by setting the cell name to "" the cells basically become invisible for
                        # the following read)
                        # take out the pcells
                        cell_list = [cell for cell in layout.each_cell()]
                        cell_indices = {cell.name: cell.cell_index() for cell in cell_list}
                        for i in cell_indices.values():
                            layout.rename_cell(i, "")

                        lmap = layout.read(gds_filename, load_options)
                        # in the new layout, get all cells names
                        cell_names2 = [(cell.cell_index(), cell.name)
                                       for cell in layout.each_cell()]

                        # make those cells point to older cells
                        prune_cells_indices = []
                        for i_duplicate, name_cached_cell in cell_names2:
                            if name_cached_cell in cell_indices.keys():
                                if name_cached_cell.startswith('cache_'):
                                    for parent_inst_array in layout.cell(i_duplicate).each_parent_inst():
                                        cell_instance = parent_inst_array.child_inst()
                                        cell_instance.cell = layout.cell(
                                            cell_indices[name_cached_cell])
                                    prune_cells_indices.append(i_duplicate)
                                else:
                                    # print('RENAME', name_cached_cell)
                                    k = 1
                                    while (name_cached_cell + f"_{k}") in cell_indices.keys():
                                        k += 1
                                    layout.rename_cell(i_duplicate, name_cached_cell + f"_{k}")

                        for i_pruned in prune_cells_indices:
                            # print('deleting cell', layout.cell(i_pruned).name)
                            layout.prune_cell(i_pruned, -1)

                        # every conflict should have been caught above
                        for name, i in cell_indices.items():
                            layout.rename_cell(i, name)

                        layer_map_dict[layout] = lmap
                        return lmap

                    cache_fname_gds = cache_fname + '.gds'
                    cache_fname_pkl = cache_fname + '.klayout.pkl'

                    os.makedirs(cache_dir, mode=0o775, exist_ok=True)

                    cache_fpath_gds = os.path.join(cache_dir, cache_fname_gds)
                    cache_fpath_pkl = os.path.join(cache_dir, cache_fname_pkl)
                    if os.path.isfile(cache_fpath_gds) and os.path.isfile(cache_fpath_pkl):
                        with open(cache_fpath_pkl, 'rb') as file:
                            ports, read_short_hash_pcell, cellname = pickle.load(file)
                        if debug:
                            print(f"Reading from cache: {cache_fname}: {diff_params}, {cellname}")
                        else:
                            print('r', end='', flush=True)
                        if not layout.has_cell(cache_fname):
                            read_layout(layout, cache_fpath_gds)
                        retrieved_cell = layout.cell(cache_fname)
                        cell = layout.create_cell(cellname)
                        cell.insert(pya.DCellInstArray(retrieved_cell.cell_index(),
                                                       pya.DTrans(pya.Trans.R0, pya.DPoint(0, 0))))
                        # cell.move_tree(retrieved_cell)
                    else:
                        if layout.has_cell(cache_fname):
                            print(f"WARNING: {cache_fname_gds} does not exist but {cache_fname} is in layout.")

                        # populating .gds and .pkl
                        empty_layout = pya.Layout()
                        compiled_cell, ports = pcell(
                            self, empty_layout, cell=None, params=params)
                        if debug:
                            print(f"Writing to cache: {cache_fname}: {diff_params}, {compiled_cell.name}")
                        else:
                            print('w', end='', flush=True)
                        cellname, compiled_cell.name = compiled_cell.name, cache_fname
                        compiled_cell.write(cache_fpath_gds)
                        with open(cache_fpath_pkl, 'wb') as file:
                            pickle.dump((ports, short_hash_pcell, cellname), file)
                        read_layout(layout, cache_fpath_gds)

                        retrieved_cell = layout.cell(cache_fname)
                        cell = layout.create_cell(cellname)
                        cell.insert(pya.DCellInstArray(retrieved_cell.cell_index(),
                                                       pya.DTrans(pya.Trans.R0, pya.DPoint(0, 0))))

                else:
                    cell, ports = pcell(self, layout, cell=cell, params=params)
                return cell, ports