Skip to content

Commit

Permalink
Merge pull request #55 from luzeqin/master
Browse files Browse the repository at this point in the history
Master

Former-commit-id: 00fb32b
  • Loading branch information
lukasc-ubc committed Feb 20, 2016
2 parents 0e534c7 + 693a42b commit 016d4b1
Show file tree
Hide file tree
Showing 5 changed files with 297 additions and 41 deletions.
Binary file modified Lumerical_EBeam_CML/ebeam_v1.2/ebeam_bragg_te1550.ice
Binary file not shown.
Binary file modified Lumerical_EBeam_CML/ebeam_v1.2/ebeam_wg_integral_1550.ice
Binary file not shown.
Binary file modified Lumerical_EBeam_CML/ebeam_v1.2/ebeam_y_1550.ice
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<klayout-macro>
<description>Lumerical INTERCONNECT - Monte Carlo simulations</description>
<description>Lumerical INTERCONNECT - WtW Monte Carlo simulations</description>
<version/>
<category>pymacros</category>
<prolog/>
Expand Down Expand Up @@ -31,7 +31,7 @@ Lukas Chrostowski 2015/11/19
- generating a Spice netlist including Optical Network Analyzer; launch Lumerical INTERCONNECT simulation

Zeqin Lu 2015/12/10
- Monte Carlo simulation
- Wafer to Wafer Monte Carlo simulation

