Running Your First Script

Understanding SUT Parameters

We first briefly explain the parameters of your system-under-test (SUT). For microrings:

  • ring_wavelength: resonant wavelength of the microring (post-fabrication)

  • fsr: free spectral range of the microring

  • tuning_range: tuning range of the microring

For now, we assume the red-shift tuning mechanism (i.e., tuning range is single-sided) and ignore the fsr variation by dispersion. Since we only consider the wavelength-domain, any coupling conditions or power levels are not included as parameters.

For lasers:

  • laser_wavelength: target laser grid wavelengths

A unique system-level parameter we introduce here is initial/target lane order which defines the spectral ordering of microrings. We assume a simple bus topology with a single shared waveguide bus, and microrings are indexed from 0 to N-1 counted from the light input side.

  • initial_lane_order: spectral ordering of microrings at the beginning of the simulation (== post-fabrication)

  • target_lane_order: spectral ordering of microrings at the end of the simulation (== post-tuning)

For example, if you have 4 microrings and the initial lane order is [0, 1, 2, 3], then the initial wavelengths are in the monotonic order from the input side. If the target lane order is [3, 2, 1, 0], then the final wavelengths are in the reverse order.

Understanding Run Script

After defining the parameters, instantiate the system under test (sut) object and the laser grid object. Note that the system under test should be instantiated with the arbiter algorithm class, which implements the algorithm of interest. Then, calling the SystemUnderTest.run_lock_sequence() will run the experiment at the specified verbosity level.

See examples/run_arbiter.py for the full script.

import logging

from wdmsim.models.system_under_test import SystemUnderTest
from wdmsim.models.laser_grid import LaserGrid
from wdmsim.utils.logger import setup_logger
from examples.example_arbiter import SimpleArbiter

logger = logging.getLogger(__name__)

# Define the parameters for the devices and the system
simple_ring_params = {"fsr": 8.96e-9, "tuning_range": 4.48e-9}

channel_spacing = 2.24e-9
resonance_wavelengths_postfab = [
    1300e-9 - 2 * channel_spacing,
    1300e-9 - 1 * channel_spacing + 0.1e-9,
    1300e-9 + 0 * channel_spacing,
    1300e-9 + 1 * channel_spacing - 0.1e-9,
]

laser_wavelengths = [
    1310e-9 - 2 * channel_spacing,
    1310e-9 - 1 * channel_spacing,
    1310e-9 + 0 * channel_spacing,
    1310e-9 + 1 * channel_spacing,
]

init_lane_order = [i for i in range(4)]
target_lane_order = init_lane_order


if __name__ == "__main__":

    # define verbosity
    setup_logger(log_fpath=None, verbose=True)

    # Build the system under test
    dwdm_under_test = SystemUnderTest.construct_slices_and_arbiter(
        ring_row_params = [simple_ring_params] * 4,
        ring_wavelengths = resonance_wavelengths_postfab,
        init_lane_order = init_lane_order,
        arbiter_cls = SimpleArbiter,
        tgt_lane_order = target_lane_order,
    )

    # Define the target laser grid
    laser_target = LaserGrid.from_wavelengths(laser_wavelengths)

    # Run the lock sequence
    dwdm_under_test.run_lock_sequence(
        laser_grid=laser_target,
        plot_snapshot=False,
        plot_statistics=False,
    )

Verbose flag is set to True to print the detailed log messages in the terminal (setup_logger()).

Understanding Arbiter Definition

We provide the example arbiter definition under examples directory.

# example_arbiter.py

from wdmsim.arbiter.base_arbiter import BaseArbiter
from wdmsim.arbiter.arbiter_factory import arbiter_factory
from wdmsim.arbiter.arbiter_instr import SearchInst, LockInst, UnlockInst

# register the arbiter class to the factory
# the register_str_id is the string id that will be used to refer to this arbiter in the CLI
@arbiter_factory(register_str_id="example_one_by_one")
class SimpleArbiter(BaseArbiter):
    # override algorithm function to implement the arbiter algorithm
    def algorithm(self):
        # set lock sequence before start running an algorithm
        if self.target_lane_order:
            slice_lock_sequence = [self.target_lane_order.index(lane) for lane in self.target_lane_order]
        else:
            slice_lock_sequence = list(range(self.num_slices))

        # loop through the lock sequence and issue LockInst to each slice
        # for each iteration, yield to update the lock-step
        for rx_idx in slice_lock_sequence:
            LockInst(self, rx_idx, "least_significant", 0).run()
            if self.check_lock_done(rx_idx) and not self.check_zero_lock(rx_idx):
                yield
            else:
                self.lock_error_state = True
                yield

        # if the sequence is done and not in error state, set end_state to True
        self.end_state = True
        yield

As explained in the previous section, the arbiter class subclasses BaseArbiter and overrides the algorithm function to implement the algorithm. Also, if you are implementing your own algorithm, then it should be registered to the arbiter factory using the decorator arbiter_factory() with the register_str_id argument. It is then usable by the CLI (which is explained in the next section), and the string id is used to refer to the arbiter in the CLI.

In your python code, you can instantiate the arbiter class and feed into the system under test object constructor as shown in the run script.

Run Your First Script

Now, run the script:

$ cd <repo>/examples
$ python run_arbiter.py

And it will display the following message:

[wdmsim.models.tuner] sweep range: [[1259.68, 1264.16], [1268.64, 1273.12], [1277.6, 1282.08], [1286.56, 1291.04], [1295.52, 1300.0], [1304.48, 1308.96], [1313.44, 1317.92], [1322.4, 1326.88], [1331.36, 1335.84]]
[wdmsim.models.tuner] incoming wavelengths [1305.52, 1307.76, 1310.0, 1312.24]
[wdmsim.models.tuner] sweep range: [[1262.02, 1266.5], [1270.98, 1275.46], [1279.94, 1284.42], [1288.9, 1293.38], [1297.86, 1302.34], [1306.82, 1311.3], [1315.78, 1320.26], [1324.74, 1329.22], [1333.7, 1338.18]]
[wdmsim.models.tuner] incoming wavelengths [1305.52, 1307.76, 1310.0, 1312.24]
[wdmsim.models.tuner] sweep range: [[1264.16, 1268.64], [1273.12, 1277.6], [1282.08, 1286.56], [1291.04, 1295.52], [1300.0, 1304.48], [1308.96, 1313.44], [1317.92, 1322.4], [1326.88, 1331.36], [1335.84, 1340.32]]
[wdmsim.models.tuner] incoming wavelengths [1305.52, 1307.76, 1310.0, 1312.24]
[wdmsim.models.tuner] sweep range: [[1266.3, 1270.78], [1275.26, 1279.74], [1284.22, 1288.7], [1293.18, 1297.66], [1302.14, 1306.62], [1311.1, 1315.58], [1320.06, 1324.54], [1329.02, 1333.5], [1337.98, 1342.46]]
[wdmsim.models.tuner] incoming wavelengths [1305.52, 1307.76, 1310.0, 1312.24]
[wdmsim.models.system_under_test] Target Ring->Laser ordering
R0 -> L0, R1 -> L1, R2 -> L2, R3 -> L3
[wdmsim.models.system_under_test] Target Laser->Ring ordering
L0 -> R0, L1 -> R1, L2 -> R2, L3 -> R3
[wdmsim.models.system_under_test] Search Table
+----+---------+--------+--------+---------+--------+--------+---------+--------+--------+---------+--------+--------+
|    |    R0/W |   R0/C |   R0/L |    R1/W |   R1/C |   R1/L |    R2/W |   R2/C |   R2/L |    R3/W |   R3/C |   R3/L |
+====+=========+========+========+=========+========+========+=========+========+========+=========+========+========+
|  0 | 1305.52 |     59 |      - | 1307.76 |     53 |      - | 1310.00 |     59 |      - | 1312.24 |     65 |      - |
+----+---------+--------+--------+---------+--------+--------+---------+--------+--------+---------+--------+--------+
|  1 | 1307.76 |    187 |      - | 1310.00 |    181 |      - | 1312.24 |    187 |      - | 1305.52 |    193 |      - |
+----+---------+--------+--------+---------+--------+--------+---------+--------+--------+---------+--------+--------+
[wdmsim.models.tuner] sweep range: [[1259.68, 1264.16], [1268.64, 1273.12], [1277.6, 1282.08], [1286.56, 1291.04], [1295.52, 1300.0], [1304.48, 1308.96], [1313.44, 1317.92], [1322.4, 1326.88], [1331.36, 1335.84]]
[wdmsim.models.tuner] incoming wavelengths [1305.52, 1307.76, 1310.0, 1312.24]
[wdmsim.models.tuner] sweep range: [[1262.02, 1266.5], [1270.98, 1275.46], [1279.94, 1284.42], [1288.9, 1293.38], [1297.86, 1302.34], [1306.82, 1311.3], [1315.78, 1320.26], [1324.74, 1329.22], [1333.7, 1338.18]]
[wdmsim.models.tuner] incoming wavelengths [1307.76, 1310.0, 1312.24]
[wdmsim.models.tuner] sweep range: [[1264.16, 1268.64], [1273.12, 1277.6], [1282.08, 1286.56], [1291.04, 1295.52], [1300.0, 1304.48], [1308.96, 1313.44], [1317.92, 1322.4], [1326.88, 1331.36], [1335.84, 1340.32]]
[wdmsim.models.tuner] incoming wavelengths [1310.0, 1312.24]
[wdmsim.models.tuner] sweep range: [[1266.3, 1270.78], [1275.26, 1279.74], [1284.22, 1288.7], [1293.18, 1297.66], [1302.14, 1306.62], [1311.1, 1315.58], [1320.06, 1324.54], [1329.02, 1333.5], [1337.98, 1342.46]]
[wdmsim.models.tuner] incoming wavelengths [1312.24]
[wdmsim.models.system_under_test] Target Ring->Laser ordering
R0 -> L0, R1 -> L1, R2 -> L2, R3 -> L3
[wdmsim.models.system_under_test] Target Laser->Ring ordering
L0 -> R0, L1 -> R1, L2 -> R2, L3 -> R3
[wdmsim.models.system_under_test] Lock Allocation Table
+----+---------+--------+--------+---------+--------+--------+---------+--------+--------+---------+--------+--------+
|    |    R0/W |   R0/C |   R0/L |    R1/W |   R1/C |   R1/L |    R2/W |   R2/C |   R2/L |    R3/W |   R3/C |   R3/L |
+====+=========+========+========+=========+========+========+=========+========+========+=========+========+========+
|  0 | 1305.52 |     59 |      L | 1307.76 |     53 |      L | 1310.00 |     59 |      L | 1312.24 |     65 |      L |
+----+---------+--------+--------+---------+--------+--------+---------+--------+--------+---------+--------+--------+
|  1 | 1307.76 |    187 |      - | 1310.00 |    181 |      - | 1312.24 |    187 |      - | 1305.52 |    193 |      - |
+----+---------+--------+--------+---------+--------+--------+---------+--------+--------+---------+--------+--------+
[wdmsim.models.system_under_test] lock_wavelengths: [1305.52, 1307.76, 1310.0, 1312.24]
[wdmsim.models.system_under_test] System is locked: 0, return with status code 0

[wdmsim.models.system_under_test] Arbiter: SimpleArbiter
[wdmsim.models.system_under_test]
 _       ___    ____  _  __  ____   _   _   ____   ____  _____  ____   ____
| |     / _ \  / ___|| |/ / / ___| | | | | / ___| / ___|| ____|/ ___| / ___|
| |    | | | || |    | ' /  \___ \ | | | || |    | |    |  _|  \___ \ \___ \
| |___ | |_| || |___ | . \   ___) || |_| || |___ | |___ | |___  ___) | ___) |
|_____| \___/  \____||_|\_\ |____/  \___/  \____| \____||_____||____/ |____/

Log message will display:

  • Sweep range and incoming wavelengths for each microring (from the first to the last in the bus)

  • Target ring-to-laser and laser-to-ring ordering

  • Microring search table and lock allocation table

    • Visible wavelengths within the tuning range and the incoming wavelengths (W)

    • Corresponding tuner codes (C)

    • Microring lock status (L)

What’s Next?

In the next section, we will explain a batch simulation mode which is one of the powerful features of the WDMSim.