-
Notifications
You must be signed in to change notification settings - Fork 156
Commit
Update from Master Former-commit-id: 377f734
- Loading branch information
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
77e2ba14c6abde44a79f6f997fbe3cda0bc1755b |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
a7f67ce95af5397b409223bc362e9e3b8f8decd4 |
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<=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<=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.") > -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.") > -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> |