"""

Expand Down Expand Up @@ -107,66 +107,65 @@ text_lsf += 'switchtolayout;\n'
text_lsf += 'deleteall;\n'
text_lsf += 'importnetlist("%s");\n' % filename
text_lsf += 'addproperty("::Root Element", "seed", "wafer", "Number"); \n'
text_lsf += 'addproperty("::Root Element::%s", "thickness_xy_wafer", "wafer", "Matrix");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "width_xy_wafer", "wafer", "Matrix");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "grid", "wafer", "Number");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "Resolution", "wafer", "Number");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "non_uniform", "wafer", "Number");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "MC_uniformity_thickness", "wafer", "Matrix");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "MC_uniformity_width", "wafer", "Matrix");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "MC_grid", "wafer", "Number");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "MC_resolution_x", "wafer", "Number");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "MC_resolution_y", "wafer", "Number");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "MC_non_uniform", "wafer", "Number");\n' % topcell.name

############################## Wafer generation ###########################################
#text_lsf += 'addproperty("::Root Element", "seed_process", "wafer", "Number");\n'
#text_lsf += 'set("seed_process",1); \n'

text_lsf += 'select("::Root Element");\n'
text_lsf += 'set("setup script",'+ "'" + ' \n'
text_lsf += 'x_span = 100000e-6; \n' #100x100 mm^2 wafer
text_lsf += 'y_span = 100000e-6; \n'
text_lsf += 'corr_length_x = 4500e-6; \n'
text_lsf += 'corr_length_y = 4500e-6; \n'

text_lsf += 'Nx = 500; \n'
text_lsf += 'Ny = 500; \n'
text_lsf += 'wafer_length = 100000e-6; \n' #100x100 mm^2 wafer
text_lsf += 'clx = 4500e-6; \n' # Correlation length in x
text_lsf += 'cly = 4500e-6; \n' # Correlation length in y
text_lsf += 'N = 500; \n'
text_lsf += 'wafer_grid=wafer_length/N; \n'

text_lsf += 'sigma_rms_width = 15/3; \n'
text_lsf += 'sigma_rms_thickness = 6/3; \n'

text_lsf += 'x = linspace(-x_span/2,x_span/2,Nx); \n'
text_lsf += 'y = linspace(-y_span/2,y_span/2,Ny); \n'

text_lsf += 'x = linspace(-wafer_length/2,wafer_length/2,N); \n'
text_lsf += 'y = linspace(-wafer_length/2,wafer_length/2,N); \n'
text_lsf += 'xx = meshgridx(x,y) ; \n'
text_lsf += 'yy = meshgridy(x,y) ; \n'

text_lsf += 'randreset(seed); \n'
text_lsf += 'Z_thickness = sigma_rms_thickness*randnmatrix(Nx,Ny); \n'
text_lsf += 'F_thickness = exp(-(xx^2/(corr_length_x^2/2)+yy^2/(corr_length_y^2/2))); \n'
text_lsf += 'thickness_xy_wafer = real( 2/sqrt(pi)*y_span/Nx/sqrt(corr_length_x)/sqrt(corr_length_y)*invfft(fft(Z_thickness,1,0)*fft(F_thickness,1,0), 1, 0) ); \n'
text_lsf += 'Z_thickness = sigma_rms_thickness*randnmatrix(N,N); \n'
text_lsf += 'F_thickness = exp(-(abs(xx)/(clx/2)+abs(yy)/(cly/2))); \n' # exponential filter
text_lsf += 'wafer_uniformity_thickness = real( 2*wafer_length/N/sqrt(clx*cly)*invfft(fft(Z_thickness,1,0)*fft(F_thickness,1,0), 1, 0) ); \n' # wafer created using exponential filter
#text_lsf += 'F_thickness = exp(-(xx^2/(clx^2/2)+yy^2/(cly^2/2))); \n' # Gaussian filter
#text_lsf += 'wafer_uniformity_thickness = real( 2/sqrt(pi)*wafer_length/N/sqrt(clx)/sqrt(cly)*invfft(fft(Z_thickness,1,0)*fft(F_thickness,1,0), 1, 0) ); \n' # wafer created using Gaussian filter

text_lsf += 'randreset(seed-1000); \n'
text_lsf += 'Z_width = sigma_rms_width*randnmatrix(Nx,Ny); \n'
text_lsf += 'F_width = exp(-(xx^2/(corr_length_x^2/2)+yy^2/(corr_length_y^2/2))); \n'
text_lsf += 'width_xy_wafer = real( 2/sqrt(pi)*y_span/Nx/sqrt(corr_length_x)/sqrt(corr_length_y)*invfft(fft(Z_width,1,0)*fft(F_width,1,0), 1, 0) ); \n'
text_lsf += 'Z_width = sigma_rms_width*randnmatrix(N,N); \n'
text_lsf += 'F_width = exp(-(abs(xx)/(clx/2)+abs(yy)/(cly/2))); \n' # exponential filter
text_lsf += 'wafer_uniformity_width = real( 2*wafer_length/N/sqrt(clx*cly)*invfft(fft(Z_width,1,0)*fft(F_width,1,0), 1, 0) ); \n' # wafer created using exponential filter
#text_lsf += 'F_width = exp(-(xx^2/(clx^2/2)+yy^2/(cly^2/2))); \n' # Gaussian filter
#text_lsf += 'wafer_uniformity_width = real( 2/sqrt(pi)*wafer_length/N/sqrt(clx)/sqrt(cly)*invfft(fft(Z_width,1,0)*fft(F_width,1,0), 1, 0) ); \n' # wafer created using Gaussian filter

text_lsf += '######################## high resolution interpolation ################# \n'
text_lsf += 'Nx_new = 800; \n'
text_lsf += 'Nx_new = 800; \n'
text_lsf += 'x_span_new = 4000e-6; \n'
text_lsf += 'y_span_new = 4000e-6; \n'
text_lsf += 'grid=x_span_new/Nx_new; \n'
text_lsf += 'Resolution = Nx_new; \n'

text_lsf += 'x_new = linspace(-x_span_new/2,x_span_new/2,Nx); \n'
text_lsf += 'y_new = linspace(-y_span_new/2,y_span_new/2,Ny); \n'
text_lsf += 'thickness_new_wafer = interp(thickness_xy_wafer, x, y, x_new, y_new); # interpolation \n'
text_lsf += 'width_new_wafer = interp(width_xy_wafer, x, y, x_new, y_new); # interpolation \n'

text_lsf += 'MC_grid = 5e-6; \n'
text_lsf += 'die_span_x = 5000e-6; \n'
text_lsf += 'die_span_y = 5000e-6; \n'
text_lsf += 'MC_resolution_x = die_span_x/MC_grid; \n'
text_lsf += 'MC_resolution_y = die_span_y/MC_grid; \n'
text_lsf += 'x_die = linspace(-die_span_x/2, die_span_x/2, MC_resolution_x); \n'
text_lsf += 'y_die = linspace(-die_span_y/2, die_span_y/2, MC_resolution_y); \n'
text_lsf += 'MC_uniformity_thickness = interp(wafer_uniformity_thickness, x, y, x_die, y_die); # interpolation \n'
text_lsf += 'MC_uniformity_width = interp(wafer_uniformity_width, x, y, x_die, y_die); # interpolation \n'

text_lsf += '#pass wafers to Root \n'
text_lsf += 'select("::Root Element::%s"); \n' % topcell.name
text_lsf += 'set("thickness_xy_wafer",thickness_new_wafer); \n'
text_lsf += 'set("width_xy_wafer",width_new_wafer); \n'
text_lsf += 'set("Resolution",Resolution); \n'
text_lsf += 'set("grid",grid); \n'
text_lsf += 'set("non_uniform",1); \n'
text_lsf += 'set("MC_uniformity_thickness",MC_uniformity_thickness); \n'
text_lsf += 'set("MC_uniformity_width",MC_uniformity_width); \n'
text_lsf += 'set("MC_resolution_x",MC_resolution_x); \n'
text_lsf += 'set("MC_resolution_y",MC_resolution_y); \n'
text_lsf += 'set("MC_grid",MC_grid); \n'
text_lsf += 'set("MC_non_uniform",1); \n'
text_lsf += "'"+'); \n'


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
<?xml version="1.0" encoding="utf-8"?>
<klayout-macro>
<description>Lumerical INTERCONNECT - DtD Monte Carlo simulations</description>
<version/>
<category>pymacros</category>
<prolog/>
<epilog/>
<doc/>
<autorun>false</autorun>
<autorun-early>false</autorun-early>
<shortcut/>
<show-in-menu>true</show-in-menu>
<group-name/>
<menu-path>siepic_menu.end</menu-path>
<interpreter>python</interpreter>
<dsl-interpreter-name/>
<text># Python script
# SiEPIC_EBeam_functions

"""
This file is part of the SiEPIC_EBeam_PDK
by Lukas Chrostowski (c) 2015

