diff --git a/klayout_dot_config/python/SiEPIC/scripts.py b/klayout_dot_config/python/SiEPIC/scripts.py index a30a1c0a..32ffb8da 100644 --- a/klayout_dot_config/python/SiEPIC/scripts.py +++ b/klayout_dot_config/python/SiEPIC/scripts.py @@ -3075,6 +3075,48 @@ def button(self): wdg.show() +def check_bb_geometries(topcell, BB_layerinfo=pya.LayerInfo(998,0), verbose=True): + ''' + Check if there are any Black Box layers in the layout. + Returns: + Count: number of different shapes + Args: + topcell: pya.Cell + BB_layerinfo: pya.LayerInfo + ''' + layout = topcell.layout() + layer_bb = layout.layer(BB_layerinfo) # hard coded for the GSiP PDK + r1 = pya.Region(topcell.begin_shapes_rec(layer_bb)) + diff_count = 0 + if not r1.is_empty(): + diff_count = r1.size() + if verbose: + print( + f" - SiEPIC.scripts.check_bb_geometries: {r1.size()} Black Box geometry(ies) found in {topcell.name} on layer {layout.get_info(layer_bb)}." + ) + else: + if verbose: + print('Black box replacement -- success -- no black box layers remaining.') + return diff_count + +def cells_containing_bb_layers(topcell, BB_layerinfo=pya.LayerInfo(998,0), verbose=True): + ''' + return a list of cell names that contain black box polygons + Args: + topcell: pya.Cell + BB_layerinfo: pya.LayerInfo + ''' + layout = topcell.layout() + iter1 = pya.RecursiveShapeIterator(layout, topcell, layout.layer(BB_layerinfo) ) + cells = [] + while not iter1.at_end(): + cells.append (iter1.cell().name) + if verbose: + print(" - %s" % iter1.cell().name) + iter1.next() + # return unique cell names + return sorted(list(set(cells))) + def layout_diff(cell1, cell2, tol = 1, verbose=True): ''' Check two cells to make sure they are identical, within a tolerance. @@ -3135,7 +3177,7 @@ def layout_diff(cell1, cell2, tol = 1, verbose=True): return diff_count -def replace_cell(layout, cell_x_name = None, cell_y_name=None, cell_y_file=None, cell_y_library=None, cell_ref_bb = None, Exact = True, RequiredCharacter = '$', run_layout_diff = True, debug = False): +def replace_cell(layout, cell_x_name = None, cell_y_name=None, cell_y_file=None, cell_y_library=None, cell_ref_bb = None, Exact = True, RequiredCharacter = '$', run_layout_diff = False, debug = False): ''' SiEPIC-Tools: scripts.replace_cell Search and replace: cell_x with cell_y @@ -3158,6 +3200,13 @@ def replace_cell(layout, cell_x_name = None, cell_y_name=None, cell_y_file=None, Basename, Basename* NO: Basename_extension Basename, Basename* YES: DifferentName ''' + + # Find the cell name from the cell_ref_bb + if not cell_x_name: + if cell_ref_bb: + cell_x_name = cell_ref_bb.name + else: + raise Exception ('missing replacement cell name') import os if debug: @@ -3179,7 +3228,10 @@ def replace_cell(layout, cell_x_name = None, cell_y_name=None, cell_y_file=None, # Find the cells that need replacement (cell_x) # find cell name exactly matching cell_x_name - cells_x = [layout.cell(cell_x_name)] + if layout.cell(cell_x_name): + cells_x = [layout.cell(cell_x_name)] + else: + cells_x = [] if not Exact: # replacement for all cells that: # 1) cell name exact matching cell_x_name, OR diff --git a/klayout_dot_config/python/SiEPIC/tests/test_replace_cell/test_scripts_replace_cell.py b/klayout_dot_config/python/SiEPIC/tests/test_replace_cell/test_scripts_replace_cell.py index b5343aa4..bd857da3 100644 --- a/klayout_dot_config/python/SiEPIC/tests/test_replace_cell/test_scripts_replace_cell.py +++ b/klayout_dot_config/python/SiEPIC/tests/test_replace_cell/test_scripts_replace_cell.py @@ -5,9 +5,9 @@ """ -def test_replace_cell(): +def test_replace_cell(show_klive=False): ''' - + show_klive: True to open the layout in KLayout using KLive ''' import pya @@ -29,7 +29,7 @@ def test_replace_cell(): raise Exception("Errors", "This example requires SiEPIC-Tools version 0.5.4 or greater.") - from SiEPIC.scripts import replace_cell, delete_extra_topcells + from SiEPIC.scripts import replace_cell, delete_extra_topcells, cells_containing_bb_layers, check_bb_geometries # The circuit layout that contains BB cells path = os.path.dirname(os.path.realpath(__file__)) @@ -51,20 +51,6 @@ def test_replace_cell(): ly_wb.read(file_wb) cell_wb = ly_wb.top_cell() ''' - def check_bb_geometries(layout): - ''' - check if there are any Black Box layers in the layout - ''' - layer_bb = layout.layer(pya.LayerInfo(998,0)) # hard coded for the GSiP PDK - r1 = pya.Region(top_cell.begin_shapes_rec(layer_bb)) - diff_count = 0 - if not r1.is_empty(): - diff_count = r1.size() - print( - f" - SiEPIC.scripts.layout_diff: {r1.size()} Black Box geometry(ies) found in {top_cell.name} on layer {layout.get_info(layer_bb)}." - ) - return diff_count - # Check -- exact replacement (without $) if 1: @@ -77,18 +63,17 @@ def check_bb_geometries(layout): ) print('replaced %s' %count) assert count == 1 - assert check_bb_geometries(layout) == 1 + assert check_bb_geometries(top_cell) == 1 + assert cells_containing_bb_layers(top_cell) == ['ebeam_y_adiabatic_500pin$1'] file_out = os.path.join(path,'example_replaced.gds') delete_extra_topcells(layout, top_cell.name) layout.write(file_out) - try: + if show_klive: # Display the layout in KLayout, using KLayout Package "klive", which needs to be installed in the KLayout Application if Python_Env == 'Script': from SiEPIC.utils import klive klive.show(file_out, technology='EBeam') - except: - pass os.remove(file_out) @@ -106,18 +91,17 @@ def check_bb_geometries(layout): ) print('replaced %s' %count) assert count == 2 - assert check_bb_geometries(layout) == 0 + assert check_bb_geometries(top_cell) == 0 + assert cells_containing_bb_layers(top_cell) == [] file_out = os.path.join(path,'example_replaced2.gds') delete_extra_topcells(layout, top_cell.name) layout.write(file_out) - try: + if show_klive: # Display the layout in KLayout, using KLayout Package "klive", which needs to be installed in the KLayout Application if Python_Env == 'Script': from SiEPIC.utils import klive klive.show(file_out, technology='EBeam') - except: - pass os.remove(file_out) # Check -- Run BB reference vs. design layout difference, non-exact replacement (with $) @@ -134,8 +118,9 @@ def check_bb_geometries(layout): ) print('replaced %s' %count) assert count == 2 - assert check_bb_geometries(layout) == 0 + assert check_bb_geometries(top_cell) == 0 assert error == False + assert cells_containing_bb_layers(top_cell) == [] # Check -- Run BB reference (changed) vs. design layout difference, non-exact replacement (with $) if 1: @@ -157,4 +142,4 @@ def check_bb_geometries(layout): assert error == True if __name__ == "__main__": - test_replace_cell() + test_replace_cell(show_klive=True) diff --git a/klayout_dot_config/tech/GSiP/pymacros/tests/test_FaML.py b/klayout_dot_config/tech/GSiP/pymacros/tests/test_FaML.py index addeaeb6..ee34005c 100644 --- a/klayout_dot_config/tech/GSiP/pymacros/tests/test_FaML.py +++ b/klayout_dot_config/tech/GSiP/pymacros/tests/test_FaML.py @@ -5,7 +5,7 @@ """ -def test_FaML_two(): +def test_FaML_two(show_klive=False): ''' --- Simple MZI, tested using Facet-Attached Micro Lenses (FaML) --- @@ -102,13 +102,14 @@ def test_FaML_two(): print('Number of errors: %s' % num_errors) # Display the layout in KLayout, using KLayout Package "klive", which needs to be installed in the KLayout Application - if Python_Env == 'Script': - from SiEPIC.utils import klive - klive.show(file_out, lyrdb_filename=file_lyrdb, technology=tech_name) + if show_klive: + if Python_Env == 'Script': + from SiEPIC.utils import klive + klive.show(file_out, lyrdb_filename=file_lyrdb, technology=tech_name) os.remove(file_out) if num_errors > 0: raise Exception ('Errors found in test_FaML_two') if __name__ == "__main__": - test_FaML_two() + test_FaML_two(show_klive=True) diff --git a/klayout_dot_config/tech/GSiP/pymacros/tests/test_SiEPIC_utils.py b/klayout_dot_config/tech/GSiP/pymacros/tests/test_SiEPIC_utils.py index 7a78c9c6..9d3a3976 100644 --- a/klayout_dot_config/tech/GSiP/pymacros/tests/test_SiEPIC_utils.py +++ b/klayout_dot_config/tech/GSiP/pymacros/tests/test_SiEPIC_utils.py @@ -82,7 +82,7 @@ def test_create_cell2(): topcell.insert(CellInstArray(cell_y.cell_index(), t)) -def test_waveguide_length(): +def test_waveguide_length(show_klive=False): import pya import SiEPIC from SiEPIC._globals import Python_Env @@ -124,9 +124,10 @@ def test_waveguide_length(): # Display in KLayout from SiEPIC._globals import Python_Env - if Python_Env == 'Script': - from SiEPIC.utils import klive - klive.show(file_out, technology=tech_name, keep_position=True) + if show_klive: + if Python_Env == 'Script': + from SiEPIC.utils import klive + klive.show(file_out, technology=tech_name, keep_position=True) os.remove(file_out) @@ -137,4 +138,4 @@ def test_waveguide_length(): if __name__ == "__main__": test_load_layout() test_create_cell2() - test_waveguide_length() \ No newline at end of file + test_waveguide_length(show_klive=True) \ No newline at end of file diff --git a/klayout_dot_config/tech/GSiP/pymacros/tests/test_bezier.py b/klayout_dot_config/tech/GSiP/pymacros/tests/test_bezier.py index e40d3477..d291823f 100644 --- a/klayout_dot_config/tech/GSiP/pymacros/tests/test_bezier.py +++ b/klayout_dot_config/tech/GSiP/pymacros/tests/test_bezier.py @@ -15,7 +15,7 @@ from pya import * -def test_bezier_bends(): +def test_bezier_bends(show_klive=False): designer_name = 'Test_Bezier_bend' top_cell_name = 'GSiP_%s' % designer_name @@ -124,15 +124,16 @@ def test_bezier_bends(): # Display in KLayout from SiEPIC._globals import Python_Env - if Python_Env == 'Script': - from SiEPIC.utils import klive - klive.show(file_out, technology=tech_name, keep_position=True) + if show_klive: + if Python_Env == 'Script': + from SiEPIC.utils import klive + klive.show(file_out, technology=tech_name, keep_position=True) os.remove(file_out) # Plot # cell.plot() # in the browser -def test_bezier_tapers(): +def test_bezier_tapers(show_klive=False): designer_name = 'Test_Bezier_tapers' top_cell_name = 'GSiP_%s' % designer_name @@ -220,9 +221,10 @@ def test_bezier_tapers(): # Display in KLayout from SiEPIC._globals import Python_Env - if Python_Env == 'Script': - from SiEPIC.utils import klive - klive.show(file_out, technology=tech_name, keep_position=True) + if show_klive: + if Python_Env == 'Script': + from SiEPIC.utils import klive + klive.show(file_out, technology=tech_name, keep_position=True) os.remove(file_out) # Plot @@ -231,5 +233,5 @@ def test_bezier_tapers(): if __name__ == "__main__": # test_bezier_bends() - test_bezier_tapers() + test_bezier_tapers(show_klive=True) diff --git a/klayout_dot_config/tech/GSiP/pymacros/tests/test_coupler_array.py b/klayout_dot_config/tech/GSiP/pymacros/tests/test_coupler_array.py index c81cd686..67632109 100644 --- a/klayout_dot_config/tech/GSiP/pymacros/tests/test_coupler_array.py +++ b/klayout_dot_config/tech/GSiP/pymacros/tests/test_coupler_array.py @@ -5,7 +5,7 @@ """ -def test_coupler_array(): +def test_coupler_array(show_klive=False): ''' --- Simple MZI, tested using Facet-Attached Micro Lenses (FaML) --- @@ -101,13 +101,14 @@ def test_coupler_array(): print('Number of errors: %s' % num_errors) # Display the layout in KLayout, using KLayout Package "klive", which needs to be installed in the KLayout Application - if Python_Env == 'Script': - from SiEPIC.utils import klive - klive.show(file_out, lyrdb_filename=file_lyrdb, technology=tech_name) + if show_klive: + if Python_Env == 'Script': + from SiEPIC.utils import klive + klive.show(file_out, lyrdb_filename=file_lyrdb, technology=tech_name) os.remove(file_out) if num_errors > 0: raise Exception ('Errors found in test_coupler_array') if __name__ == "__main__": - test_coupler_array() + test_coupler_array(show_klive=True) diff --git a/klayout_dot_config/tech/GSiP/pymacros/tests/test_example_circuit.py b/klayout_dot_config/tech/GSiP/pymacros/tests/test_example_circuit.py index 29829dee..40a7b3da 100644 --- a/klayout_dot_config/tech/GSiP/pymacros/tests/test_example_circuit.py +++ b/klayout_dot_config/tech/GSiP/pymacros/tests/test_example_circuit.py @@ -16,7 +16,7 @@ from pya import * -def example_circuit(): +def example_circuit(show_klive=False): designer_name = 'Test' top_cell_name = 'GSiP_%s' % designer_name @@ -122,9 +122,10 @@ def example_circuit(): # Display in KLayout from SiEPIC._globals import Python_Env - if Python_Env == 'Script': - from SiEPIC.utils import klive - klive.show(file_out, technology=tech_name, keep_position=True) + if show_klive: + if Python_Env == 'Script': + from SiEPIC.utils import klive + klive.show(file_out, technology=tech_name, keep_position=True) os.remove(file_out) # Plot @@ -143,5 +144,5 @@ def test_example_circuit(): assert example_circuit() == 0 if __name__ == "__main__": - example_circuit() + example_circuit(show_klive=True) diff --git a/klayout_dot_config/tech/GSiP/pymacros/tests/test_instantiate_all_cells.py b/klayout_dot_config/tech/GSiP/pymacros/tests/test_instantiate_all_cells.py index 76aaaf9a..9a731717 100644 --- a/klayout_dot_config/tech/GSiP/pymacros/tests/test_instantiate_all_cells.py +++ b/klayout_dot_config/tech/GSiP/pymacros/tests/test_instantiate_all_cells.py @@ -10,7 +10,7 @@ from pya import * -def test_all_library_cells(): +def test_all_library_cells(show_klive=False): designer_name = 'Test' top_cell_name = 'GSiP_%s' % designer_name @@ -54,7 +54,8 @@ def test_all_library_cells(): if c.is_empty() or c.bbox().area() == 0: raise Exception('Empty cell: %s' % c.name) - topcell.show() + if show_klive: + topcell.show() # Verify num_errors = layout_check(cell=topcell, verify_DFT=False, verbose=False, GUI=True) @@ -64,4 +65,4 @@ def test_all_library_cells(): if __name__ == "__main__": - test_all_library_cells() + test_all_library_cells(show_klive=True)