Skip to content

Commit

Permalink
Merge pull request #196 from jasminabrar/master
Browse files Browse the repository at this point in the history
Added automated docker build process and a sample 'disabled' GitHub action
  • Loading branch information
lukasc-ubc authored Nov 23, 2023
2 parents 4de7172 + 5fa9617 commit cc9633b
Show file tree
Hide file tree
Showing 7 changed files with 373 additions and 2 deletions.
69 changes: 69 additions & 0 deletions .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Create and Publish Docker image

on:
push:
branches: [ "master" ]
paths:
- 'Dockerfile'
pull_request:
types:
- closed
branches: [ "master" ]
paths:
- 'Dockerfile'

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}/klayout

jobs:
build-and-push-image:

runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Check pull request was merged
if: github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == false
run: |
echo "Error: Pull request is not merged."
exit 1
- name: Checkout repository
uses: actions/checkout@v4

- name: Get the current date
id: date
run: echo "::set-output name=date::$(date +%Y%m%d)"

- name: Log in to the container registry
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

- name: Build and push Docker image as latest image
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}-latest
labels: ${{ steps.meta.outputs.labels }}

- name: Build and push Docker image as unique image
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
with:
context: .
push: true
tags: "${{ steps.meta.outputs.tags }}.${{ steps.date.outputs.date }}.${{ github.run_number }}"
labels: ${{ steps.meta.outputs.labels }}

54 changes: 54 additions & 0 deletions .github/workflows/sample.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Sample Github Action that sets up docker container using image in this repo

name: Sample Github Action

# Specify this github action to run on (i) a push to master or any branch, and (ii) a pull request to master
# Note: Since this is a sample action we don't want it to run. We cannot leave this empty and have put
# a placeholder to ensure it doesn't run. Delete the current code and uncomment the commented code when you
# want this action to run.
on:
#push:
#branches:
#- '**'
#pull_request:
#branches:
#- master
push:
branches:
- v0.1.4

jobs:
ebeam-lib-pcell-test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Pull klayout image
run: docker pull ghcr.io/jasminabrar/siepic-tools/klayout:master-latest

- name: Run docker container from image
run: docker run -itd --name sample --security-opt label=type:container_runtime_t ghcr.io/jasminabrar/siepic-tools/klayout:master-latest

# input code to run tests in klayout docker container

# e.g
# - name: Copy pymacros folder to docker container (needed to run EBeam_Lib_PCellTests.py)
# run: docker cp $GITHUB_WORKSPACE/klayout/EBeam/pymacros ebeam_test:/home/pymacros
# - name: Run EBeam Library Pcell Test Script
# run: docker exec -e DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix sample klayout -zz -r pymacros/EBeam_Lib_PCellTests.py || echo "KLAYOUT_EXIT_CODE=$?" >> $GITHUB_ENV
# continue-on-error: true
# -> IMPORTANT COMMAND: needed so rest of github action runs if an error occurs when running the script

- name: Stop container and remove it
run: |
docker stop sample
docker rm sample
- name: Fail job if exit code is non-zero
run: |
if [ $KLAYOUT_EXIT_CODE -ne 0 ]; then
echo "KLayout exited with non-zero exit code"
exit 1
fi
17 changes: 17 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
FROM quay.io/centos/centos:stream8

# Update the system and install necessary tools.
RUN dnf -y update && \
dnf -y install wget bzip2 unzip git mesa-dri-drivers

# Install the newest version of KLayout
RUN wget https://www.klayout.org/downloads/CentOS_8/klayout-0.28.12-0.x86_64.rpm -O ~/klayout.rpm && \
dnf -y localinstall ~/klayout.rpm && \
rm ~/klayout.rpm

# Set the working directory
WORKDIR /home

# Set PATH
ENV PATH="/usr/local/bin:${PATH}"
ENV QT_QPA_PLATFORM=minimal
1 change: 0 additions & 1 deletion klayout_dot_config/python/SiEPIC/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1508,4 +1508,3 @@ def pointlist_to_path(pointlist, dbu):
return path



2 changes: 1 addition & 1 deletion klayout_dot_config/python/SiEPIC/utils/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,4 +232,4 @@ def cell_to_component(cell, ports = ['L','R'], verbose=False):

connect_pins_with_waveguide(inst, 'opt1', inst, 'opt3', waveguide_type=waveguide_type, turtle_A = [10, 90, 10, 90], turtle_B = [10, -90, 10, -90])
connect_pins_with_waveguide(inst, 'opt2', inst, 'opt4', waveguide_type=waveguide_type, turtle_B = [10, 90, 10, 90], turtle_A = [10, -90, 10, -90])


1 change: 1 addition & 0 deletions klayout_dot_config/python/SiEPIC/utils/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -1283,3 +1283,4 @@ def new_layout(tech, topcell_name, GUI=True, overwrite = False):
ly.TECHNOLOGY = get_technology_by_name(tech)

return topcell, ly

231 changes: 231 additions & 0 deletions pcell_python_GDSfactory.lym
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
<?xml version="1.0" encoding="utf-8"?>
<klayout-macro>
<description/>
<version/>
<category>pymacros</category>
<prolog/>
<epilog/>
<doc/>
<autorun>true</autorun>
<autorun-early>false</autorun-early>
<priority>0</priority>
<shortcut/>
<show-in-menu>false</show-in-menu>
<group-name/>
<menu-path/>
<interpreter>python</interpreter>
<dsl-interpreter-name/>
<text>
'''
PCell created using geometries from GDSfactory
by: Lukas Chrostowski, 2023

- query the GDSfactory PCell to find out the parameters and defaults
use those to populate the GUI
- pass on the KLayout parameters to GDSfactory
- generates the GDSfactory layout, and load it into the KLayout PCell

'''

# klayout api
import pya
import gdsfactory as gf
import inspect
from SiEPIC.utils.layout import make_pin
from SiEPIC.utils import get_technology_by_name
from gdsfactory.add_padding import get_padding_points

class mmi1x2(pya.PCellDeclarationHelper):

def __init__(self):

# Important: initialize the super class
super(mmi1x2, self).__init__()

# query the GDSfactory PCell to get parameters and add to KLayout
#import gdsfactory as gf
#import inspect
sig = inspect.signature(gf.components.mmi1x2)
params = sig.parameters
for p in params.values():
if p.kind is inspect.Parameter.POSITIONAL_OR_KEYWORD:
param_name = p.name
param_default = p.default
param_type = type(param_default)
if param_type is type(1.0):
self.param(param_name, self.TypeDouble, param_name, default = param_default)
if param_type is type(1):
self.param(param_name, self.TypeInt, param_name, default = param_default)
if param_type is type(True):
self.param(param_name, self.TypeBoolean, param_name, default = param_default)
# self.TypeLayer, TypeList, TypeNone, TypeShape, TypeString
# no layer parameters

# add layer parameters
# TO DO: lots of this code is duplicate with the code in produce_impl()
# - create a function to take in the gdsfactory component name and return
# the labels, layers, ports

# extracting all pcell information from gdsfactory pcell
pcell = gf.components.mmi1x2()

# get dictionary mapping layers to the polygons (represented by points) contained within
layer_to_polygonpts = pcell.get_polygons(by_spec=True)

# get ports
ports = pcell.get_ports()

# get gdsfactory layer information
layers = pcell.get_layers()
layer_names = pcell.get_layer_names()

# get labels
labels = pcell.get_labels()

# get bounding box points from gdsfactory
bbox_points = get_padding_points(pcell)
#bbox = gf.components.bbox(bbox=points, layer=(68,0))

# translate extracted information into klayout pcell

# add layer parameters to pcell decl
layers = list(layer_to_polygonpts.keys())

