1 Introduction

SPECS (Scalable Photonic Event-driven Circuit Simulator) is a simulator of photonic circuits. It is possible to use SPECS in multiple ways, due to the flexibility of the netlist file format. You can call SPECS from the command line on Linux and Windows, from Python, or even create your own circuits directly in C++.

To ‘solve’ a circuit, the simulator numerically processes signals passing through components as events, based on compact models of components. These models define how each device will affect the amplitude and phase of optical signals of given wavelengths.

Note: In SPECS, events of multiple wavelengths can propagate simultaneously. For example, E1 = 1.0∠π  @ 1550nm E2 = 0.0∠0  @ 1560nm represent two events: the first of 1V/m amplitude and π radians at 1550nm wavelength, and a zero signal at 1560nm, representing the end of a pulse for this wavelength, for example.

The signal abstraction of SPECS, also known as a “baseband” approach, assumes that the changes in the wave characteristics are much slower than the wave oscillations themselves, which is usually true. A signal for this simulator is composed of multiple value-change events, that can happen across time. For example, the figure shows how a pulse can be described in this representation. More complex waveforms can be represented in this way by sampling it in events that contain the curve values at each specific time.

The biggest advantage of SPECS is that, being an event-driven simulator, there is no simulation when no signal change is present. This is optimal when dealing with pulses, but can also be interesting for waveforms where the values of interest are concentrated. SPECS gives the user freedom on how events can can be generated, given that they fit a 1fs (1e-15) grid. More details on the limitations can be found in the #reference.

2 Getting started

2.1 Installing SPECS (Linux)

Before anything, make sure you have the necessary prerequisites. For Debian-based systems,

> sudo apt install git cmake build-essentials clang ccache gtkwave

Note: If you are on windows using the WSL environment, you should follow this section, but GTKWave can be installed in its windows native version (the gtkwave.exe is inside the bin folder when extracted). Otherwise, you can install it in WSL and before running you must set up an X server.

To install SPECS, first clone our repository and make sure you have the mandatory prerequisites

> git clone https://github.com/clement-z/specs

If you are in our lab, the command is

> git clone https://gitlab.inl90.ec-lyon.fr/czrounba/systemc-pcm-matrix-multiplication-simulator.git specs

Go into the downloaded folder

> cd specs

Run the installation script

> sh install.sh

If everything went well, SPECS is ready to be used, and its executable is in the folder. It may be a good idea to run one of the premade simulation tests, for instance

> ./specs -t wg

In this folder you will also find useful things, such as our custom KiCAD symbol library for editing circuits with a GUI (more info in tut3_specs_tutorial_gui).

2.2 Creating SPECS netlists with a text editor

A netlist is a text file that contains the description of a circuit, and it is the simplest and most direct way to use SPECS (not requiring anything else to run). In this tutorial we will create the netlists for three circuits, run them in SPECS, and analyse the results using GTKWave, an open source program.

SPECS outputs results by default using the .vcd format, which GTKWave is made to process. In the Python part of the tutorial, you will see how to read the .vcd file directly in Python.

2.2.1 Simple waveguide circuit, operating point simulation

Consider the following photonic circuit.

We have a continuous-wave source (CWSRC1), connected to a waveguide (WG1). A netlist for this circuit looks like:

* Title: First circuit
* Lines starting with asterisk are ignored

* Description of the circuit
cwsrc1 in wl=1550e-9 power=1e-3
wg1 in out length=1e-2 neff=2 ng=4 att=3 d=0

* Analysis
.op

.end
tutorial_sch1.cir

Warning: The first line is always ignored. Use it for a title of your netlist and other useful info.

Warning: Always end the netlist with .end

At the start of the netlist, we have comments starting with *. Then, the circuit is described in three lines, one for each component. To instantiate a continuous-wave source, the line should start with CWSRC followed by a unique number identifier.

After a component’s name, we must specify the net to which each port is connected. Our syntax accepts numbers like 1 or strings like in, but not strings that start with numbers, like 1in. It is also possible to start the string with a forward slash such as /in. If multiple ports are present, they must be spaced by one single empty space.

After port names, we need to specify device-specific parameters. In the case of this source, we have wavelength wl in meters, and output power power. As the parameters are named, they can come in any order. This pattern is repeated in all other devices in this example.

Note: In photonics, many components are bidirectional, and SPECS supports them. However, depending on the context to which they are connected, waveguides can be considered as unidirectional, improving simulation time and memory.

