-
-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #196 from jasminabrar/master
Added automated docker build process and a sample 'disabled' GitHub action
- Loading branch information
Showing
7 changed files
with
373 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 }} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1508,4 +1508,3 @@ def pointlist_to_path(pointlist, dbu): | |
return path | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |