This toolbox is made of two main component
- The NIST Lithography toolbox made by Rob Illic at NIST and using a java backend for easy creation of primitive or polygons into gds. That is pretty much working for sure and refer to the Rob's tool page for more information
- A python layer created by me for very easy user interfacing to generated dense layout of differnet microring resonator. Well, here that's my contribution, and it may or may not work perfectly but so far it works sufficiently good enough.
I so not plan on creating new functionallity based on the community needed. Instead, I am sharing what I have developed throughout the years and used regularly for my own designs. Reach out if needed but I provide very limited support.
In the idea of sharing with the community, if you create new functionality, create a pull requests please
Here I would only discuss the UNIX way to install, it no idea how to do on Windows. Should be similar but I invite you to look at Rob's toolbox manual if needed
- Download and install the Oracle version 8 of the Java Runtime Environment. (Note: OpenJava will not work_
- If you are on a Linux machine, make sure that you are indeed using this version of java
- list all version of java install using
update-java-alternatives --list - change if needed which version you are using through
sudo update-alternatives --config java - You may need to reboot.
- Open the NIST toolbox ui to check if it works, usually through a command line such that
java -jar <jarFile>
- list all version of java install using
You will have to modify the xml file that defined where all the path are for the java toolbox. In particular line 64 to defined where the CNST is placed in your system.
⚠︎ Note that line 69 should not be changed. It is essential to save the gds to /opt/gds for the python toolbox to work.
To this extend you may want to create a folder sudo mkdir /opt/gds which you set the property correctly sudo chmod 777 /opt/gds
You shouldn't have much to do here hopefully. Either you know you won't touch much the toolbox and you can install it system-wide through
python setup.py install
Note: you may need to use python3 depending on your environment. Note: you may want to create a virtual environment first
If you plan on tweaking it, I recomand to add the NISTgenerator package to your python path manually as described in the examples
In case you are tweaking the package a lot, it is easier to put it in a path that is more user friendly than the standard site-packaged such that:
import os, sys
parFile = os.path.expanduser(r"/Users/greg/Documents/Nanofab/PatternDesign/")
if not parFile in sys.path:
sys.path.insert(-1, parFile)Defining a set of parameters that are global for the chip, all parameter should be straighforward to understand. Both a Global Parameter and a Cell dictionary must be defined
GlobalParams = dict(
resist="positive",
Wchip=2500,
Hchip=10000,
layer_ring=1,
layer_waveguide=1,
layer_label=1,
device_layer=1,
photomask_layer=1,
)
Cells = dict(ncell=-1, cell_type=[], param=[], YSHIFT=[])A single chip is defined by "Blocks", each block being looped through the parameter that are sets inside a dictionary. Every combination possible will be created with this type of nesting:
- Pulley length:
- waveguide/ring gap:
- Dimer gap:
- Ring width:
- Ring radius:
- Bus waveguide width:
- PhC inner ring modulation strength:
- PhC ring modulation phase:
- PhC inner ring modulation strength:
- Bus waveguide width:
- Ring radius:
- Ring width:
- Dimer gap:
- waveguide/ring gap:
(i.e. if ring width and ring radius are varried, all the different ring radii will be next to each other with a fixed RW, and the RW is steped once the variation of RR is done)
Several Blocks can be defined, and they will be shifted by the parameter top_shift which is a loose thing to set
⚠︎All dimnesioned are in micrometers!!⚠︎
Block = [
dict(
racetrack=True,
heater=True,
RR=23,
Lrace=361,
G=np.arange(300, 600.1, 100),
RW=np.arange(800, 1000.1, 10),
W=0.460,
ypitch=10,
xpitch=165,
carriage_shift=20,
Wtapper=0.2,
xdec=180,
Label="Rtrack Lc=361 Curve Cpl - 400GHz",
),
dict(
top_shift=1600,
racetrack=True,
heater=True,
RR=23,
Lrace=361,
G=np.arange(300, 600.1, 100),
RW=np.arange(1700, 2100.1, 25),
W=0.460,
ypitch=10,
xpitch=165,
carriage_shift=20,
Wtapper=0.32,
xdec=180,
Label="Rtrack Lc=361 Curve Cpl - 400GHz ª • 1550nm pump",
)
]If multiple chips needs to be made, it is convenient to wrap the each Block list into another dictionary, index by the chip number. FOr instance
Blocks = {}
Blocks[1] = [
dict(
RR=23,
G=gregArange(250, 50, 600),
RW=gregArange(800, 10, 920),
W=gregArange(360, 100, 660),
ypitch=9.5,
xpitch=85,
xdec=97,
Label="RR=23 Strg Cpl",
)
]
Blocks[2] = [copy(Blocks[1][0])]
Blocks[2][0].update(RR = 24)Several utilies are defined for the sake of simplicity to create the design and make them into a chip. Usually the standard ones are:
NISTgenerator.Utils.LogFile(GlobalParams, block, Cells, design_number=index)This create a log file in the log folder of the working directory
NISTgenerator.ChipFeature.TopLabel(Cells, GlobalParams, block, data=label, design_number=index)Create a top label for chip identification. This also create a QR code and can be disbaled
NISTgenerator.Ring.RingPulleyWgShifted(Cells, GlobalParams, Block, design_number=index)This function let you create from the a single Block list the densed version of the Ligentec layout.
The generation is split in two steps: creation of the cnst file through python, creation of the gds from the java tool box.
Hence, one need to first call the
CNSTpath = os.path.expanduser(<PATH WHERe IT>r"CNSTnanoToolboxV2019.05.01/cnst_script_files/")
NISTgenerator.Builder.CreateCNST(
Cells["cell_type"],
Cells["param"],
"DesignFilenName",
yshift=Cells["YSHIFT"],
CNSTpath=CNSTpath,
top_cell_name=f"TOP",
xdec=GlobalParams["Wchip"] / 2,
ydec=GlobalParams["Hchip"],
res=0.005,
)Please be adviced to change the res parameter accordingly to your fabrication process.
This will create a DesignFilenName.cnst in the cnst folder of your working directory.
To create the gds file, one would nee to use
Gen.Builder.CreateGDS(
GlobalParams["filename"],
CNSTpath=CNSTpath,
GDSpath=r"/opt/gds_files_created/",
ToolBoxPath=CNSTpath.split("cnst_")[0],
javaVers="CNSTspecialScriptsV2019.05.01.jar",
removeRobCell=True,
dogds=True,
dcty=os.path.dirname(__file__),
)Which will create a DesignFilenName.gds in the gds folder of your working directory
When many chips (let's say 44), it becomes convenient to define all the parameter in separate files, define a dictionary of block for each chip, indexed by the chip number and run a loop for the gds generation