For two-port components in unidirectional mode, the first (leftmost) is the input and the second (rightmost) is the output. For multi-port devices, check their documentation.

Try running this same example but changing the wg1 line to wg1 out in length=1e-2 neff=2 ng=4 att=3 d=0 and verify the difference in output.

To simulate a netlist in this way, we must specify a simulation directive in the file. In this case, it is .op, that evaluates the operational point of the circuit, printing the amplitude and phase of light in every node. This type of simulation considers only continuous wave sources.

Save the tutorial_sch1.cir file in the folder circuits/ located in the SPECS directory, then run the simulator with

> ./specs -f circuits/tutorial_sch1.cir

Warning: If you run SPECS outside of its own folder, make sure that you have a folder called traces in whatever directory you use, otherwise SPECS will fail to write its results to a file and thus will not run correctly.

If you get an error related to ‘Cannot open trace file’ and you don’t know what to do, type mkdir traces before running a simulation command.

SPECS will output the processing of the netlist in the terminal, then run the simulation. You should verify that the final output looks like this

╔═══════════════════╗
║  OPERATING POINT  ║
╠═══════════════════╣
║                   ╨───┄┄
║ - ROOT/in (OPTICAL) = [0019]  @ 1550 nm (0.031623 V.m⁻¹, 0.001000 W, 0.0000 rad)
║ - ROOT/out (OPTICAL) = [0033]  @ 1550 nm (0.022387 V.m⁻¹, 0.000501 W, 1.4188 rad)
║                   ╥───┄┄
╚═══════════════════╝
╔═══════════════════╗
║        DONE       ║
╚═══════════════════╝

We can see that in the out net, the optical power is 0.501 mW, with a phase delay. This amplitude comes from the fact that the waveguide has 1 cm and losses of 3 dB/cm.

Note: You may be used to terminate unconnected ports from other photonic simulators. In SPECS, every net is automatically terminated if it is not connected to another component.

2.2.2 Simple waveguide circuit, transient simulation

In this simulation we will use a slightly different circuit to simulate a pulse propagating through a waveguide and plot the results with GTKWave. The circuit is now the following

* Title: Second circuit

* Description of the circuit
vlsrc1 in values=[[0,1e-3,1550e-9],[1e-9,0,1550e-9]]
wg1 in out length=1e-2 neff=2 ng=4 att=3 d=0
probe1 out

* Analysis
.tran 2e-9

* Simulator options
.options timescale=-15 traceall=0

.end
tutorial_sch2.cir

There are a few new elements in this netlist. The first one is the VLSRC component. It is a single-port element that will emit a list of optical signal events as specified by the values keyword. Its syntax is values=[event1,event2,event3], and each event is specified as [time,power,wavelength], therefore the full syntax is values=[[t1,p1,wl1],[t2,p2,wl2],[t3,p3,wl3]].

Another new element is the probe. It will simply record all the events that it sees and save it to a .vcd file. When multiple probes are used, they all write to the same file.

To run a time-domain simulation (instead of finding the operating point) we must use the .tran command. It can take as argument the maximum simulation time, at which SPECS will stop running. If no max time is provided, SPECS will run until all the events are processed.

Finally, we included two simulator options with the .options directive. The timescale option informs SPECS the smallest time it should consider. In this case it is 10−15 , or 1 fs. To specify a timescale of 1 ns, use timescale=-9, for example. The option traceall determines if all nets of the circuit should be saved or not. When it is true (1), it is equivalent to adding a probe to every net.

Note: timescale is not a sampling time. SPECS is an event-driven simulator. This value determines the smallest time that can be represented.

Save the netlist to the circuits folder and run SPECS on it with

> ./specs -f circuits/tutorial_sch2.cir -o traces/tutorial_sch2

The -o option is followed by the output file location, and it could be anywhere in your computer. If no options are given, it will be saved to traces/delete_me.vcd as default.

The simulation output should be the following

╔═══════════════════╗
║  OPERATING POINT  ║
╠═══════════════════╣
║                   ╨───┄┄
║ - ROOT/in (OPTICAL) = [0001]  @ 1550 nm (0.000000 V.m⁻¹, 0.000000 W, 0.0000 rad)
║ - ROOT/out (OPTICAL) = [0019]  @ 1550 nm (0.000000 V.m⁻¹, 0.000000 W, 0.0000 rad)
║                   ╥───┄┄
╚═══════════════════╝
ROOT/VLSRC1 was enabled
@0 s, ROOT/VLSRC1 emitted: [0021]  @ 1550 nm (0.031623 V.m⁻¹, 0.001000 W, 0.0000 rad)
@1 ns, ROOT/VLSRC1 emitted: [0048]  @ 1550 nm (0.000000 V.m⁻¹, 0.000000 W, 0.0000 rad)
Simulated 2 ns
╔═══════════════════╗
║        DONE       ║
╚═══════════════════╝

Every transient simulation starts with an operating point simulation, to get the steady-state values in the circuit. Then, the VLSRC1 is enabled and it emits two signals: the first at 0s of 1mW, and the second at 1ns of 0W, both at the same wavelength.

To check out the results, open GTKWave with the following command, or by clicking File and Open New Tab in the GTKWave menus.

gtkwave traces/tutorial_sch2.vcd

On the left, under SST, click on the + icon beside SystemC, which will reveal the ROOT/PROBE1 content. Select it.

In the bottom, we see all the information saved by PROBE1. They represent, respectively, the amplitude (absolute value) of light seen by the probe, followed by its phase, power, and wavelength. Double click each one of them. They will be displayed in the graph to the right, as numbers.

Now you only see all as zero. It means that in the first two fs no signals were received by the probe. Adjust the scale by clicking on the symbol.

You can now see that, after about 133 ps, a pulse of power 0.5 mW is detected by the probe and, after 1.133ns, it goes back to zero. Note that these are the only two datapoints. There lies the strength of SPECS: it only simulates a component when it is needed, i.e., when events arrive. Note also that although we simulated the circuit with tran 2e-9, the data does not continue until 2 ns. That is because the specified time is a maximum, SPECS does not run anymore if there are no events to be processed.

2.2.3 Add-drop filter with two wavelengths, transient simulation

Now let’s try running a more complex circuit that contains dynamics that can also be visualized in GTKWave.

* Title: third circuit

* Options and simulation directive
.options traceall=0 timescale=-15
.tran

* Device parameters
.param length=1e-3
.param neff=2.44283
.param ng=4.05284
.param att=1
.param d=0
.param wl1=1549.600e-9
.param wl2=1549.716e-9

* Circuit description
VLSRC1 in values=[[0.1e-9,1,{wl1}],[1e-9,0,{wl1}],[0.1e-9,1,{wl2}],[1e-9,0,{wl2}]]
COUPLER1 in r1 out r2 k=0.5 
WG1 r2 r4 length={length} att={att} neff={neff} ng={ng} d={d}
WG2 r3 r1 length={length} att={att} neff={neff} ng={ng} d={d}
COUPLER2 r4 add r3 drop k=0.5
MLPROBE1 out wl=[{wl1},{wl2}]
MLPROBE2 drop wl=[{wl1},{wl2}]

.end
tutorial_sch3.cir

This circuit was written in unidirectional mode. Note how WG1 goes from r2 to r4, while WG2 goes from r3 to r1.

The first new component here is the directional coupler, instantiated as COUPLER. It has 4 ports, the two first being the inputs and the other two the outputs. Its parameter k is the field coupling value. It has also a parameter called loss, but it was not specified (SPECS has default value of zero).

The other new component is the multi-lambda probe MLPROBE. This device is required if you want to visualize different wavelengths separately, which is the case of a time-domain simulation with multiple wavelengths. We will see that in frequency domain sweeps it is not necessary. To use it, you must specify a list of wavelengths that it will monitor with the wl=[] argument.

Another novelty is the inclusion of the .param statements. These are useful to declare variables that will be used throughout the netlist. To use the variable length, you must insert it as {length} in a field that takes a number.

Call the simulation with

> ./specs -f circuits/tutorial_sch3.cir -o traces/tutorial_sch3

And load the traces/tutorial_sch3.vcd trace file. Notice how each MLPROBE has the the abs power phase wl signals for each wavelength.

Double-click on both power signals and adjust the scale by clicking on the symbol. It won’t be easy to understand what’s going on in this case. Let’s try changing the visualization mode.

First, select both signals holding the Shift button in the keyboard. Then right-click any of them and follow the menus as seen below.

Warning: In time-domain simulations, the time between samples may vary a lot because SPECS is an event-driven simulator. Therefore trying to interpolate this data may lead to incorrect visualization.

