Skip to content

Commit

Permalink
simply loading PDK libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasc-ubc committed Oct 19, 2024
1 parent 055eb7f commit 224b115
Show file tree
Hide file tree
Showing 8 changed files with 290 additions and 138 deletions.
167 changes: 167 additions & 0 deletions klayout_dot_config/python/SiEPIC/scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#################################################################################
'''
Functions in this file:
connect_pins_with_waveguide
path_to_waveguide
path_to_waveguide2
Expand Down Expand Up @@ -34,6 +36,8 @@
zoom_out: When running in the GUI, Zoom out and show full hierarchy
export_layout
instantiate_all_library_cells
load_klayout_library
technology_libraries
'''

Expand Down Expand Up @@ -3410,3 +3414,166 @@ def instantiate_all_library_cells(topcell, terminator_cells = None, terminator_l
if True or Python_Env == "KLayout_GUI":
p.destroy

def load_klayout_library(technology, library_name=None, library_description='', folder_gds=None, folder_pcell=None, verbose=True):
'''
Load KLayout Library
Loads PCells and fixed cells from sub folders,
creates a KLayout pya.Library,
registers the library with the technology name.
Inputs:
technology: name of the technology, e.g., "EBeam", or pya.Technology
library_name: name of the library
library_description: description of the library
folder_gds: relative sub-folder (within the technology folder) from which to load .gds/.oas fixed cells
folder_pcell: relative sub-folder (within the technology folder) from which to load .py PCells
returns:
pya.Library name
'''

if type(technology) == str:
tech = pya.Technology.technology_by_name(technology)
if not tech:
raise Exception('SiEPIC.load_klayout_library cannot load technology: %s' % technology)
tech_name = technology
elif type(technology) == pya.Technology:
tech = technology
if not tech:
raise Exception('SiEPIC.load_klayout_library cannot load technology: %s' % technology)
tech_name = technology.name
else:
raise Exception('SiEPIC.load_klayout_library requires a technology as input.')

if not library_name:
library_name = tech_name

import os
import pathlib
import sys

if verbose:
print(' - Technology path: %s' % tech.default_base_path)
print(' - PCell folder path: %s' % os.path.join(tech.default_base_path, folder_pcell))

import importlib.util
import sys

def import_module_from_path(module_name, file_path):
'''
import a Python module given a path
'''
import importlib.util
import sys
from pathlib import Path

file_path = os.path.join(file_path, '__init__.py')
path = Path(file_path).resolve()
if verbose:
print(' - PCell init file: %s' % path)
spec = importlib.util.spec_from_file_location(module_name, path)
if not spec:
raise Exception('SiEPIC.load_klayout_library cannot import module: %s, from path: %s ' % (module_name,path))
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module # Add it to sys.modules
spec.loader.exec_module(module) # Execute the module code

return module

# Load all Python PCells
if folder_pcell:
import importlib
importlib.invalidate_caches()

# Import the Python folder as a module
folder_pcell_abs = os.path.join(tech.default_base_path, folder_pcell)
module_name = os.path.split(folder_pcell)[-1]
if verbose:
print(' - PCell module name: %s' % module_name)
module = import_module_from_path(module_name, folder_pcell_abs)
globals()[module_name] = module

# Import all the PCell python files
pcells_=[]
files = [f for f in os.listdir(folder_pcell_abs) if '.py' in pathlib.Path(f).suffixes and '__init__' not in f]
for f in files:
submodule = '%s.%s' % (module_name, f.replace('.py',''))
# m = importlib.import_module(submodule)
m = importlib.import_module('.'+f.replace('.py',''), package=module_name)
if not m:
raise Exception('SiEPIC.load_klayout_library cannot import module: %s, from path: %s ' % (submodule,folder_pcell_abs))
if verbose:
print(' - imported PCell: %s' % submodule)
pcells_.append(importlib.reload(m))
if verbose:
print(' - module dir(): %s' % dir(module))

if not type(module) == type(os):
raise Exception('SiEPIC.load_klayout_library cannot import module.')

# Create the KLayout library, using GDS and Python PCells
class library(pya.Library):
def __init__(self):
self.technology=tech_name
if verbose:
print(" - Initializing '%s' Library." % library_name)

# Set the description
self.description = library_description

self.register(library_name)

# Save the path, used for loading WAVEGUIDES.XML
# import os
# self.path = os.path.dirname(os.path.realpath(__file__))

# Import all the GDS files from the tech folder
# GDS files
import os, fnmatch
dir_path = os.path.join(tech.default_base_path, folder_gds)
if verbose:
print(' - GDS/OAS folder path: %s' % dir_path)
search_strs = ['*.[Oo][Aa][Ss]', '*.[Gg][Dd][Ss]'] # OAS, GDS
for search_str in search_strs:
for root, dirnames, filenames in os.walk(dir_path, followlinks=True):
for filename in fnmatch.filter(filenames, search_str):
file1=os.path.join(root, filename)
if verbose:
print(" - reading %s" % filename )
self.layout().read(file1)

# Create the PCell declarations
for m in pcells_:
mm = m.__name__.replace('%s.' % module_name,'')
# mm2 = m.__name__+'.'+mm+'()'
mm2 = 'module'+'.'+mm+'.'+mm+'()'
if verbose:
print(' - register_pcell %s, %s' % (mm,mm2))
# self.layout().register_pcell(mm, eval(mm2))
self.layout().register_pcell(mm, getattr(m,mm)())

if verbose:
print(' - done loading pcells')

# Register us the library with the technology name
# If a library with that name already existed, it will be replaced then.
self.register(library_name)

library()

return library_name

def technology_libraries(tech):
'''
Function to get a list of all the pya.Library associated with a pya.Technology
missing in KLayout: https://github.com/KLayout/klayout/issues/879
https://www.klayout.de/doc-qt5/code/class_Technology.html
'''
import pya
tech_libs = []
libs = pya.Library.library_ids()
for lib in libs:
l = pya.Library.library_by_id(lib)
if tech in l.technologies():
tech_libs.append(l.name())
#print("%s" % (l.name()))
print('Libraries associated with Technology %s: %s' % (tech, tech_libs))

2 changes: 1 addition & 1 deletion klayout_dot_config/tech/GSiP/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
print('SiEPIC-GSiP PDK Python module: siepic_gsip_pdk, KLayout technology: GSipP')
print('SiEPIC-GSiP PDK Python module: siepic_gsip_pdk, KLayout technology: GSiP')

# Load the KLayout technology, when running in Script mode
import pya, os
Expand Down
131 changes: 0 additions & 131 deletions klayout_dot_config/tech/GSiP/pymacros/GSiP_Library.py

This file was deleted.

47 changes: 45 additions & 2 deletions klayout_dot_config/tech/GSiP/pymacros/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,51 @@
print('SiEPIC-GSiP PDK Python module: pymacros')
# $autorun
"""
This file is part of the SiEPIC-Tools and SiEPIC-GSiP PDK
by Lukas Chrostowski (c) 2015-2017
from . import GSiP_Library
This Python file implements a library called "GSiP" for scripted and GUI-based layout flows.
Crash warning:
https://www.klayout.de/forum/comments.php?DiscussionID=734&page=1#Item_13
This library has nested PCells. Running this macro with a layout open may
cause it to crash. Close the layout first before running.
Version history:
Mustafa Hammood 2020/6/25
- Refactored PCells out of library files into individual files in a subdirectory
Jaspreet Jhoja 2020/5/23
- Refactored PCells to make them compatible with both, GUI and script-based layout operations
Stefan Preble and Karl McNulty (RIT) 2019/6/13
- Wireguide : Path to metal wires
Lukas Chrostowski 2017/12/16
- compatibility with KLayout 0.25 and SiEPIC-Tools
Lukas Chrostowski
- GDS cells (detector, etc) and PCells (ring modulator, filter)
Lukas 2023/11
- compatibility with PyPI usage of KLayout
Lukas 2024/10
- moving all the library loading code into SiEPIC.scripts.load_klayout_library
"""

print('SiEPIC-GSiP PDK Python module: load library GDS/OAS cells and PCells')

verbose = False

tech = 'GSiP'

from SiEPIC.scripts import load_klayout_library , technology_libraries

# Load the library
load_klayout_library(tech, tech, 'SiEPIC Generic SiP, v1.1', 'gds/building_blocks','pymacros/pcells_GSiP', verbose=verbose)

# List the libraries loaded
technology_libraries(tech)

Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
<prolog/>
<epilog/>
<doc/>
<autorun>true</autorun>
<autorun>false</autorun>
<autorun-early>false</autorun-early>
<priority>0</priority>
<shortcut/>
<show-in-menu>false</show-in-menu>
<group-name/>
Expand Down
Loading

0 comments on commit 224b115

Please sign in to comment.