# include layers for pins (get them from the ports)
for port in ports:
if port.layer not in layers:
layers.append(port.layer)

# include layers for labels
for label in labels:
layer = label.layer
if layer not in layers:
layers.append(layer)

for l in layers:
# how to get the name?
# use the layer map?
PDK = gf.get_active_pdk()
name_to_layer = PDK.layers
layer_to_name = {v: k for k, v in name_to_layer.items()}
name = layer_to_name[l]

self.param(name, self.TypeLayer, "{} Layer".format(name), default = LayerInfo(l[0], l[1]))

# create devrec layer, what about pin rec layers?
# for pin layers: checked the layers for each port and created layer parameters for them
self.technology_name = 'EBeam'
TECHNOLOGY = get_technology_by_name(self.technology_name)
self.param("devrec", self.TypeLayer, "DevRec Layer", default = TECHNOLOGY['DevRec'])

def display_text_impl(self):
# Provide a descriptive text for the cell

param_list = ''
for p in self.get_parameters():
param_list += '_' + p.name + '_' + str(eval('self.%s' % p.name))

return "mmi1x2" + param_list

def produce_impl(self):

# extracting all pcell information from gdsfactory pcell
pcell = gf.components.mmi1x2()

# get dictionary mapping layers to the polygons (represented by points) contained within
layer_to_polygonpts = pcell.get_polygons(by_spec=True)

# get ports
ports = pcell.get_ports()

# get gdsfactory layer information
layers = pcell.get_layers()
layer_names = pcell.get_layer_names()

# get labels
labels = pcell.get_labels()

# get bounding box points from gdsfactory
bbox_points = get_padding_points(pcell)

# translate extracted information into klayout pcell

# add layer parameters to pcell decl
layers = list(layer_to_polygonpts.keys())

# include layers for pins (get them from the ports)
for port in ports:
if port.layer not in layers:
layers.append(port.layer)

# include layers for labels
for label in labels:
layer = label.layer
if layer not in layers:
layers.append(layer)

# map layer numbers to their name
PDK = gf.get_active_pdk()
name_to_layer = PDK.layers
layer_to_name = {v: k for k, v in name_to_layer.items()}


# add polygons to pcell in correct layer
for l in layer_to_polygonpts.keys():
polygonpts = layer_to_polygonpts[l]
layer_name = layer_to_name[l]

layer = self.layout.layer(getattr(self, layer_name))

# need to convert to a Point array since this is how points are passed into Polygons
for pts in polygonpts:
klayout_points = []
for p in pts:
klayout_points.append(Point(p[0],p[1]))

self.cell.shapes(layer).insert(Polygon(klayout_points))

# add pins: get the appropriate port information, then call make_pin()
for port in ports:
port_layer_name = layer_to_name[port.layer]
port_layer = self.layout.layer(getattr(self, port_layer_name))
make_pin(self.cell, port.name, port.center, port.width, port_layer, port.orientation)

# insert labels into correct layer and position
for label in labels:
layer_name = layer_to_name[label.layer]
klayout_label = Text(label.text, label.origin)
self.cell.shapes(self.layout.layer(self.layer_name)).insert(klayout_label)

# add bounding box to dev rec layer
# using bbox points make simple polygon to represent bbox
# convert points to a klayout Points array
bbox_klayout_points = []
for p in bbox_points:
bbox_klayout_points.append(Point(p[0],p[1]))

bbox = SimplePolygon(bbox_klayout_points)

self.cell.shapes(self.layout.layer(self.devrec)).insert(bbox)

class GDSfactory_PCellLib(pya.Library):

def __init__(self):

# TODO: change the description
self.description = "Generic library"

# register the PCell declarations
self.layout().register_pcell("mmi1x2", mmi1x2())

# register our library
self.register("GDSfactory PCells")


# instantiate and register the library
GDSfactory_PCellLib()



</text>
</klayout-macro>

0 comments on commit cc9633b

Please sign in to comment.