Skip to content

Commit

Permalink
Merge branch 'load_klayout_library'
Browse files Browse the repository at this point in the history
  • Loading branch information
lukasc-ubc committed Oct 19, 2024
2 parents 25f3a59 + b7c4e42 commit 16c3cbd
Show file tree
Hide file tree
Showing 13 changed files with 360 additions and 142 deletions.
43 changes: 43 additions & 0 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

name: Upload Python Package

on:
release:
types: [published]

permissions:
contents: read

jobs:
deploy:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: |
# python -m build
cd klayout_dot_config/python
python3 -m build
cp -a dist ../..
- name: Publish package
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
2 changes: 1 addition & 1 deletion .github/workflows/run-layout-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
# python -m pip install --upgrade pip
pip install klayout numpy scipy pytest pytest-cov IPython
pip install -e klayout_dot_config/python
- name: Test with pytest, python 3.11
run: pytest --cov=klayout_dot_config/python/SiEPIC klayout_dot_config/tech --cov-report=xml

Expand Down
2 changes: 1 addition & 1 deletion klayout_dot_config/grain.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<salt-grain>
<name>siepic_tools</name>
<version>0.5.13</version>
<version>0.5.14</version>
<api-version>0.27</api-version>
<title>SiEPIC Tools</title>
<doc>Tools for designing Silicon Photonic Integrated Circuits, including waveguides, component simulations, functional verification, DRC verification, Functional verification, netlist extraction, circuit simulations. Layout can be implemented graphically or by programming in Python using the SiEPIC functions and KLayout Python API. Framework and examples for creating layouts using scripts. Includes a generic PDK (GSiP). Other PDKs are installed separately, and depend on SiEPIC-Tools.</doc>
Expand Down
2 changes: 1 addition & 1 deletion klayout_dot_config/python/SiEPIC/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
SiEPIC-Tools package for KLayout
'''

__version__ = "0.5.13"
__version__ = "0.5.14"

print("KLayout SiEPIC-Tools version %s" %__version__)

Expand Down
190 changes: 190 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,189 @@ 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.abspath(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/OASIS files from the tech folder
if folder_gds:
import os, fnmatch
dir_path = os.path.abspath(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
found = False
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)
found = True
if not found:
print(' - Warning: no fixed GDS/OAS files found for library: %s, in folder: %s' % (library_name, dir_path))


# Create the PCell declarations
if folder_pcell:
if not pcells_:
print(' - Warning: no PCells found for library: %s' % library_name)
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(technology):
'''
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
Inputs:
technology: name of the technology, e.g., "EBeam", or pya.Technology
'''

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.')

tech_libs = []
libs = pya.Library.library_ids()
for lib in libs:
l = pya.Library.library_by_id(lib)
if tech_name in l.technologies():
tech_libs.append(l.name())

print('Libraries associated with Technology %s: %s' % (tech_name, tech_libs))

2 changes: 1 addition & 1 deletion klayout_dot_config/python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "SiEPIC"
version = "0.5.13"
version = "0.5.14"
authors = [
{ name="Lukas Chrostowski", email="[email protected]" },
]
Expand Down
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
Loading

0 comments on commit 16c3cbd

Please sign in to comment.