Changing the scale to step-analog is good, but not enough. The axis is still too thin. To solve this, right-click one of the signals and select Insert Analog Height Extension. Notice how it adds a blank line under the signal. You can copy and paste it to increase the height faster. Try making your graph look like this:

Since we took the data from MLPROBE1, this means that the first wavelength “passes” through the filter, and the second does not. Try looking at the power in MLPROBE2 and verify the circuit’s behavior at the drop port.

Note also that the data seems very square here. This is not a consequence of SPECS, but rather of the circuit’s dynamics, that update in discrete ways based on the waveguide delay. Finally, note that each row has a different y-axis, so make sure to use the cursor to get an idea of their amplitudes.

2.2.4 Add-drop filter with two wavelengths, frequency simulation

Photonic circuits usually have frequency domain characteristics, like the filter in previous example. Let’s try to plot it’s frequency domain transmission curves with SPECS.

* Title: third circuit

* Options and simulation directive
.options traceall=0 timescale=-15
.dc /cwsrc1/WL 1549.5e-9 1550.5e-9 2e-13

* Device parameters
.param length=1e-3
.param neff=2.44283
.param ng=4.05284
.param att=1
.param d=0
.param wl1=1549.600e-9
.param wl2=1549.716e-9

* Circuit description
CWSRC1 in power=1 wl=1550e-9
COUPLER1 in r1 out r2 k=0.5 
WG1 r2 r4 length={length} att={att} neff={neff} ng={ng} d={d}
WG2 r3 r1 length={length} att={att} neff={neff} ng={ng} d={d}
COUPLER2 r4 add r3 drop k=0.5
PROBE1 out
PROBE2 drop

.end
tutorial_sch4.cir

First, we adapted the source to a CWSRC and the multi-lambda probes to the simple PROBE. Then, we changed the simulation directive to .dc.

The .dc directive performs a series of .op simulations while sweeping through a parameter. In this case, we are interested in varying the wavelength of the CWSRC1 source from 1549.5 nm to 1550.5 nm, using a step of 0.2 pm.

Run the simulation and load up its results in GTKWave. Load the power signals of each probe and the wavelength signal of only one of them. After setting the visualization type to analog-interpolated and adding the appropriate spacings, you should see the following:

To have the extra information in the Signals panel, you can press h in your keyboard to activate the hierarchical naming. You can move the red cursor around to get the transmission levels of the circuit with respect to each output and also get the corresponding wavelength. Note that the wavelength was not set to analog, but it is increasing linearly.

Note: While SPECS can perform this type of simulation, it is not made with this purpose in mind, and the event-driven engine is not the most optimal for this situation. We intend to implement an S-matrix solver in the future, exclusively for this type of simulation.

2.2.5 Creating subcircuits

SPECS supports hierarchical netlists, meaning that you can create a block of other SPECS components, wrap it with its own parameters, and instantiate it in other netlists.

TODO, but you can check the circuits/subckt_tests.cir file, that implements this paradigm.

3 Using the Python interface

3.1 Using PySPECS

Python is a powerful and ubiquitous programming language. We have created SPECS wrappers for Python, so you can run it comfortably from your notebooks.

With Python, post-processing of SPECS data is made easy. We process the .vcd files

3.2 Configuration

We are currently planning a PySPECS release through PIP. While that does not come, you can follow the first tutorial to install SPECS normally, and you can find the following files in the pyspecs subfolder in the simulator’s root directory:

> ls pyspecs/
__pycache__  pyspecs_example.ipynb  specs.py  specsparse.py

Our python helpers depend on three other libraries, so make sure you install them using

> pip install numpy matplotlib pandas pyDigitalWaveTools

3.3 Running our example notebook

We have created a notebook with the complete utilization of SPECS in python. It assumes that you already created a netlist (you can use one from the previous examples).

To notebook is located in

specs/pyspecs/pyspecs_example.ipynb

3.4 Extra possibilities with python

While we did not cover that with our premade functions, it is possible to use python for:

  • Automatically generating circuits
  • Generating input data in CSV format for the electrical or optical sources
  • Run multiple simulations in parallel

They should all be fairly easy to do, as our program depends on a text file (the netlist), with inputs that can be loaded from csv files. The parallel part is easy because you can just call the SPECS executable multiple times, one on each thread, even outside of python.

If you develop helpers to facilitate your use of SPECS, we invite you to contribute to our repository.

4 Creating SPECS netlists with a graphical interface

Although creating netlists with a text editor is very simple and easy to automate, it is also possible to integrate SPECS with graphical schematic editors.

We created our netlist language to be compatible with SPICE, very common in electronics. As a reward, any electronic circuit editor can be adjusted to create a SPECS netlist, if you create the appropriate symbol library. We already created a symbol library for KiCad, but the same could be done for other programs.

4.1 Configuration

Assuming that you chose to use KiCad, install it on the official website, following their instructions. We will use only one part of KiCad, the schematic editor (Eeschema). Once you install the program, open KiCad and create a new project (Ctrl+N) in any place you find suitable.

Once the project has been created, open the schematic editor by clicking on its icon in the project’s interface.

Note: It is possible to load Eeschema directly by accessing the installation folder of KiCad and finding its executable. C:\Program Files\KiCad\7.0\bin\eeschema.exe in Windows.

When the editor is open, you should see a blank schematic page like the following

To include our custom symbol library, access the Preferences menu and click the Manage Symbol Libraries option.

In this page there may be a long list of symbol libraries. We do not really need them so to make it easier for us, first select all of them with CTRL+A and make sure that both the Active and Visible boxes are un-ticked.

Then, click the icon in the bottom row to add a new symbol library. The file explorer will open and you should select the file in specs/utils/specs.kicad_sym. If for some reason this step does not work, you can press the cross icon right beside it and manually enter the full directory. Make sure it is both Active and Visible, then press OK.

4.2 Schematic example

Let us create the same ring resonator schematic that we have used in the first tutorial, but now using KiCad. We will provide you with basic knowledge about their menus and hotkeys, but if you want more information on how to use Eeschema, you can check their documentation.

If the SPECS custom library is correctly installed, click the symbol on the right corner to add a component, or press A in your keyboard. The Choose Symbol window will pop up. Under SPECS, select WAVEGUIDE and click Ok. The symbol of a waveguide will appear under your cursor in the schematic sheet. Place it somewhere in the sheet.

Note that your mouse cursor will have the add component symbol under it. When clicking anywhere, the Choose Symbol window will appear again. Choose V_SOURCE_LIST this time and place it in the sheet. Repeat the same process for the DIRECTIONAL_COUPLER and PROBE components. You will have something like the following in the end.

You can move devices around by selecting and dragging them, or by pressing M after selection. Copy and paste the waveguide, probe, and coupler so you have two of each by using CTRL+C and CTRL+V. To rotate a component, press R when it is selected, and to mirror it horizontally (vertically), press X (Y) when it is selected.

Using these commands, organize your schematic to have this structure

Warning: Pay attention to the port numbers in WG2 and COUPLER2. Make sure they are mirrored to keep the circuit entirely unidirectional.

If the text with parameters bothers you, you can hide it by double clicking a device and un-checking the Show box in Sims.Params. To change a parameter after it is hidden, just access the same window.

To wire the components, you can click the small circle in their ports, and click again to choose the wiring destination. Alternatively, you can just hover on top of the starting point and press W. If a wire does not connect anywhere, you can double-click to finish its placement. Wire the circuit so it looks like this

In the same way as the netlist, you can declare variables with .param. For this, click the Add Text in the right toolbar or press T in your keyboard. Paste the following inside the text box and place it anywhere in the scheme.

* Device parameters
.param length=1e-3
.param neff=2.44283
.param ng=4.05284
.param att=1
.param d=0
.param wl1=1549.600e-9

Now, edit the waveguide parameters to include these values, using the curly bracket notation that we mentioned in the first tutorial (length={length} att={att} …). In VLSRC1, edit it to generate a 1W pulse from 0.1ns to 1ns at the wavelength wl1, using values=[[0.1e-9,1,{wl1}],[1e-9,0,{wl1}]].

We need to include the simulation directives. Using the Add Text tool, include

* Options and simulation directive
.options traceall=1 timescale=-15
.tran

KiCad automatically label the nets connecting components, but you can include your own labels to help debugging a circuit. To do it, either click on the Add a net label icon on the right toolbar or press L in your keyboard. After everything, this is how your circuit should look