This Python file extract the circuit netlist from the physical layout, saves it to Spice file,
and launches Lumerical INTERCONNECT for circuit simulations.

Version history:

Lukas Chrostowski 2015/11/19
- initial version
- generating a Spice netlist including Optical Network Analyzer; launch Lumerical INTERCONNECT simulation

Zeqin Lu 2016/2/18
- Within Wafer Monte Carlo simulation

"""

import os
print(os.name)

import platform
print(platform.system())
print(platform.release())

import sys
version = sys.version

import string

SIMULATION = 2 # INTERCONNECT simulation

INTERCONNECT_VISUALIZER = 1 # Plot the data using the Lumerical visualizer, or a regular plot?


# find the currently selected cell:
topcell = pya.Application.instance().main_window().current_view().active_cellview().cell
if topcell == None:
raise Exception("No cell")
layout = topcell.layout()
dbu = layout.dbu

# initialize the arrays to keep track of layout objects
optical_components = []
optical_waveguides = []
optical_pins = []
optical_nets = []

# Define layers based on the PDK:
LayerSiN = layout.layer(LayerSi)
LayerTextN = layout.layer(LayerText)
LayerPinRecN = layout.layer(LayerPinRec)
LayerDevRecN = layout.layer(LayerDevRec)
LayerFbrTgtN = layout.layer(LayerFbrTgt)
LayerErrorN = layout.layer(LayerError)
LayerINTERCONNECTN = layout.layer(LayerINTERCONNECT)


# extract the circuit netlist from the physical layout:
optical_waveguides, optical_components = netlist_extraction(topcell)[:2]

# Output the Spice netlist:
text_Spice, num_detectors = generate_Spice_file(topcell, optical_waveguides, optical_components)
print(text_Spice)

if sys.platform.startswith("win"):

folder_name = app.application_data_path()
if not os.path.isdir(folder_name+'/tmp'):
os.makedirs(folder_name+"/tmp")
filename = folder_name + '/tmp/%s.spi' % topcell.name
filename2 = folder_name + '/tmp/%s.lsf' % topcell.name
else:

filename = '/tmp/%s.spi' % topcell.name
filename2 = '/tmp/%s.lsf' % topcell.name

# Write the Spice netlist to file
file = open(filename, 'w')
file.write (text_Spice)
file.close()

# Write the Lumerical INTERCONNECT start-up script.
file = open(filename2, 'w')
text_lsf = '###DEVELOPER:Zeqin Lu, University of British Columbia, Feb. 2016 \n'

text_lsf += 'switchtolayout;\n'
text_lsf += 'deleteall;\n'
text_lsf += 'importnetlist("%s");\n' % filename
text_lsf += 'addproperty("::Root Element", "wafer_uniformity_thickness", "wafer", "Matrix");\n'
text_lsf += 'addproperty("::Root Element", "wafer_uniformity_width", "wafer", "Matrix");\n'
text_lsf += 'addproperty("::Root Element", "N", "wafer", "Number");\n'
text_lsf += 'addproperty("::Root Element", "die_num", "wafer", "Number");\n'
text_lsf += 'addproperty("::Root Element", "wafer_length", "wafer", "Number");\n'

text_lsf += 'addproperty("::Root Element::%s", "MC_uniformity_thickness", "wafer", "Matrix");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "MC_uniformity_width", "wafer", "Matrix");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "MC_grid", "wafer", "Number");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "MC_resolution_x", "wafer", "Number");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "MC_resolution_y", "wafer", "Number");\n' % topcell.name
text_lsf += 'addproperty("::Root Element::%s", "MC_non_uniform", "wafer", "Number");\n' % topcell.name

############################## Wafer generation ###########################################
text_lsf += 'wafer_length = 100000e-6; \n' #100x100 mm^2 wafer
text_lsf += 'clx = 4500e-6; \n' # Correlation length in x
text_lsf += 'cly = 4500e-6; \n' # Correlation length in y
text_lsf += 'N = 500; \n'
text_lsf += 'wafer_grid=wafer_length/N; \n'

text_lsf += 'sigma_rms_width = 15/3; \n'
text_lsf += 'sigma_rms_thickness = 6/3; \n'

text_lsf += 'x = linspace(-wafer_length/2,wafer_length/2,N); \n'
text_lsf += 'y = linspace(-wafer_length/2,wafer_length/2,N); \n'
text_lsf += 'xx = meshgridx(x,y) ; \n'
text_lsf += 'yy = meshgridy(x,y) ; \n'

text_lsf += 'Z_thickness = sigma_rms_thickness*randnmatrix(N,N); \n'
text_lsf += 'F_thickness = exp(-(abs(xx)/(clx/2)+abs(yy)/(cly/2))); \n' # exponential filter
text_lsf += 'wafer_uniformity_thickness = real( 2*wafer_length/N/sqrt(clx*cly)*invfft(fft(Z_thickness,1,0)*fft(F_thickness,1,0), 1, 0) ); \n' # wafer created using exponential filter
#text_lsf += 'F_thickness = exp(-(xx^2/(clx^2/2)+yy^2/(cly^2/2))); \n' # Gaussian filter
#text_lsf += 'wafer_uniformity_thickness = real( 2/sqrt(pi)*wafer_length/N/sqrt(clx)/sqrt(cly)*invfft(fft(Z_thickness,1,0)*fft(F_thickness,1,0), 1, 0) ); \n' # wafer created using Gaussian filter

text_lsf += 'Z_width = sigma_rms_width*randnmatrix(N,N); \n'
text_lsf += 'F_width = exp(-(abs(xx)/(clx/2)+abs(yy)/(cly/2))); \n' # exponential filter
text_lsf += 'wafer_uniformity_width = real( 2*wafer_length/N/sqrt(clx*cly)*invfft(fft(Z_width,1,0)*fft(F_width,1,0), 1, 0) ); \n' # wafer created using exponential filter
#text_lsf += 'F_width = exp(-(xx^2/(clx^2/2)+yy^2/(cly^2/2))); \n' # Gaussian filter
#text_lsf += 'wafer_uniformity_width = real( 2/sqrt(pi)*wafer_length/N/sqrt(clx)/sqrt(cly)*invfft(fft(Z_width,1,0)*fft(F_width,1,0), 1, 0) ); \n' # wafer created using Gaussian filter

##################################### pass wafers to root ###################
text_lsf += '#pass wafers to object \n'
text_lsf += 'select("::Root Element"); \n'
text_lsf += 'set("wafer_uniformity_thickness", wafer_uniformity_thickness); \n'
text_lsf += 'set("wafer_uniformity_width", wafer_uniformity_width); \n'
text_lsf += 'set("N",N); \n'
text_lsf += 'set("wafer_length",wafer_length); \n'

text_lsf += 'select("::Root Element");\n'
text_lsf += 'set("setup script",'+ "'" + ' \n'
text_lsf += '######################## high resolution interpolation for dies ################# \n'
text_lsf += 'MC_grid = 5e-6; \n'
text_lsf += 'die_span_x = 5000e-6; \n'
text_lsf += 'die_span_y = 5000e-6; \n'
text_lsf += 'MC_resolution_x = die_span_x/MC_grid; \n'
text_lsf += 'MC_resolution_y = die_span_y/MC_grid; \n'
text_lsf += 'die_num_x = floor(wafer_length/die_span_x); \n'
text_lsf += 'die_num_y = floor(wafer_length/die_span_y); \n'
text_lsf += 'die_num_total = die_num_x*die_num_y; \n'
text_lsf += 'x = linspace(-wafer_length/2,wafer_length/2,N); \n'
text_lsf += 'y = linspace(-wafer_length/2,wafer_length/2,N); \n'

# pick die for simulation
text_lsf += 'if (die_num&lt;=die_num_total) { \n'
text_lsf += 'j=die_num; \n'
text_lsf += 'die_min_x = -wafer_length/2+(j-1)*die_span_x -floor((j-1)/die_num_x)*wafer_length; \n'
text_lsf += 'die_max_x = -wafer_length/2+j*die_span_x -floor((j-1)/die_num_x)*wafer_length; \n'
text_lsf += 'die_min_y = wafer_length/2-ceil(j/die_num_y)*die_span_y; \n'
text_lsf += 'die_max_y = wafer_length/2-(ceil(j/die_num_y)-1)*die_span_y; \n'

text_lsf += 'x_die = linspace(die_min_x, die_max_x, MC_resolution_x); \n'
text_lsf += 'y_die = linspace(die_min_y, die_max_y, MC_resolution_y); \n'

text_lsf += 'MC_uniformity_thickness = interp(wafer_uniformity_thickness, x, y, x_die, y_die); # interpolation \n'
text_lsf += 'MC_uniformity_width = interp(wafer_uniformity_width, x, y, x_die, y_die); # interpolation \n'
text_lsf += '} \n'

text_lsf += '#pass wafers to object \n'
text_lsf += 'select("::Root Element::%s"); \n' % topcell.name
text_lsf += 'set("MC_uniformity_thickness",MC_uniformity_thickness); \n'
text_lsf += 'set("MC_uniformity_width",MC_uniformity_width); \n'
text_lsf += 'set("MC_resolution_x",MC_resolution_x); \n'
text_lsf += 'set("MC_resolution_y",MC_resolution_y); \n'
text_lsf += 'set("MC_grid",MC_grid); \n'
text_lsf += 'set("MC_non_uniform",1); \n'

text_lsf += "'"+'); \n'


text_lsf += '#Run Monte Carlo simulations; \n'
if INTERCONNECT_VISUALIZER:
for i in range(0, num_detectors):
text_lsf += 'mc%s = matrixdataset("mc%s"); # initialize visualizer data, mc%s \n' % (i+1, i+1, i+1)
text_lsf += 'seed=randreset; \n'
text_lsf += 'for (simu=1;simu&lt;=5;simu=simu+1) { \n'
text_lsf += ' switchtodesign; \n'
text_lsf += ' select("::Root Element"); \n'
text_lsf += ' set("die_num",simu); \n'
text_lsf += ' run;\n'

text_lsf += ' select("ONA_1");\n'
text_lsf += ' f_start = get("start frequency");\n'
text_lsf += ' f_stop = get("stop frequency");\n'
text_lsf += ' num_points = get("number of points");\n'
text_lsf += ' wavelength = c/f_start : (c/f_stop-c/f_start)/(num_points-1) : c/f_stop;\n'

if INTERCONNECT_VISUALIZER:
for i in range(0, num_detectors):
text_lsf += ' if (simu==1) { mc%s.addparameter("wavelength",wavelength);} \n' % (i+1)
text_lsf += ' mc%s.addattribute("run", getattribute ( getresult("ONA_1", "input %s/mode 1/gain"), "TE gain (dB)") );\n' % (i+1, i+1)
else:
text_lsf += ' gain = getattribute( getresult("ONA_1","input 1/mode 1/gain"), "TE gain (dB)" );\n'
text_lsf += ' plot(wavelength,gain);\n'
text_lsf += ' holdon;\n'

text_lsf += '}\n'
if INTERCONNECT_VISUALIZER:
for i in range(0, num_detectors):
text_lsf += 'visualize(mc%s);\n' % (i+1)


file.write (text_lsf)
file.close()

print(text_lsf)

if sys.platform.startswith('linux'):
# Linux-specific code here...
if string.find(version,"2.") &gt; -1:
import commands
print("Running INTERCONNECT")
commands.getstatusoutput('/CMC/tools/lumerical/INTERCONNECT-5.0.527/bin/interconnect')

elif sys.platform.startswith('darwin'):
# OSX specific
if string.find(version,"2.7.") &gt; -1:
import commands
print("Running INTERCONNECT")
#commands.getstatusoutput('open /Applications/Lumerical/INTERCONNECT/INTERCONNECT.app --args %s' % filename)
commands.getstatusoutput('open -n /Applications/Lumerical/INTERCONNECT/INTERCONNECT.app --args -run %s' % filename2)

elif sys.platform.startswith('win'):
# Windows specific code here
import subprocess
print("Running INTERCONNECT")
subprocess.Popen(args=['C:\\Program Files\\Lumerical\\INTERCONNECT\\bin\\interconnect.exe', '-run', filename2], shell=True)

</text>
</klayout-macro>

0 comments on commit 016d4b1

Please sign in to comment.