To run this circuit in SPECS, you have to export its netlist. To do so, click on File->Export->Netlist. A faster way to get there is to hold ALT then press F E N in this order, or alternatively create your own hotkey clicking on Preferences->Preferences and on the Hotkeystab search for netlist and edit your own hotkey (we recommend CTRL+SHIFT+N.

When the Export Netlist window opens up, select the SPICE tab and click on Export Netlist. It will ask you where to save and the file name. Choose them as you see fit.

Open the text file that you just exported. It should look something like this

.title KiCad schematic
* Device parameters
.param length=1e-3
.param neff=2.44283
.param ng=4.05284
.param att=1
.param d=0
.param wl1=1549.600e-9
* Options and simulation directive
.options traceall=0 timescale=-15
.tran
COUPLER2 Net-_COUPLER2-Pad1_ /add Net-_COUPLER2-Pad3_ /drop k=0.5
PROBE1 /out 
WG1 Net-_COUPLER1-Pad4_ Net-_COUPLER2-Pad1_ length={length} att={att} neff={neff} ng={ng} d={d}
VLSRC1 /in values=[[0.1e-9,1,{wl1}],[1e-9,0,{wl1}]]
WG2 Net-_COUPLER2-Pad3_ Net-_COUPLER1-Pad2_ length={length} att={att} neff={neff} ng={ng} d={d}
COUPLER1 /in Net-_COUPLER1-Pad2_ /out Net-_COUPLER1-Pad4_ k=0.5
PROBE2 /drop 
.end

Now that your circuit is a netlist, you can simulate it with your preferred way, either on the command-line tool or in python, according to the previous tutorials.

4.3 Creating subcircuits

TODO

5 Reference

5.1 Components

5.1.1 Waveguide (WG)

Instantiation: wg1 1 2 length=val att=val neff=val ng=val d=val

  • 1 is the input terminal, 2 is the output terminal
  • length is the length of the waveguide in meters
  • att is the attenuation of the waveguide in dB/cm
  • neff is the effective refractive index at 1550nm
  • ng is the group index at 1550nm
  • d is the dispersion in s/m/m at 1550nm

WG is the only component that has length. All other components have an ideal behavior, such that if you want, for example, a directional coupler with delay and mismatching between arms, you can use COUPLER and multiple WG modules.

Dispersion is accounted for in phase and time delay, but SPECS does not account for the pulse broadening effect.

5.1.2 Continuous-wave source (CWSRC)

Instantiation: cwsrc1 1 power=val phi=val wl=val

  • 1 is the output terminal
  • power is the output power in watts
  • phi is the output phase in degrees
  • wl is the supporting wavelength

CWSRC outputs a continuous wave, assumed to always be on. If you want a source that turns on in a specific time, use VLSRC.

5.1.3 Value source (VLSRC)

Instantiation: vlsrc1 1 values=[[t0,p0,wl0],[t1,p1,wl1],...] Alternative: vlsrc 1 values="file.csv"

  • 1 is the output terminal
  • t0, t1, … is the time in seconds of each sample in the list
  • p0, p1, … is the power in watts of each sample in the list
  • wl0, wl1, … is the supporting wavelength for each sample in the list

This is the main source for transient simulations. The first way of using it is to list all values that it assumes individually, with power, time, and wavelength.

Alternatively, you can create a csv file containing a table of values. Make sure that you specify the correct path to the file when including it in the netlist.

t p wl
0 1 1550e-9
1e-9 0 1550e-9
`file.csv`

5.1.4 Electrical value source (EVLSRC)

Instantiation: evlsrc1 1 values=[[t0,v0],[t1,v1],...] Alternative: evlsrc1 1 values="file.csv"

  • 1 is the output terminal
  • t0,t1, … is the time in seconds of each sample
  • v0, v1, … is the voltage in volts of each sample

This source output electrical values, that can be used at the moment as inputs to the phase-shifter’s electrical port. Be careful not to mix electrical and optical ports.

The alternative usage works in the same way as VLSRC, but the columns are t, v.

5.1.5 Directional coupler (COUPLER)

Instantiation: coupler1 1 2 3 4 k=val loss=val Alternative: coupler1 1 2 3 4 kpower=val loss=val

  • 1,2 are input terminals, 3,4 are output terminals
  • k is the cross coupling coefficient for field
  • kpower is the cross coupling coefficient for power
  • loss is the insertion loss of the device in dB

5.1.6 Splitter (SPLITTER)

Instantiation: splitter1 1 2 3 il=val ratio=val

  • 1 is an input terminal, 2,3 are output terminals
  • il is the insertion loss of the device in dB
  • ratio is the splitting ratio between 0 and 1

Even though this device is physically symmetrical, please take care when deciding to use it or the combiner.

5.1.7 Combiner (MERGER)

Instantiation: merger1 1 2 3 il=val

  • 1,2 are input terminals, 3 is an output terminal
  • il is the insertion loss of the device in dB
  • loss is the insertion loss of the device in dB

Even though this device is physically symmetrical, please take care when deciding to use it or the splitter.

5.1.8 Phase shifter (PSHIFT)

Instantiation: pshift1 1 2 3 att=val, gain=val

  • 1,2 are the optical input and output, 3 is the electrical input
  • att is the device attenuation in dB
  • gain is the phase shifting scale in rad/volts

A phase shifter that will immediately trigger a shift of the light going through it when an electrical signal is received. Take care with the port types, as electrical and optical signals cannot mix.

5.1.9 Photodiode (PDET)

TODO: update the photodetector netlist syntax and include its documentation

5.1.10 Optical probe (PROBE)

Instantiation: probe1 1 - 1 is the input terminal - The net connected to the probe will be saved in the output .vcd file, with the name chosen during execution.

5.1.11 Optical multi-wavelength probe (MLPROBE)

Instantiation: mlprobe1 1 wl=[wl0,wl1,...] - 1 is the input terminal - wl0, wl1, … are the wavelengths that will be tracked by the probe

Be careful not to use this probe during frequency-domain simulations, as it separates the wavelengths in different vectors.

5.2 Syntax and simulation options

5.2.0.1 Simulation directives

  • .op Finds the operation point of the circuit, before any value-source is activated. Useful when there are CWSRC present.
  • .tran T Performs a transient time-domain simulation for T seconds. If T is not determined, the simulation will run until all events are resolved.
  • .dc /cwsrc1/WL wl0 wl1 dwl Performs a sequence of .op operations, sweeping between a specific parameter. In this case, the WL value of CWSRC1 source. The parameter varies between wl0 and wl1 with the step of dwl.

5.2.0.2 Simulation options

To use the following options, you have to include the command

.options option1=val1 option2=val2 ...

in your netlist, where the options and their accepted values are listed below.

  • abstol The absolute tolerance of the simulator. Absolute variations of field that are smaller than abstol are not considered. Accepted values: any positive float. Default value: 10nV/m
  • reltol The relative tolerance of the simulator. Relative variations of field smaller than reltol are not considered. Accepted values: any positive float. Default value: 0.01%
  • timescale Sets the smallest time resolution in the simulator to 10timescale. All the times involved in the simulator will be matched to a grid defined by timescale. That does not mean that they will be sampled at that rate, but if an event has to happen in a time smaller than timescale allows, it will happen in a later moment. We have thoroughly tested our engine to make sure this entails minimal precision losses. Accepted values: integers between 0 and -15 Default value: -13
  • traceall Defines if all optical nets will be traced (saved) in the .vcd file or not. If it is off, probe components need to be included in the relevant points of the circuit. For large circuits, having this option on will marginally affect simulation time. Accepted values: 0 or 1 Default value: 1

5.2.0.3 Declaring parameters

You can declare a parameter in the netlist using the .param directive. For example:

.param var=1e-6

You will be able to use this value in the entire circuit by making reference to it. For instance, wg1 in out length={var} ng=4 neff=2

5.2.0.4 Handling multiple files

You can separate a netlist in multiple files. However, they should be linked together internally otherwise SPECS will try to simulate the called netlist independently.

To do so, a netlist must use the .include directive to call for another. Therefore you will have one main netlist containing multiple include calls to others, that may also have similar calls, if needed. For example:

* Title of main netlist
* ...
.include netlist1.cir
* ...
.end
* end of main netlist
main_netlist.cir
.param var1=1
.param var2=2
.param var3=3
netlist1.cir

When running, SPECS will flatten the netlists. The effect will be similar to writing all the contents to the main netlist.

A good use-case is to have a file full of parameters that will be used throughout many different simulations. In this way you can be sure that all of them are using the same materials or devices.

5.2.0.5 2.x Miscellaneous

  • You can use the + character to break lines and make your netlist more readable Ex: wg1 in out length=1e-6 ng=4 neff=2 can become wg1 in out length=1e-6 +ng=4 neff=2``

  • We have pre-programmed parameters that you can use in the netlist. Currently {c} the speed of light in m/s and {pi}.