From befb0f50629482f3c8db4054ad0cbaff07dd3fb8 Mon Sep 17 00:00:00 2001 From: Dario Quintero Date: Mon, 24 Jul 2023 12:33:59 +0100 Subject: [PATCH] FIX: Docs --- .github/workflows/code_coverage.yaml | 8 +- docs/autoapi/index.rst | 11 + docs/autoapi/piel/cli/index.rst | 27 + docs/autoapi/piel/components/index.rst | 4 + docs/autoapi/piel/config/index.rst | 17 + docs/autoapi/piel/defaults/index.rst | 14 + docs/autoapi/piel/file_conversion/index.rst | 26 + docs/autoapi/piel/file_system/index.rst | 197 +++ docs/autoapi/piel/index.rst | 1364 +++++++++++++++++ .../piel/integration/cocotb_sax/index.rst | 9 + .../gdsfactory_hdl21/conversion/index.rst | 68 + .../gdsfactory_hdl21/core/index.rst | 246 +++ .../integration/gdsfactory_hdl21/index.rst | 106 ++ .../gdsfactory_hdl21/utils/index.rst | 29 + .../integration/gdsfactory_openlane/index.rst | 45 + docs/autoapi/piel/integration/index.rst | 247 +++ .../piel/integration/sax_qutip/index.rst | 55 + .../piel/integration/sax_thewalrus/index.rst | 52 + .../integration/thewalrus_qutip/index.rst | 51 + .../piel/models/frequency/all/index.rst | 28 + .../piel/models/frequency/defaults/index.rst | 28 + .../models/frequency/electrical/index.rst | 4 + .../frequency/electro_optic/ideal/index.rst | 20 + .../models/frequency/electro_optic/index.rst | 13 + .../models/frequency/electronic/index.rst | 4 + docs/autoapi/piel/models/frequency/index.rst | 76 + .../frequency/opto_electronic/index.rst | 4 + .../photonic/coupler_simple/index.rst | 25 + .../directional_coupler_length/index.rst | 25 + .../directional_coupler_real/index.rst | 8 + .../directional_coupler_simple/index.rst | 25 + .../photonic/grating_coupler/index.rst | 25 + .../piel/models/frequency/photonic/index.rst | 68 + .../frequency/photonic/mmi1x2/index.rst | 25 + .../frequency/photonic/mmi2x2/index.rst | 25 + .../photonic/straight_waveguide/index.rst | 33 + .../piel/models/frequency/utils/index.rst | 28 + docs/autoapi/piel/models/index.rst | 25 + .../piel/models/logic/electrical/index.rst | 4 + .../piel/models/logic/electro_optic/index.rst | 68 + .../electro_optic/signal_mapping/index.rst | 80 + .../piel/models/logic/electronic/index.rst | 4 + docs/autoapi/piel/models/logic/index.rst | 17 + .../models/logic/opto_electronic/index.rst | 4 + .../piel/models/logic/photonic/index.rst | 4 + .../physical/electrical/cable/index.rst | 4 + .../piel/models/physical/electrical/index.rst | 13 + .../electro_optic/basic_heater/index.rst | 22 + .../models/physical/electro_optic/index.rst | 13 + .../physical/electronic/capacitor/index.rst | 51 + .../physical/electronic/defaults/index.rst | 28 + .../piel/models/physical/electronic/index.rst | 67 + .../physical/electronic/resistor/index.rst | 33 + .../physical/electronic/straight/index.rst | 36 + .../physical/electronic/taper/index.rst | 34 + .../physical/electronic/via_stack/index.rst | 34 + .../piel/models/physical/geometry/index.rst | 28 + docs/autoapi/piel/models/physical/index.rst | 66 + .../models/physical/opto_electronic/index.rst | 4 + .../piel/models/physical/photonic/index.rst | 4 + .../piel/models/physical/thermal/index.rst | 20 + .../piel/models/physical/units/index.rst | 30 + .../models/transient/electrical/index.rst | 4 + .../models/transient/electro_optic/index.rst | 4 + .../models/transient/electronic/index.rst | 4 + docs/autoapi/piel/models/transient/index.rst | 17 + .../transient/opto_electronic/index.rst | 4 + .../piel/models/transient/photonic/index.rst | 4 + docs/autoapi/piel/models/utils/index.rst | 4 + docs/autoapi/piel/parametric/index.rst | 66 + docs/autoapi/piel/project_structure/index.rst | 44 + docs/autoapi/piel/tools/cocotb/core/index.rst | 118 ++ docs/autoapi/piel/tools/cocotb/data/index.rst | 61 + docs/autoapi/piel/tools/cocotb/index.rst | 146 ++ docs/autoapi/piel/tools/gdsfactory/index.rst | 100 ++ .../piel/tools/gdsfactory/netlist/index.rst | 91 ++ .../piel/tools/hdl21/circuit/index.rst | 22 + docs/autoapi/piel/tools/hdl21/index.rst | 33 + .../piel/tools/hdl21/simulator/index.rst | 22 + docs/autoapi/piel/tools/hdl21/units/index.rst | 39 + docs/autoapi/piel/tools/index.rst | 873 +++++++++++ docs/autoapi/piel/tools/openlane/index.rst | 468 ++++++ .../piel/tools/openlane/migrate/index.rst | 40 + .../piel/tools/openlane/parse/index.rst | 287 ++++ .../tools/openlane/parse/sta_rpt/index.rst | 167 ++ .../piel/tools/openlane/parse/utils/index.rst | 70 + .../piel/tools/openlane/utils/index.rst | 26 + docs/autoapi/piel/tools/openlane/v1/index.rst | 157 ++ docs/autoapi/piel/tools/openlane/v2/index.rst | 29 + docs/autoapi/piel/tools/qutip/fock/index.rst | 54 + docs/autoapi/piel/tools/qutip/index.rst | 106 ++ .../piel/tools/qutip/unitary/index.rst | 57 + docs/autoapi/piel/tools/sax/index.rst | 168 ++ docs/autoapi/piel/tools/sax/utils/index.rst | 164 ++ docs/autoapi/piel/tools/thewalrus/index.rst | 45 + .../piel/tools/thewalrus/operations/index.rst | 36 + .../piel/visual/auto_plot_multiple/index.rst | 41 + .../piel/visual/data_conversion/index.rst | 70 + docs/autoapi/piel/visual/index.rst | 105 ++ 99 files changed, 7475 insertions(+), 4 deletions(-) create mode 100644 docs/autoapi/index.rst create mode 100644 docs/autoapi/piel/cli/index.rst create mode 100644 docs/autoapi/piel/components/index.rst create mode 100644 docs/autoapi/piel/config/index.rst create mode 100644 docs/autoapi/piel/defaults/index.rst create mode 100644 docs/autoapi/piel/file_conversion/index.rst create mode 100644 docs/autoapi/piel/file_system/index.rst create mode 100644 docs/autoapi/piel/index.rst create mode 100644 docs/autoapi/piel/integration/cocotb_sax/index.rst create mode 100644 docs/autoapi/piel/integration/gdsfactory_hdl21/conversion/index.rst create mode 100644 docs/autoapi/piel/integration/gdsfactory_hdl21/core/index.rst create mode 100644 docs/autoapi/piel/integration/gdsfactory_hdl21/index.rst create mode 100644 docs/autoapi/piel/integration/gdsfactory_hdl21/utils/index.rst create mode 100644 docs/autoapi/piel/integration/gdsfactory_openlane/index.rst create mode 100644 docs/autoapi/piel/integration/index.rst create mode 100644 docs/autoapi/piel/integration/sax_qutip/index.rst create mode 100644 docs/autoapi/piel/integration/sax_thewalrus/index.rst create mode 100644 docs/autoapi/piel/integration/thewalrus_qutip/index.rst create mode 100644 docs/autoapi/piel/models/frequency/all/index.rst create mode 100644 docs/autoapi/piel/models/frequency/defaults/index.rst create mode 100644 docs/autoapi/piel/models/frequency/electrical/index.rst create mode 100644 docs/autoapi/piel/models/frequency/electro_optic/ideal/index.rst create mode 100644 docs/autoapi/piel/models/frequency/electro_optic/index.rst create mode 100644 docs/autoapi/piel/models/frequency/electronic/index.rst create mode 100644 docs/autoapi/piel/models/frequency/index.rst create mode 100644 docs/autoapi/piel/models/frequency/opto_electronic/index.rst create mode 100644 docs/autoapi/piel/models/frequency/photonic/coupler_simple/index.rst create mode 100644 docs/autoapi/piel/models/frequency/photonic/directional_coupler_length/index.rst create mode 100644 docs/autoapi/piel/models/frequency/photonic/directional_coupler_real/index.rst create mode 100644 docs/autoapi/piel/models/frequency/photonic/directional_coupler_simple/index.rst create mode 100644 docs/autoapi/piel/models/frequency/photonic/grating_coupler/index.rst create mode 100644 docs/autoapi/piel/models/frequency/photonic/index.rst create mode 100644 docs/autoapi/piel/models/frequency/photonic/mmi1x2/index.rst create mode 100644 docs/autoapi/piel/models/frequency/photonic/mmi2x2/index.rst create mode 100644 docs/autoapi/piel/models/frequency/photonic/straight_waveguide/index.rst create mode 100644 docs/autoapi/piel/models/frequency/utils/index.rst create mode 100644 docs/autoapi/piel/models/index.rst create mode 100644 docs/autoapi/piel/models/logic/electrical/index.rst create mode 100644 docs/autoapi/piel/models/logic/electro_optic/index.rst create mode 100644 docs/autoapi/piel/models/logic/electro_optic/signal_mapping/index.rst create mode 100644 docs/autoapi/piel/models/logic/electronic/index.rst create mode 100644 docs/autoapi/piel/models/logic/index.rst create mode 100644 docs/autoapi/piel/models/logic/opto_electronic/index.rst create mode 100644 docs/autoapi/piel/models/logic/photonic/index.rst create mode 100644 docs/autoapi/piel/models/physical/electrical/cable/index.rst create mode 100644 docs/autoapi/piel/models/physical/electrical/index.rst create mode 100644 docs/autoapi/piel/models/physical/electro_optic/basic_heater/index.rst create mode 100644 docs/autoapi/piel/models/physical/electro_optic/index.rst create mode 100644 docs/autoapi/piel/models/physical/electronic/capacitor/index.rst create mode 100644 docs/autoapi/piel/models/physical/electronic/defaults/index.rst create mode 100644 docs/autoapi/piel/models/physical/electronic/index.rst create mode 100644 docs/autoapi/piel/models/physical/electronic/resistor/index.rst create mode 100644 docs/autoapi/piel/models/physical/electronic/straight/index.rst create mode 100644 docs/autoapi/piel/models/physical/electronic/taper/index.rst create mode 100644 docs/autoapi/piel/models/physical/electronic/via_stack/index.rst create mode 100644 docs/autoapi/piel/models/physical/geometry/index.rst create mode 100644 docs/autoapi/piel/models/physical/index.rst create mode 100644 docs/autoapi/piel/models/physical/opto_electronic/index.rst create mode 100644 docs/autoapi/piel/models/physical/photonic/index.rst create mode 100644 docs/autoapi/piel/models/physical/thermal/index.rst create mode 100644 docs/autoapi/piel/models/physical/units/index.rst create mode 100644 docs/autoapi/piel/models/transient/electrical/index.rst create mode 100644 docs/autoapi/piel/models/transient/electro_optic/index.rst create mode 100644 docs/autoapi/piel/models/transient/electronic/index.rst create mode 100644 docs/autoapi/piel/models/transient/index.rst create mode 100644 docs/autoapi/piel/models/transient/opto_electronic/index.rst create mode 100644 docs/autoapi/piel/models/transient/photonic/index.rst create mode 100644 docs/autoapi/piel/models/utils/index.rst create mode 100644 docs/autoapi/piel/parametric/index.rst create mode 100644 docs/autoapi/piel/project_structure/index.rst create mode 100644 docs/autoapi/piel/tools/cocotb/core/index.rst create mode 100644 docs/autoapi/piel/tools/cocotb/data/index.rst create mode 100644 docs/autoapi/piel/tools/cocotb/index.rst create mode 100644 docs/autoapi/piel/tools/gdsfactory/index.rst create mode 100644 docs/autoapi/piel/tools/gdsfactory/netlist/index.rst create mode 100644 docs/autoapi/piel/tools/hdl21/circuit/index.rst create mode 100644 docs/autoapi/piel/tools/hdl21/index.rst create mode 100644 docs/autoapi/piel/tools/hdl21/simulator/index.rst create mode 100644 docs/autoapi/piel/tools/hdl21/units/index.rst create mode 100644 docs/autoapi/piel/tools/index.rst create mode 100644 docs/autoapi/piel/tools/openlane/index.rst create mode 100644 docs/autoapi/piel/tools/openlane/migrate/index.rst create mode 100644 docs/autoapi/piel/tools/openlane/parse/index.rst create mode 100644 docs/autoapi/piel/tools/openlane/parse/sta_rpt/index.rst create mode 100644 docs/autoapi/piel/tools/openlane/parse/utils/index.rst create mode 100644 docs/autoapi/piel/tools/openlane/utils/index.rst create mode 100644 docs/autoapi/piel/tools/openlane/v1/index.rst create mode 100644 docs/autoapi/piel/tools/openlane/v2/index.rst create mode 100644 docs/autoapi/piel/tools/qutip/fock/index.rst create mode 100644 docs/autoapi/piel/tools/qutip/index.rst create mode 100644 docs/autoapi/piel/tools/qutip/unitary/index.rst create mode 100644 docs/autoapi/piel/tools/sax/index.rst create mode 100644 docs/autoapi/piel/tools/sax/utils/index.rst create mode 100644 docs/autoapi/piel/tools/thewalrus/index.rst create mode 100644 docs/autoapi/piel/tools/thewalrus/operations/index.rst create mode 100644 docs/autoapi/piel/visual/auto_plot_multiple/index.rst create mode 100644 docs/autoapi/piel/visual/data_conversion/index.rst create mode 100644 docs/autoapi/piel/visual/index.rst diff --git a/.github/workflows/code_coverage.yaml b/.github/workflows/code_coverage.yaml index e420c7d4..ef43a8a7 100644 --- a/.github/workflows/code_coverage.yaml +++ b/.github/workflows/code_coverage.yaml @@ -1,4 +1,4 @@ -- name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v3 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} +name: Upload coverage reports to Codecov +uses: codecov/codecov-action@v3 +env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/docs/autoapi/index.rst b/docs/autoapi/index.rst new file mode 100644 index 00000000..7de4a30e --- /dev/null +++ b/docs/autoapi/index.rst @@ -0,0 +1,11 @@ +API Reference +============= + +This page contains auto-generated API reference documentation [#f1]_. + +.. toctree:: + :titlesonly: + + /autoapi/piel/index + +.. [#f1] Created with `sphinx-autoapi `_ diff --git a/docs/autoapi/piel/cli/index.rst b/docs/autoapi/piel/cli/index.rst new file mode 100644 index 00000000..33fb8cfc --- /dev/null +++ b/docs/autoapi/piel/cli/index.rst @@ -0,0 +1,27 @@ +:py:mod:`piel.cli` +================== + +.. py:module:: piel.cli + +.. autoapi-nested-parse:: + + Console script for piel. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.cli.main + + + +.. py:function:: main(args=None) + + Console script for piel. diff --git a/docs/autoapi/piel/components/index.rst b/docs/autoapi/piel/components/index.rst new file mode 100644 index 00000000..37bb8a88 --- /dev/null +++ b/docs/autoapi/piel/components/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.components` +========================= + +.. py:module:: piel.components diff --git a/docs/autoapi/piel/config/index.rst b/docs/autoapi/piel/config/index.rst new file mode 100644 index 00000000..41ea732b --- /dev/null +++ b/docs/autoapi/piel/config/index.rst @@ -0,0 +1,17 @@ +:py:mod:`piel.config` +===================== + +.. py:module:: piel.config + +.. autoapi-nested-parse:: + + We create a set of parameters that can be used throughout the project for optimisation. + + The numerical solver is jax and is imported throughout the module. + + + +Module Contents +--------------- + +.. py:data:: piel_path_types diff --git a/docs/autoapi/piel/defaults/index.rst b/docs/autoapi/piel/defaults/index.rst new file mode 100644 index 00000000..1fc23dc2 --- /dev/null +++ b/docs/autoapi/piel/defaults/index.rst @@ -0,0 +1,14 @@ +:py:mod:`piel.defaults` +======================= + +.. py:module:: piel.defaults + + +Module Contents +--------------- + +.. py:data:: test_spm_open_lane_configuration + + + +.. py:data:: example_open_lane_configuration diff --git a/docs/autoapi/piel/file_conversion/index.rst b/docs/autoapi/piel/file_conversion/index.rst new file mode 100644 index 00000000..626c9ad3 --- /dev/null +++ b/docs/autoapi/piel/file_conversion/index.rst @@ -0,0 +1,26 @@ +:py:mod:`piel.file_conversion` +============================== + +.. py:module:: piel.file_conversion + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.file_conversion.read_csv_to_pandas + piel.file_conversion.read_vcd_to_json + + + +.. py:function:: read_csv_to_pandas(file_path: piel.config.piel_path_types) + + This function returns a Pandas dataframe that contains all the simulation data outputted from the simulation run. + + +.. py:function:: read_vcd_to_json(file_path: piel.config.piel_path_types) diff --git a/docs/autoapi/piel/file_system/index.rst b/docs/autoapi/piel/file_system/index.rst new file mode 100644 index 00000000..45fed232 --- /dev/null +++ b/docs/autoapi/piel/file_system/index.rst @@ -0,0 +1,197 @@ +:py:mod:`piel.file_system` +========================== + +.. py:module:: piel.file_system + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.file_system.check_path_exists + piel.file_system.check_example_design + piel.file_system.copy_source_folder + piel.file_system.create_new_directory + piel.file_system.delete_path + piel.file_system.delete_path_list_in_directory + piel.file_system.get_files_recursively_in_directory + piel.file_system.permit_script_execution + piel.file_system.permit_directory_all + piel.file_system.read_json + piel.file_system.return_path + piel.file_system.run_script + piel.file_system.setup_example_design + piel.file_system.write_script + + + +.. py:function:: check_path_exists(path: piel.config.piel_path_types, raise_errors: bool = False) -> bool + + Checks if a directory exists. + + :param path: Input path. + :type path: piel_path_types + + :returns: True if directory exists. + :rtype: directory_exists(bool) + + +.. py:function:: check_example_design(design_name: str = 'simple_design', designs_directory: piel.config.piel_path_types | None = None) -> bool + + We copy the example simple_design from docs to the `/foss/designs` in the `iic-osic-tools` environment. + + :param design_name: Name of the design to check. + :type design_name: str + :param designs_directory: Directory that contains the DESIGNS environment flag. + :type designs_directory: piel_path_types + :param # TODO: + + :returns: None + + +.. py:function:: copy_source_folder(source_directory: piel.config.piel_path_types, target_directory: piel.config.piel_path_types) -> None + + Copies the files from a source_directory to a target_directory + + :param source_directory: Source directory. + :type source_directory: piel_path_types + :param target_directory: Target directory. + :type target_directory: piel_path_types + + :returns: None + + +.. py:function:: create_new_directory(directory_path: str | pathlib.Path) -> None + + Creates a new directory. + + If the parents of the target_directory do not exist, they will be created too. + + :param directory_path: Input path. + :type directory_path: str | pathlib.Path + + :returns: None + + +.. py:function:: delete_path(path: str | pathlib.Path) -> None + + Deletes a path. + + :param path: Input path. + :type path: str | pathlib.Path + + :returns: None + + +.. py:function:: delete_path_list_in_directory(directory_path: piel.config.piel_path_types, path_list: list, ignore_confirmation: bool = False, validate_individual: bool = False) -> None + + Deletes a list of files in a directory. + + :param directory_path: Input path. + :type directory_path: piel_path_types + :param path_list: List of files. + :type path_list: list + :param ignore_confirmation: Ignore confirmation. Default: False. + :type ignore_confirmation: bool + :param validate_individual: Validate individual files. Default: False. + :type validate_individual: bool + + :returns: None + + +.. py:function:: get_files_recursively_in_directory(path: piel.config.piel_path_types, extension: str = '*') + + Returns a list of files in a directory. + + :param path: Input path. + :type path: piel_path_types + :param extension: File extension. + :type extension: str + + :returns: List of files. + :rtype: file_list(list) + + +.. py:function:: permit_script_execution(script_path: piel.config.piel_path_types) -> None + + Permits the execution of a script. + + :param script_path: Script path. + :type script_path: piel_path_types + + :returns: None + + +.. py:function:: permit_directory_all(directory_path: piel.config.piel_path_types) -> None + + Permits a directory to be read, written and executed. Use with care as it can be a source for security issues. + + :param directory_path: Input path. + :type directory_path: piel_path_types + + :returns: None + + +.. py:function:: read_json(path: piel.config.piel_path_types) -> dict + + Reads a JSON file. + + :param path: Input path. + :type path: piel_path_types + + :returns: JSON data. + :rtype: json_data(dict) + + +.. py:function:: return_path(input_path: piel.config.piel_path_types) -> pathlib.Path + + Returns a pathlib.Path to be able to perform operations accordingly internally. + + This allows us to maintain compatibility between POSIX and Windows systems. + + :param input_path: Input path. + :type input_path: str + + :returns: Pathlib path. + :rtype: pathlib.Path + + +.. py:function:: run_script(script_path: piel.config.piel_path_types) -> None + + Runs a script on the filesystem `script_path`. + + :param script_path: Script path. + :type script_path: piel_path_types + + :returns: None + + +.. py:function:: setup_example_design(project_source: Literal[piel, openlane] = 'piel', example_name: str = 'simple_design') -> None + + We copy the example simple_design from docs to the `/foss/designs` in the `iic-osic-tools` environment. + + :param project_source: Source of the project. + :type project_source: str + :param example_name: Name of the example design. + :type example_name: str + + :returns: None + + +.. py:function:: write_script(directory_path: piel.config.piel_path_types, script: str, script_name: str) -> None + + Records a `script_name` in the `scripts` project directory. + + :param directory_path: Design directory. + :type directory_path: piel_path_types + :param script: Script to write. + :type script: str + :param script_name: Name of the script. + :type script_name: str + + :returns: None diff --git a/docs/autoapi/piel/index.rst b/docs/autoapi/piel/index.rst new file mode 100644 index 00000000..3bcc77b9 --- /dev/null +++ b/docs/autoapi/piel/index.rst @@ -0,0 +1,1364 @@ +:py:mod:`piel` +============== + +.. py:module:: piel + +.. autoapi-nested-parse:: + + Top-level package for piel. + + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + components/index.rst + integration/index.rst + models/index.rst + tools/index.rst + visual/index.rst + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + cli/index.rst + config/index.rst + defaults/index.rst + file_conversion/index.rst + file_system/index.rst + parametric/index.rst + project_structure/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.check_path_exists + piel.check_example_design + piel.copy_source_folder + piel.create_new_directory + piel.delete_path + piel.delete_path_list_in_directory + piel.get_files_recursively_in_directory + piel.permit_directory_all + piel.permit_script_execution + piel.setup_example_design + piel.read_json + piel.return_path + piel.run_script + piel.write_script + piel.create_gdsfactory_component_from_openlane + piel.gdsfactory_netlist_to_spice_netlist + piel.construct_hdl21_module + piel.convert_connections_to_tuples + piel.gdsfactory_netlist_with_hdl21_generators + piel.sax_circuit_permanent + piel.unitary_permanent + piel.sax_to_ideal_qutip_unitary + piel.fock_transition_probability_amplitude + piel.single_parameter_sweep + piel.multi_parameter_sweep + piel.check_cocotb_testbench_exists + piel.configure_cocotb_simulation + piel.run_cocotb_simulation + piel.get_simulation_output_files_from_design + piel.read_simulation_data + piel.simple_plot_simulation_data + piel.get_input_ports_index + piel.get_matched_ports_tuple_index + piel.get_design_from_openlane_migration + piel.find_design_run + piel.check_config_json_exists_openlane_v1 + piel.check_design_exists_openlane_v1 + piel.configure_and_run_design_openlane_v1 + piel.configure_parametric_designs_openlane_v1 + piel.configure_flow_script_openlane_v1 + piel.create_parametric_designs_openlane_v1 + piel.get_design_directory_from_root_openlane_v1 + piel.get_latest_version_root_openlane_v1 + piel.read_configuration_openlane_v1 + piel.write_configuration_openlane_v1 + piel.filter_timing_sta_files + piel.filter_power_sta_files + piel.get_all_timing_sta_files + piel.get_all_power_sta_files + piel.calculate_max_frame_amount + piel.calculate_propagation_delay_from_file + piel.calculate_propagation_delay_from_timing_data + piel.configure_timing_data_rows + piel.configure_frame_id + piel.filter_timing_data_by_net_name_and_type + piel.get_frame_meta_data + piel.get_frame_lines_data + piel.get_frame_timing_data + piel.get_all_timing_data_from_file + piel.read_sta_rpt_fwf_file + piel.contains_in_lines + piel.create_file_lines_dataframe + piel.get_file_line_by_keyword + piel.read_file_lines + piel.run_openlane_flow + piel.convert_numeric_to_prefix + piel.get_sdense_ports_index + piel.sax_to_s_parameters_standard_matrix + piel.fock_state_nonzero_indexes + piel.fock_state_to_photon_number_factorial + piel.verify_matrix_is_unitary + piel.subunitary_selection_on_range + piel.subunitary_selection_on_index + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + piel.piel_path_types + piel.test_spm_open_lane_configuration + piel.example_open_lane_configuration + piel.delete_simulation_output_files + piel.get_simulation_output_files + piel.snet + piel.standard_s_parameters_to_qutip_qobj + piel.__author__ + piel.__email__ + piel.__version__ + + +.. py:data:: piel_path_types + + + +.. py:data:: test_spm_open_lane_configuration + + + +.. py:data:: example_open_lane_configuration + + + +.. py:function:: check_path_exists(path: piel.config.piel_path_types, raise_errors: bool = False) -> bool + + Checks if a directory exists. + + :param path: Input path. + :type path: piel_path_types + + :returns: True if directory exists. + :rtype: directory_exists(bool) + + +.. py:function:: check_example_design(design_name: str = 'simple_design', designs_directory: piel.config.piel_path_types | None = None) -> bool + + We copy the example simple_design from docs to the `/foss/designs` in the `iic-osic-tools` environment. + + :param design_name: Name of the design to check. + :type design_name: str + :param designs_directory: Directory that contains the DESIGNS environment flag. + :type designs_directory: piel_path_types + :param # TODO: + + :returns: None + + +.. py:function:: copy_source_folder(source_directory: piel.config.piel_path_types, target_directory: piel.config.piel_path_types) -> None + + Copies the files from a source_directory to a target_directory + + :param source_directory: Source directory. + :type source_directory: piel_path_types + :param target_directory: Target directory. + :type target_directory: piel_path_types + + :returns: None + + +.. py:function:: create_new_directory(directory_path: str | pathlib.Path) -> None + + Creates a new directory. + + If the parents of the target_directory do not exist, they will be created too. + + :param directory_path: Input path. + :type directory_path: str | pathlib.Path + + :returns: None + + +.. py:function:: delete_path(path: str | pathlib.Path) -> None + + Deletes a path. + + :param path: Input path. + :type path: str | pathlib.Path + + :returns: None + + +.. py:function:: delete_path_list_in_directory(directory_path: piel.config.piel_path_types, path_list: list, ignore_confirmation: bool = False, validate_individual: bool = False) -> None + + Deletes a list of files in a directory. + + :param directory_path: Input path. + :type directory_path: piel_path_types + :param path_list: List of files. + :type path_list: list + :param ignore_confirmation: Ignore confirmation. Default: False. + :type ignore_confirmation: bool + :param validate_individual: Validate individual files. Default: False. + :type validate_individual: bool + + :returns: None + + +.. py:function:: get_files_recursively_in_directory(path: piel.config.piel_path_types, extension: str = '*') + + Returns a list of files in a directory. + + :param path: Input path. + :type path: piel_path_types + :param extension: File extension. + :type extension: str + + :returns: List of files. + :rtype: file_list(list) + + +.. py:function:: permit_directory_all(directory_path: piel.config.piel_path_types) -> None + + Permits a directory to be read, written and executed. Use with care as it can be a source for security issues. + + :param directory_path: Input path. + :type directory_path: piel_path_types + + :returns: None + + +.. py:function:: permit_script_execution(script_path: piel.config.piel_path_types) -> None + + Permits the execution of a script. + + :param script_path: Script path. + :type script_path: piel_path_types + + :returns: None + + +.. py:function:: setup_example_design(project_source: Literal[piel, openlane] = 'piel', example_name: str = 'simple_design') -> None + + We copy the example simple_design from docs to the `/foss/designs` in the `iic-osic-tools` environment. + + :param project_source: Source of the project. + :type project_source: str + :param example_name: Name of the example design. + :type example_name: str + + :returns: None + + +.. py:function:: read_json(path: piel.config.piel_path_types) -> dict + + Reads a JSON file. + + :param path: Input path. + :type path: piel_path_types + + :returns: JSON data. + :rtype: json_data(dict) + + +.. py:function:: return_path(input_path: piel.config.piel_path_types) -> pathlib.Path + + Returns a pathlib.Path to be able to perform operations accordingly internally. + + This allows us to maintain compatibility between POSIX and Windows systems. + + :param input_path: Input path. + :type input_path: str + + :returns: Pathlib path. + :rtype: pathlib.Path + + +.. py:function:: run_script(script_path: piel.config.piel_path_types) -> None + + Runs a script on the filesystem `script_path`. + + :param script_path: Script path. + :type script_path: piel_path_types + + :returns: None + + +.. py:function:: write_script(directory_path: piel.config.piel_path_types, script: str, script_name: str) -> None + + Records a `script_name` in the `scripts` project directory. + + :param directory_path: Design directory. + :type directory_path: piel_path_types + :param script: Script to write. + :type script: str + :param script_name: Name of the script. + :type script_name: str + + :returns: None + + +.. py:function:: create_gdsfactory_component_from_openlane(design_name_v1: str | None = None, design_directory: piel.config.piel_path_types | None = None, run_name: str | None = None, v1: bool = True) -> gdsfactory.Component + + This function cretes a gdsfactory layout component that can be included in the network codesign of the device, or that can be used for interconnection codesign. + + It will look into the latest design run and extract the final OpenLane-generated GDS. You do not have to have run this with OpenLane2 as it just looks at the latest run. + + :param design_name_v1: Design name of the v1 design that can be found within `$OPENLANE_ROOT/""/designs`. + :type design_name_v1: str + :param design_directory: Design directory PATH. + :type design_directory: piel_path_types + :param run_name: Name of the run to extract the GDS from. If None, it will look at the latest run. + :type run_name: str + :param v1: If True, it will import the design from the OpenLane v1 configuration. + :type v1: bool + + :returns: GDSFactory component. + :rtype: component(gf.Component) + + +.. py:function:: gdsfactory_netlist_to_spice_netlist(gdsfactory_netlist: dict, generators: dict, **kwargs) -> hdl21.Module + + This function converts a GDSFactory electrical netlist into a standard SPICE netlist. It follows the same + principle as the `sax` circuit composition. + + Each GDSFactory netlist has a set of instances, each with a corresponding model, and each instance with a given + set of geometrical settings that can be applied to each particular model. We know the type of SPICE model from + the instance model we provides. + + We know that the gdsfactory has a set of instances, and we can map unique models via sax through our own + composition circuit. Write the SPICE component based on the model into a total circuit representation in string + from the reshaped gdsfactory dictionary into our own structure. + + :param gdsfactory_netlist: GDSFactory netlist + :param generators: Dictionary of Generators + + :returns: hdl21 module or raw SPICE string + + +.. py:function:: construct_hdl21_module(spice_netlist: dict, **kwargs) -> hdl21.Module + + This function converts a gdsfactory-spice converted netlist using the component models into a SPICE circuit. + + Part of the complexity of this function is the multiport nature of some components and models, and assigning the + parameters accordingly into the SPICE function. This is because not every SPICE component will be bi-port, + and many will have multi-ports and parameters accordingly. Each model can implement the composition into a + SPICE circuit, but they depend on a set of parameters that must be set from the instance. Another aspect is + that we may want to assign the component ID according to the type of component. However, we can also assign the + ID based on the individual instance in the circuit, which is also a reasonable approximation. However, + it could be said, that the ideal implementation would be for each component model provided to return the SPICE + instance including connectivity except for the ID. + + # TODO implement validators + + +.. py:function:: convert_connections_to_tuples(connections: dict) + + Convert from: + + .. code-block:: + + { + 'straight_1,e1': 'taper_1,e2', + 'straight_1,e2': 'taper_2,e2', + 'taper_1,e1': 'via_stack_1,e3', + 'taper_2,e1': 'via_stack_2,e1' + } + + to: + + .. code-block:: + + [(('straight_1', 'e1'), ('taper_1', 'e2')), (('straight_1', 'e2'), ('taper_2', 'e2')), (('taper_1', 'e1'), + ('via_stack_1', 'e3')), (('taper_2', 'e1'), ('via_stack_2', 'e1'))] + + +.. py:function:: gdsfactory_netlist_with_hdl21_generators(gdsfactory_netlist: dict, generators=None) + + This function allows us to map the ``hdl21`` models dictionary in a `sax`-like implementation to the ``GDSFactory`` netlist. This allows us to iterate over each instance in the netlist and construct a circuit after this function.] + + Example usage: + + .. code-block:: + + >>> import gdsfactory as gf + >>> from piel.integration.gdsfactory_hdl21.conversion import gdsfactory_netlist_with_hdl21_generators + >>> from piel.models.physical.electronic import get_default_models + >>> gdsfactory_netlist_with_hdl21_generators(gdsfactory_netlist=gf.components.mzi2x2_2x2_phase_shifter().get_netlist(exclude_port_types="optical"),generators=get_default_models()) + + :param gdsfactory_netlist: The netlist from ``GDSFactory`` to map to the ``hdl21`` models dictionary. + :param generators: The ``hdl21`` models dictionary to map to the ``GDSFactory`` netlist. + + :returns: The ``GDSFactory`` netlist with the ``hdl21`` models dictionary. + + +.. py:function:: sax_circuit_permanent(sax_input: sax.SType) -> tuple + + The permanent of a unitary is used to determine the state probability of combinatorial Gaussian boson samping systems. + + ``thewalrus`` Ryser's algorithm permananet implementation is described here: https://the-walrus.readthedocs.io/en/latest/gallery/permanent_tutorial.html + + # TODO maybe implement subroutine if computation is taking forever. + + :param sax_input: The sax S-parameter dictionary. + :type sax_input: sax.SType + + :returns: The circuit permanent and the time it took to compute it. + :rtype: tuple + + +.. py:function:: unitary_permanent(unitary_matrix: jax.numpy.ndarray) -> tuple + + The permanent of a unitary is used to determine the state probability of combinatorial Gaussian boson samping systems. + + ``thewalrus`` Ryser's algorithm permananet implementation is described here: https://the-walrus.readthedocs.io/en/latest/gallery/permanent_tutorial.html + + Note that this function needs to be as optimised as possible, so we need to minimise our computational complexity of our operation. + + # TODO implement validation + # TODO maybe implement subroutine if computation is taking forever. + # TODO why two outputs? Understand this properly later. + + :param unitary_permanent: The unitary matrix. + :type unitary_permanent: np.ndarray + + :returns: The circuit permanent and the time it took to compute it. + :rtype: tuple + + +.. py:function:: sax_to_ideal_qutip_unitary(sax_input: sax.SType) + + This function converts the calculated S-parameters into a standard Unitary matrix topology so that the shape and + dimensions of the matrix can be observed. + + I think this means we need to transpose the output of the filtered sax SDense matrix to map it to a QuTip matrix. + Note that the documentation and formatting of the standard `sax` mapping to a S-parameter standard notation is + already in described in piel/piel/sax/utils.py. + + From this stage we can implement a ``QObj`` matrix accordingly and perform simulations accordingly. + https://qutip.org/docs/latest/guide/qip/qip-basics.html#unitaries + + For example, a ``qutip`` representation of an s-gate gate would be: + + ..code-block:: + + import numpy as np + import qutip + # S-Gate + s_gate_matrix = np.array([[1., 0], [0., 1.j]]) + s_gate = qutip.Qobj(mat, dims=[[2], [2]]) + + In mathematical notation, this S-gate would be written as: + + ..math:: + + S = \begin{bmatrix} + 1 & 0 \\ + 0 & i \\ + \end{bmatrix} + + :param sax_input: A dictionary of S-parameters in the form of a SDict from `sax`. + :type sax_input: sax.SType + + :returns: A QuTip QObj representation of the S-parameters in a unitary matrix. + :rtype: qobj_unitary (qutip.Qobj) + + +.. py:function:: fock_transition_probability_amplitude(initial_fock_state: qutip.Qobj, final_fock_state: qutip.Qobj, unitary_matrix: jax.numpy.ndarray) + + This function returns the transition probability amplitude between two Fock states when propagating in between + the unitary_matrix which represents a quantum state circuit. + + Note that based on (TODO cite Jeremy), the initial Fock state corresponds to the columns of the unitary and the + final Fock states corresponds to the rows of the unitary. + + .. math :: + + ewcommand{\ket}[1]{\left|{#1} + ight + angle} + + The subunitary :math:`U_{f_1}^{f_2}` is composed from the larger unitary by selecting the rows from the output state + Fock state occupation of :math:`\ket{f_2}`, and columns from the input :math:`\ket{f_1}`. In our case, we need to select the + columns indexes :math:`(0,3)` and rows indexes :math:`(1,2)`. + + If we consider a photon number of more than one for the transition Fock states, then the Permanent needs to be + normalised. The probability amplitude for the transition is described as: + + .. math :: + a(\ket{f_1} o \ket{f_2}) = + rac{ ext{per}(U_{f_1}^{f_2})}{\sqrt{(j_1! j_2! ... j_N!)(j_1^{'}! j_2^{'}! ... j_N^{'}!)}} + + Args: + initial_fock_state (qutip.Qobj): A QuTip QObj representation of the initial Fock state. + final_fock_state (qutip.Qobj): A QuTip QObj representation of the final Fock state. + unitary_matrix (jnp.ndarray): A JAX NumPy array representation of the unitary matrix. + + Returns: + float: The transition probability amplitude between the initial and final Fock states. + + + +.. py:function:: single_parameter_sweep(base_design_configuration: dict, parameter_name: str, parameter_sweep_values: list) + + This function takes a base_design_configuration dictionary and sweeps a single parameter over a list of values. It returns a list of dictionaries that correspond to the parameter sweep. + + :param base_design_configuration: Base design configuration dictionary. + :type base_design_configuration: dict + :param parameter_name: Name of parameter to sweep. + :type parameter_name: str + :param parameter_sweep_values: List of values to sweep. + :type parameter_sweep_values: list + + :returns: List of dictionaries that correspond to the parameter sweep. + :rtype: parameter_sweep_design_dictionary_array(list) + + +.. py:function:: multi_parameter_sweep(base_design_configuration: dict, parameter_sweep_dictionary: dict) -> list + + This multiparameter sweep is pretty cool, as it will generate designer list of dictionaries that comprise of all the possible combinations of your parameter sweeps. For example, if you are sweeping `parameter_1 = np.arange(0, 2) = array([0, 1])`, and `parameter_2 = np.arange(2, 4) = array([2, 3])`, then this function will generate list of dictionaries based on the default_design dictionary, but that will comprise of all the potential parameter combinations within this list. + + For the example above, there arould be 4 combinations [(0, 2), (0, 3), (1, 2), (1, 3)]. + + If you were instead sweeping for `parameter_1 = np.arange(0, 5)` and `parameter_2 = np.arange(0, 5)`, the dictionary generated would correspond to these parameter combinations of:: + [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]. + + Make sure to use the parameter_names from default_design when writing up the parameter_sweep dictionary key name. + + Example project_structure formats:: + + example_parameter_sweep_dictionary = { + "parameter_1": np.arange(1, -40, 1), + "parameter_2": np.arange(1, -40, 1), + } + + example_base_design_configuration = { + "parameter_1": 10.0, + "parameter_2": 40.0, + "parameter_3": 0, + } + + :param base_design_configuration: Dictionary of the default design configuration. + :type base_design_configuration: dict + :param parameter_sweep_dictionary: Dictionary of the parameter sweep. The keys should be the same as the keys in the base_design_configuration dictionary. + :type parameter_sweep_dictionary: dict + + :returns: List of dictionaries that comprise of all the possible combinations of your parameter sweeps. + :rtype: parameter_sweep_design_dictionary_array(list) + + +.. py:function:: check_cocotb_testbench_exists(design_directory: str | pathlib.Path) -> bool + + Checks if a cocotb testbench exists in the design directory. + + :param design_directory: Design directory. + :type design_directory: str | pathlib.Path + + :returns: True if cocotb testbench exists. + :rtype: cocotb_testbench_exists(bool) + + +.. py:function:: configure_cocotb_simulation(design_directory: str | pathlib.Path, simulator: Literal[icarus, verilator], top_level_language: Literal[verilog, vhdl], top_level_verilog_module: str, test_python_module: str, design_sources_list: list | None = None) + + Writes a cocotb makefile. + + If no design_sources_list is provided then it adds all the design sources under the `src` folder. + + In the form + .. code-block:: + + #!/bin/sh + # Makefile + # defaults + SIM ?= icarus + TOPLEVEL_LANG ?= verilog + + # Note we need to include the test script to the PYTHONPATH + export PYTHONPATH = + + VERILOG_SOURCES += $(PWD)/my_design.sv + # use VHDL_SOURCES for VHDL files + + # TOPLEVEL is the name of the toplevel module in your Verilog or VHDL file + TOPLEVEL := my_design + + # MODULE is the basename of the Python test file + MODULE := test_my_design + + # include cocotb's make rules to take care of the simulator setup + include $(shell cocotb-config --makefiles)/Makefile.sim + + + :param design_directory: The directory where the design is located. + :type design_directory: str | pathlib.Path + :param simulator: The simulator to use. + :type simulator: Literal["icarus", "verilator"] + :param top_level_language: The top level language. + :type top_level_language: Literal["verilog", "vhdl"] + :param top_level_verilog_module: The top level verilog module. + :type top_level_verilog_module: str + :param test_python_module: The test python module. + :type test_python_module: str + :param design_sources_list: A list of design sources. Defaults to None. + :type design_sources_list: list | None, optional + + :returns: None + + +.. py:data:: delete_simulation_output_files + + + +.. py:function:: run_cocotb_simulation(design_directory: str) -> subprocess.CompletedProcess + + Equivalent to running the cocotb makefile + .. code-block:: + + make + + :param design_directory: The directory where the design is located. + :type design_directory: str + + :returns: The subprocess.CompletedProcess object. + :rtype: subprocess.CompletedProcess + + +.. py:data:: get_simulation_output_files + + + +.. py:function:: get_simulation_output_files_from_design(design_directory: piel.config.piel_path_types, extension: str = 'csv') + + This function returns a list of all the simulation output files in the design directory. + + :param design_directory: The path to the design directory. + :type design_directory: piel_path_types + + :returns: List of all the simulation output files in the design directory. + :rtype: output_files (list) + + +.. py:function:: read_simulation_data(file_path: piel.config.piel_path_types) + + This function returns a Pandas dataframe that contains all the simulation data outputted from the simulation run. + + :param file_path: The path to the simulation data file. + :type file_path: piel_path_types + + :returns: The simulation data in a Pandas dataframe. + :rtype: simulation_data (pd.DataFrame) + + +.. py:function:: simple_plot_simulation_data(simulation_data: pandas.DataFrame) + + +.. py:function:: get_input_ports_index(ports_index: dict, sorting_algorithm: Literal[get_input_ports_index.prefix] = 'prefix', prefix: str = 'in') -> tuple + + This function returns the input ports of a component. However, input ports may have different sets of prefixes and suffixes. This function implements different sorting algorithms for different ports names. The default algorithm is `prefix`, which sorts the ports by their prefix. The Endianness implementation means that the tuple order is determined according to the last numerical index order of the port numbering. + + .. code-block:: python + + raw_ports_index = { + "in_o_0": 0, + "out_o_0": 1, + "out_o_1": 2, + "out_o_2": 3, + "out_o_3": 4, + "in_o_1": 5, + "in_o_2": 6, + "in_o_3": 7, + } + + get_input_ports_index(ports_index=raw_ports_index) + + # Output + ((0, "in_o_0"), (5, "in_o_1"), (6, "in_o_2"), (7, "in_o_3")) + + :param ports_index: The ports index dictionary. + :type ports_index: dict + :param sorting_algorithm: The sorting algorithm to use. Defaults to "prefix". + :type sorting_algorithm: Literal["prefix"], optional + :param prefix: The prefix to use for the sorting algorithm. Defaults to "in". + :type prefix: str, optional + + :returns: The ordered input ports index tuple. + :rtype: tuple + + +.. py:function:: get_matched_ports_tuple_index(ports_index: dict, selected_ports_tuple: Optional[tuple] = None, sorting_algorithm: Literal[get_matched_ports_tuple_index.prefix, selected_ports] = 'prefix', prefix: str = 'in') -> (tuple, tuple) + + This function returns the input ports of a component. However, input ports may have different sets of prefixes + and suffixes. This function implements different sorting algorithms for different ports names. The default + algorithm is `prefix`, which sorts the ports by their prefix. The Endianness implementation means that the tuple + order is determined according to the last numerical index order of the port numbering. Returns just a tuple of + the index. + + .. code-block:: python + + raw_ports_index = { + "in_o_0": 0, + "out_o_0": 1, + "out_o_1": 2, + "out_o_2": 3, + "out_o_3": 4, + "in_o_1": 5, + "in_o_2": 6, + "in_o_3": 7, + } + + get_input_ports_tuple_index(ports_index=raw_ports_index) + + # Output + (0, 5, 6, 7) + + :param ports_index: The ports index dictionary. + :type ports_index: dict + :param selected_ports_tuple: The selected ports tuple. Defaults to None. + :type selected_ports_tuple: tuple, optional + :param sorting_algorithm: The sorting algorithm to use. Defaults to "prefix". + :type sorting_algorithm: Literal["prefix"], optional + :param prefix: The prefix to use for the sorting algorithm. Defaults to "in". + :type prefix: str, optional + + :returns: The ordered input ports index tuple. + matched_ports_name_tuple_order(tuple): The ordered input ports name tuple. + :rtype: matches_ports_index_tuple_order(tuple) + + +.. py:function:: get_design_from_openlane_migration(v1: bool = True, design_name_v1: str | None = None, design_directory: str | pathlib.Path | None = None, root_directory_v1: str | pathlib.Path | None = None) -> (str, pathlib.Path) + + This function provides the integration mechanism for easily migrating the interconnection with other toolsets from an OpenLane v1 design to an OpenLane v2 design. + + This function checks if the inputs are to be treated as v1 inputs. If so, and a `design_name` is provided then it will set the `design_directory` to the corresponding `design_name` directory in the corresponding `root_directory_v1 / designs`. If no `root_directory` is provided then it returns `$OPENLANE_ROOT/""/. If a `design_directory` is provided then this will always take precedence even with a `v1` flag. + + :param v1: If True, it will migrate from v1 to v2. + :type v1: bool + :param design_name_v1: Design name of the v1 design that can be found within `$OPENLANE_ROOT/""/designs`. + :type design_name_v1: str + :param design_directory: Design directory PATH. Optional path for v2-based designs. + :type design_directory: str + :param root_directory_v1: Root directory of OpenLane v1. If set to None it will return `$OPENLANE_ROOT/""` + :type root_directory_v1: str + + :returns: None + + +.. py:function:: find_design_run(design_directory: piel.config.piel_path_types, run_name: str | None = None) -> pathlib.Path + + For a given `design_directory`, the `openlane` output can be found in the `runs` subdirectory. + + They get sorted based on a reverse `list.sort()` method. + + # TODO docs + + +.. py:function:: check_config_json_exists_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> bool + + Checks if a design has a `config.json` file. + + :param design_name: Name of the design. + :type design_name: str + + :returns: True if `config.json` exists. + :rtype: config_json_exists(bool) + + +.. py:function:: check_design_exists_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> bool + + Checks if a design exists in the OpenLane v1 design folder. + + Lists all designs inside the Openlane V1 design root. + + :param design_name: Name of the design. + :type design_name: str + + :returns: True if design exists. + :rtype: design_exists(bool) + + +.. py:function:: configure_and_run_design_openlane_v1(design_name: str, configuration: dict | None = None, root_directory: str | pathlib.Path | None = None) -> None + + Configures and runs an OpenLane v1 design. + + This function does the following: + 1. Check that the design_directory provided is under $OPENLANE_ROOT//designs + 2. Check if `config.json` has already been provided for this design. If a configuration dictionary is inputted into the function parameters, then it overwrites the default `config.json`. + 3. Create a script directory, a script is written and permissions are provided for it to be executable. + 4. Permit and execute the `openlane_flow.sh` script in the `scripts` directory. + + :param design_name: Name of the design. + :type design_name: str + :param configuration: Configuration dictionary. + :type configuration: dict | None + :param root_directory: Design directory. + :type root_directory: str | pathlib.Path + + :returns: None + + +.. py:function:: configure_parametric_designs_openlane_v1(design_name: str, parameter_sweep_dictionary: dict, add_id: bool = True) -> list + + For a given `source_design_directory`, this function reads in the config.json file and returns a set of parametric sweeps that gets used when creating a set of parametric designs. + + :param add_id: Add an ID to the design name. Defaults to True. + :type add_id: bool + :param parameter_sweep_dictionary: Dictionary of parameters to sweep. + :type parameter_sweep_dictionary: dict + :param source_design_directory: Source design directory. + :type source_design_directory: str | pathlib.Path + + :returns: List of configurations to sweep. + :rtype: configuration_sweep(list) + + +.. py:function:: configure_flow_script_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> None + + Configures the OpenLane v1 flow script after checking that the design directory exists. + + :param design_directory: Design directory. Defaults to latest OpenLane root. + :type design_directory: str | pathlib.Path | None + + :returns: None + + +.. py:function:: create_parametric_designs_openlane_v1(design_name: str, parameter_sweep_dictionary: dict, target_directory: str | pathlib.Path | None = None) -> None + + Takes a OpenLane v1 source directory and creates a parametric combination of these designs. + + :param design_name: Name of the design. + :type design_name: str + :param parameter_sweep_dictionary: Dictionary of parameters to sweep. + :type parameter_sweep_dictionary: dict + :param target_directory: Optional target directory. + :type target_directory: str | pathlib.Path | None + + :returns: None + + +.. py:function:: get_design_directory_from_root_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> pathlib.Path + + Gets the design directory from the root directory. + + :param design_name: Name of the design. + :type design_name: str + :param root_directory: Design directory. + :type root_directory: str | pathlib.Path + + :returns: Design directory. + :rtype: design_directory(pathlib.Path) + + +.. py:function:: get_latest_version_root_openlane_v1() -> pathlib.Path + + Gets the latest version root of OpenLane v1. + + +.. py:function:: read_configuration_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> dict + + Reads a `config.json` from a design directory. + + :param design_name: Design name. + :type design_name: str + :param root_directory: Design directory. + :type root_directory: str | pathlib.Path + + :returns: Configuration dictionary. + :rtype: configuration(dict) + + +.. py:function:: write_configuration_openlane_v1(configuration: dict, design_directory: str | pathlib.Path) -> None + + Writes a `config.json` onto a `design_directory` + + :param configuration: OpenLane configuration dictionary. + :type configuration: dict + :param design_directory: Design directory PATH. + :type design_directory: str + + :returns: None + + +.. py:function:: filter_timing_sta_files(file_list) + + Filter the timing sta files from the list of files + + :param file_list: List containing the file paths + :type file_list: list + + :returns: List containing the timing sta files + :rtype: timing_sta_files (list) + + +.. py:function:: filter_power_sta_files(file_list) + + Filter the power sta files from the list of files + + :param file_list: List containing the file paths + :type file_list: list + + :returns: List containing the power sta files + :rtype: power_sta_files (list) + + +.. py:function:: get_all_timing_sta_files(run_directory) + + This function aims to list and perform analysis on all the relevant files in a particular run between all the corners. + + :param run_directory: The run directory to perform the analysis on. Defaults to None. + :type run_directory: str, optional + + :returns: List of all the .rpt files in the run directory. + :rtype: timing_sta_files_list (list) + + +.. py:function:: get_all_power_sta_files(run_directory) + + This function aims to list and perform analysis on all the relevant files in a particular run between all the corners. + + :param run_directory: The run directory to perform the analysis on. Defaults to None. + :type run_directory: str, optional + + :returns: List of all the .rpt files in the run directory. + :rtype: power_sta_files_list (list) + + +.. py:function:: calculate_max_frame_amount(file_lines_data: pandas.DataFrame) + + Calculate the maximum frame amount based on the frame IDs in the DataFrame + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Maximum number of frames in the file + :rtype: maximum_frame_amount (int) + + +.. py:function:: calculate_propagation_delay_from_file(file_path: str | pathlib.Path) + + Calculate the propagation delay for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: Dictionary containing the propagation delay + :rtype: propagation_delay (dict) + + +.. py:function:: calculate_propagation_delay_from_timing_data(net_name_in: str, net_name_out: str, timing_data: pandas.DataFrame) + + Calculate the propagation delay between two nets + + :param net_name_in: Name of the input net + :type net_name_in: str + :param net_name_out: Name of the output net + :type net_name_out: str + :param timing_data: Dataframe containing the timing data + :type timing_data: pd.DataFrame + + :returns: Dataframe containing the propagation delay + :rtype: propagation_delay_dataframe (pd.DataFrame) + + +.. py:function:: configure_timing_data_rows(file_lines_data: pandas.DataFrame) + + Identify the timing data lines for each frame and creates a metadata dictionary for frames. + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Dictionary containing the frame metadata + :rtype: frame_meta_data (dict) + + +.. py:function:: configure_frame_id(file_lines_data: pandas.DataFrame) + + Identify the frame delimiters and assign frame ID to each line in the file + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: filter_timing_data_by_net_name_and_type(timing_data: pandas.DataFrame, net_name: str, net_type: str) + + Filter the timing data by net name and type + + :param timing_data: DataFrame containing the timing data + :type timing_data: pd.DataFrame + :param net_name: Net name to be filtered + :type net_name: str + :param net_type: Net type to be filtered + :type net_type: str + + :returns: DataFrame containing the timing data + :rtype: timing_data (pd.DataFrame) + + +.. py:function:: get_frame_meta_data(file_lines_data) + + Get the frame metadata + + :param file_lines_data: DataFrame containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: DataFrame containing the start point name + end_point_name (pd.DataFrame): DataFrame containing the end point name + path_group_name (pd.DataFrame): DataFrame containing the path group name + path_type_name (pd.DataFrame): DataFrame containing the path type name + :rtype: start_point_name (pd.DataFrame) + + +.. py:function:: get_frame_lines_data(file_path: str | pathlib.Path) + + Calculate the timing data for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: DataFrame containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: get_frame_timing_data(file: str | pathlib.Path, frame_meta_data: dict, frame_id: int = 0) + + Extract the timing data from the file + + :param file: Address of the file + :type file: str | pathlib.Path + :param frame_meta_data: Dictionary containing the frame metadata + :type frame_meta_data: dict + :param frame_id: Frame ID to be read + :type frame_id: int + + :returns: DataFrame containing the timing data + :rtype: timing_data (pd.DataFrame) + + +.. py:function:: get_all_timing_data_from_file(file_path: str | pathlib.Path) + + Calculate the timing data for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: Dictionary containing the timing data for each frame + :rtype: frame_timing_data (dict) + + +.. py:function:: read_sta_rpt_fwf_file(file: str | pathlib.Path, frame_meta_data: dict, frame_id: int = 0) + + Read the fixed width file and return a DataFrame + + :param file: Address of the file + :type file: str | pathlib.Path + :param frame_meta_data: Dictionary containing the frame metadata + :type frame_meta_data: dict + :param frame_id: Frame ID to be read + :type frame_id: int + + :returns: DataFrame containing the file data + :rtype: file_data (pd.DataFrame) + + +.. py:function:: contains_in_lines(file_lines_data: pandas.DataFrame, keyword: str) + + Check if the keyword is contained in the file lines + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + :param keyword: Keyword to search for + :type keyword: str + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: create_file_lines_dataframe(file_lines_raw) + + Create a DataFrame from the raw lines of a file + + :param file_lines_raw: list containing the file lines + :type file_lines_raw: list + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: get_file_line_by_keyword(file_lines_data: pandas.DataFrame, keyword: str, regex: str) + + Extract the data from the file lines using the given keyword and regex + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + :param keyword: Keyword to search for + :type keyword: str + :param regex: Regex to extract the data + :type regex: str + + :returns: Dataframe containing the extracted values + :rtype: extracted_values (pd.DataFrame) + + +.. py:function:: read_file_lines(file_path: str | pathlib.Path) + + Extract lines from the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: list containing the file lines + :rtype: file_lines_raw (list) + + +.. py:function:: run_openlane_flow(configuration: dict | None = test_spm_open_lane_configuration, design_directory: piel.config.piel_path_types = '/foss/designs/spm') -> None + + Runs the OpenLane flow. + + :param configuration: OpenLane configuration dictionary. If none is present it will default to the config.json file on the design_directory. + :type configuration: dict + :param design_directory: Design directory PATH. + :type design_directory: piel_path_types + + :returns: None + + +.. py:function:: convert_numeric_to_prefix(value: float) + + This function converts a numeric value to a number under a SPICE unit closest to the base prefix. This allows us to connect a particular number real output, into a term that can be used in a SPICE netlist. + + +.. py:function:: get_sdense_ports_index(input_ports_order: tuple, all_ports_index: dict) -> dict + + This function returns the ports index of the sax dense S-parameter matrix. + + Given that the order of the iteration is provided by the user, the dictionary keys will also be ordered + accordingly when iterating over them. This requires the user to provide a set of ordered. + + TODO verify reasonable iteration order. + + .. code-block:: python + + # The input_ports_order can be a tuple of tuples that contain the index and port name. Eg. + input_ports_order = ((0, "in_o_0"), (5, "in_o_1"), (6, "in_o_2"), (7, "in_o_3")) + # The all_ports_index is a dictionary of the ports index. Eg. + all_ports_index = { + "in_o_0": 0, + "out_o_0": 1, + "out_o_1": 2, + "out_o_2": 3, + "out_o_3": 4, + "in_o_1": 5, + "in_o_2": 6, + "in_o_3": 7, + } + # Output + {"in_o_0": 0, "in_o_1": 5, "in_o_2": 6, "in_o_3": 7} + + :param input_ports_order: The ports order tuple. Can be a tuple of tuples that contain the index and port name. + :type input_ports_order: tuple + :param all_ports_index: The ports index dictionary. + :type all_ports_index: dict + + :returns: The ordered input ports index tuple. + :rtype: tuple + + +.. py:function:: sax_to_s_parameters_standard_matrix(sax_input: sax.SType, input_ports_order: tuple | None = None) -> tuple + + A ``sax`` S-parameter SDict is provided as a dictionary of tuples with (port0, port1) as the key. This + determines the direction of the scattering relationship. It means that the number of terms in an S-parameter + matrix is the number of ports squared. + + In order to generalise, this function returns both the S-parameter matrices and the indexing ports based on the + amount provided. In terms of computational speed, we definitely would like this function to be algorithmically + very fast. For now, I will write a simple python implementation and optimise in the future. + + It is possible to see the `sax` SDense notation equivalence here: + https://flaport.github.io/sax/nbs/08_backends.html + + .. code-block:: python + + import jax.numpy as jnp + from sax.core import SDense + + # Directional coupler SDense representation + dc_sdense: SDense = ( + jnp.array([[0, 0, τ, κ], [0, 0, κ, τ], [τ, κ, 0, 0], [κ, τ, 0, 0]]), + {"in0": 0, "in1": 1, "out0": 2, "out1": 3}, + ) + + + # Directional coupler SDict representation + # Taken from https://flaport.github.io/sax/nbs/05_models.html + def coupler(*, coupling: float = 0.5) -> SDict: + kappa = coupling**0.5 + tau = (1 - coupling) ** 0.5 + sdict = reciprocal( + { + ("in0", "out0"): tau, + ("in0", "out1"): 1j * kappa, + ("in1", "out0"): 1j * kappa, + ("in1", "out1"): tau, + } + ) + return sdict + + If we were to relate the mapping accordingly based on the ports indexes, a S-Parameter matrix in the form of + :math:`S_{(output,i),(input,i)}` would be: + + .. math:: + + S = \begin{bmatrix} + S_{00} & S_{10} \\ + S_{01} & S_{11} \\ + \end{bmatrix} = + \begin{bmatrix} + \tau & j \kappa \\ + j \kappa & \tau \\ + \end{bmatrix} + + Note that the standard S-parameter and hence unitary representation is in the form of: + + .. math:: + + S = \begin{bmatrix} + S_{00} & S_{01} \\ + S_{10} & S_{11} \\ + \end{bmatrix} + + + .. math:: + + \begin{bmatrix} + b_{1} \\ + \vdots \\ + b_{n} + \end{bmatrix} + = + \begin{bmatrix} + S_{11} & \dots & S_{1n} \\ + \vdots & \ddots & \vdots \\ + S_{n1} & \dots & S_{nn} + \end{bmatrix} + \begin{bmatrix} + a_{1} \\ + \vdots \\ + a_{n} + \end{bmatrix} + + TODO check with Floris, does this mean we need to transpose the matrix? + + :param sax_input: The sax S-parameter dictionary. + :type sax_input: sax.SType + :param input_ports_order: The ports order tuple containing the names and order of the input ports. + :type input_ports_order: tuple + + :returns: The S-parameter matrix and the input ports index tuple in the standard S-parameter notation. + :rtype: tuple + + +.. py:data:: snet + + + +.. py:function:: fock_state_nonzero_indexes(fock_state: qutip.Qobj) + + This function returns the indexes of the nonzero elements of a Fock state. + + :param fock_state: A QuTip QObj representation of the Fock state. + :type fock_state: qutip.Qobj + + :returns: The indexes of the nonzero elements of the Fock state. + :rtype: tuple + + +.. py:function:: fock_state_to_photon_number_factorial(fock_state: qutip.Qobj) + + This function converts a Fock state defined as: + + .. math:: + + ewcommand{\ket}[1]{\left|{#1} + ight + angle} + \ket{f_1} = \ket{j_1, j_2, ... j_N}$ + + and returns: + + .. math:: + + j_1^{'}! j_2^{'}! ... j_N^{'}! + + Args: + fock_state (qutip.Qobj): A QuTip QObj representation of the Fock state. + + Returns: + float: The photon number factorial of the Fock state. + + + +.. py:data:: standard_s_parameters_to_qutip_qobj + + + +.. py:function:: verify_matrix_is_unitary(matrix: jax.numpy.ndarray) -> bool + + Verify that the matrix is unitary. + + :param matrix: The matrix to verify. + :type matrix: jnp.ndarray + + :returns: True if the matrix is unitary, False otherwise. + :rtype: bool + + +.. py:function:: subunitary_selection_on_range(unitary_matrix: jax.numpy.ndarray, stop_index: tuple, start_index: Optional[tuple] = (0, 0)) + + This function returns a unitary between the indexes selected, and verifies the indexes are valid by checking that + the output matrix is also a unitary. + + TODO implement validation of a 2D matrix. + + +.. py:function:: subunitary_selection_on_index(unitary_matrix: jax.numpy.ndarray, rows_index: jax.numpy.ndarray | tuple, columns_index: jax.numpy.ndarray | tuple) + + This function returns a unitary between the indexes selected, and verifies the indexes are valid by checking that + the output matrix is also a unitary. + + TODO implement validation of a 2D matrix. + + +.. py:data:: __author__ + :value: 'Dario Quintero' + + + +.. py:data:: __email__ + :value: 'darioaquintero@gmail.com' + + + +.. py:data:: __version__ + :value: '0.0.43' diff --git a/docs/autoapi/piel/integration/cocotb_sax/index.rst b/docs/autoapi/piel/integration/cocotb_sax/index.rst new file mode 100644 index 00000000..69dd9225 --- /dev/null +++ b/docs/autoapi/piel/integration/cocotb_sax/index.rst @@ -0,0 +1,9 @@ +:py:mod:`piel.integration.cocotb_sax` +===================================== + +.. py:module:: piel.integration.cocotb_sax + +.. autoapi-nested-parse:: + + The goal of implementing this integration is to enable co-simulation of photonic state evolution based on the + electronic test function or logical state implemented. diff --git a/docs/autoapi/piel/integration/gdsfactory_hdl21/conversion/index.rst b/docs/autoapi/piel/integration/gdsfactory_hdl21/conversion/index.rst new file mode 100644 index 00000000..fec83a0b --- /dev/null +++ b/docs/autoapi/piel/integration/gdsfactory_hdl21/conversion/index.rst @@ -0,0 +1,68 @@ +:py:mod:`piel.integration.gdsfactory_hdl21.conversion` +====================================================== + +.. py:module:: piel.integration.gdsfactory_hdl21.conversion + +.. autoapi-nested-parse:: + + `sax` has very good GDSFactory integration functions, so there is a question on whether implementing our own circuit + construction, and SPICE netlist parser from it, accordingly. We need in some form to connect electrical models to our + parsed netlist, in order to apply SPICE passive values, and create connectivity for each particular device. Ideally, + this would be done from the component instance as that way the component model can be integrated with its geometrical + parameters, but does not have to be done necessarily. This comes down to implementing a backend function to compile + SAX compiled circuit. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.integration.gdsfactory_hdl21.conversion.convert_connections_to_tuples + piel.integration.gdsfactory_hdl21.conversion.gdsfactory_netlist_with_hdl21_generators + + + +.. py:function:: convert_connections_to_tuples(connections: dict) + + Convert from: + + .. code-block:: + + { + 'straight_1,e1': 'taper_1,e2', + 'straight_1,e2': 'taper_2,e2', + 'taper_1,e1': 'via_stack_1,e3', + 'taper_2,e1': 'via_stack_2,e1' + } + + to: + + .. code-block:: + + [(('straight_1', 'e1'), ('taper_1', 'e2')), (('straight_1', 'e2'), ('taper_2', 'e2')), (('taper_1', 'e1'), + ('via_stack_1', 'e3')), (('taper_2', 'e1'), ('via_stack_2', 'e1'))] + + +.. py:function:: gdsfactory_netlist_with_hdl21_generators(gdsfactory_netlist: dict, generators=None) + + This function allows us to map the ``hdl21`` models dictionary in a `sax`-like implementation to the ``GDSFactory`` netlist. This allows us to iterate over each instance in the netlist and construct a circuit after this function.] + + Example usage: + + .. code-block:: + + >>> import gdsfactory as gf + >>> from piel.integration.gdsfactory_hdl21.conversion import gdsfactory_netlist_with_hdl21_generators + >>> from piel.models.physical.electronic import get_default_models + >>> gdsfactory_netlist_with_hdl21_generators(gdsfactory_netlist=gf.components.mzi2x2_2x2_phase_shifter().get_netlist(exclude_port_types="optical"),generators=get_default_models()) + + :param gdsfactory_netlist: The netlist from ``GDSFactory`` to map to the ``hdl21`` models dictionary. + :param generators: The ``hdl21`` models dictionary to map to the ``GDSFactory`` netlist. + + :returns: The ``GDSFactory`` netlist with the ``hdl21`` models dictionary. diff --git a/docs/autoapi/piel/integration/gdsfactory_hdl21/core/index.rst b/docs/autoapi/piel/integration/gdsfactory_hdl21/core/index.rst new file mode 100644 index 00000000..bbd13ea7 --- /dev/null +++ b/docs/autoapi/piel/integration/gdsfactory_hdl21/core/index.rst @@ -0,0 +1,246 @@ +:py:mod:`piel.integration.gdsfactory_hdl21.core` +================================================ + +.. py:module:: piel.integration.gdsfactory_hdl21.core + +.. autoapi-nested-parse:: + + Most of the ``hdl21``-``gdsfactory`` integration functions will be contributed directly to `gdsfactory`. However, + some `translation language` inherent to the ``piel`` implementation of these tools is included here. + + Note that to be able to construct a full circuit model of the netlist tools provided, it is necessary to create + individual circuit models of the devices that we will interconnect, and then map them to a larger netlist. This means + that it is necessary to create specific SPICE models for each particular component, say in an electrical netlist. + + This functions convert a GDSFactory netlist, with a set of component models, into `hdl21` that accounts for the + instance properties, which can then be connected into a VLSIR compatible `Netlist` implementation. + + Eventually we will implement RCX where we can extract the netlist with parasitics directly from the layout, + but for now this will be the implementation. The output structure of our SPICE should be compatible with the + `Netlist` package BaseModel. + + We follow the principle in: https://eee.guc.edu.eg/Courses/Electronics/ELCT503%20Semiconductors/Lab/spicehowto.pdf + + .. code-block:: spice + + Spice Simulation 1-1 + *** MODEL Descriptions *** + .model nm NMOS level=2 VT0=0.7 + KP=80e-6 LAMBDA=0.01 + + *** NETLIST Description *** + M1 vdd ng 0 0 nm W=3u L=3u + R1 in ng 50 + Vdd vdd 0 5 + Vin in 0 2.5 + + *** SIMULATION Commands *** + .op + .end + + Note that the netlist device connectivity structure of most passive components is in the form: + + .. code-block:: spice + + + + Our example GDSFactory netlist format is in the simplified form: + + .. code-block:: + + { + "connections": { + "straight_1": { + "e1": "taper_1,e2", + "e2": "taper_2,e2" + }, + "taper_1": { + "e1": "via_stack_1,e3" + }, + "taper_2": { + "e1": "via_stack_2,e1" + } + }, + "instances": { + "straight_1": { + "component": "straight", + "info": { + "length": 15.0, + "width": 0.5, + "cross_section": "strip_heater_metal", + "settings": { + "width": 0.5, + "layer": "WG", + "heater_width": 2.5, + "layer_heater": "HEATER" + } + } + }, + "taper_1": { + "component": "taper", + "info": { + "length": 5.0, + "width1": 11.0, + "width2": 2.5 + }, + "settings": { + "cross_section": { + "layer": "HEATER", + "width": 2.5, + "offset": 0.0, + "taper_length": 10.0, + "gap": 5.0, + "min_length": 5.0, + "port_names": ["e1", "e2"] + } + } + }, + "taper_2": { + "component": "taper", + "info": { + "length": 5.0, + "width1": 11.0, + "width2": 2.5 + }, + "settings": { + "cross_section": { + "layer": "HEATER", + "width": 2.5, + "offset": 0.0, + "taper_length": 10.0, + "gap": 5.0, + "min_length": 5.0, + "port_names": ["e1", "e2"] + } + } + }, + "via_stack_1": { + "component": "via_stack", + "info": { + "size": [11.0, 11.0], + "layer": "M3" + }, + "settings": { + "layers": ["HEATER", "M2", "M3"] + } + }, + "via_stack_2": { + "component": "via_stack", + "info": { + "size": [11.0, 11.0], + "layer": "M3" + }, + "settings": { + "layers": ["HEATER", "M2", "M3"] + } + } + }, + "placements": { + "straight_1": {"x": 0.0, "y": 0.0, "rotation": 0, "mirror": 0}, + "taper_1": {"x": -5.0, "y": 0.0, "rotation": 0, "mirror": 0}, + "taper_2": {"x": 20.0, "y": 0.0, "rotation": 180, "mirror": 0}, + "via_stack_1": {"x": -10.5, "y": 0.0, "rotation": 0, "mirror": 0}, + "via_stack_2": {"x": 25.5, "y": 0.0, "rotation": 0, "mirror": 0} + }, + "ports": { + "e1": "taper_1,e2", + "e2": "taper_2,e2" + }, + "name": "straight_heater_metal_simple", + } + + This is particularly useful when creating our components and connectivity, because what we can do is instantiate our + devices with their corresponding values, and then create our connectivity accordingly. To do this properly from our + GDSFactory netlist to ``hdl21``, we can then extract the total SPICE circuit, and convert it to a VLSIR format using + the ``Netlist`` module. The reason why we can't use the Netlist package from Dan Fritchman directly is that we need to + apply a set of models that translate a particular component instantiation into an electrical model. Because we are + not yet doing layout extraction as that requires EM solvers, we need to create some sort of SPICE level assignment + based on the provided dictionary. + + Note that ``hdl21`` already can implement the port connectivity directly from internal instances, and translate this + to our connectivity netlist. This means we only need to iterate to create our instances based on our models into a + ``hdl21`` module, then we can easily assign the corresponding values. It is also possible to create the assigned + parameters as part of the ``hdl21`` component which would form part of our module. Because the gdsfactory names are + compatible with ``hdl21``, then it is fine to create the integration accordingly. + + The algorithm can be to: + + 1. Parse the gdsfactory netlist, assign the electrical ports for the model. Extract all instances and + required models from the netlist. + 2. Verify that the models have been provided. Each model describes the type of + component this is, how many ports it requires and so on. Create a ``hdl21`` top level module for every gdsfactory + netlist, this is reasonable as it is composed, and not a generator class. This generates a large amount of instantiated ``hdl21`` modules that are generated from `generators`. + 3. Map the connections to each instance port as part of the instance dictionary. This parses the connectivity in the ``gdsfactory`` netlist and connects the ports accordingly. + + The connections are a bit more complex. So each of our connections dictionary is in the form: + + .. code-block:: + + "connections": { + "straight_1": { + "e1": "taper_1,e2", + "e2": "taper_2,e2" + }, + "taper_1": { + "e1": "via_stack_1,e3" + }, + "taper_2": { + "e1": "via_stack_2,e1" + } + }, + + We know what our top model ports are. We know our internal instance ports as well, and this will be provided by the + model too. For the sake of easiness, we can describe these as ``hdl21`` equivalent ``InOut`` or ``Port` `ports and + not have to deal with directionality. After instance declaration, and models for each of these components with the + corresponding port topology, it is then straightforward to parse the connectivity and implement the network, + and extract the SPICE. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.integration.gdsfactory_hdl21.core.gdsfactory_netlist_to_spice_netlist + piel.integration.gdsfactory_hdl21.core.construct_hdl21_module + + + +.. py:function:: gdsfactory_netlist_to_spice_netlist(gdsfactory_netlist: dict, generators: dict, **kwargs) -> hdl21.Module + + This function converts a GDSFactory electrical netlist into a standard SPICE netlist. It follows the same + principle as the `sax` circuit composition. + + Each GDSFactory netlist has a set of instances, each with a corresponding model, and each instance with a given + set of geometrical settings that can be applied to each particular model. We know the type of SPICE model from + the instance model we provides. + + We know that the gdsfactory has a set of instances, and we can map unique models via sax through our own + composition circuit. Write the SPICE component based on the model into a total circuit representation in string + from the reshaped gdsfactory dictionary into our own structure. + + :param gdsfactory_netlist: GDSFactory netlist + :param generators: Dictionary of Generators + + :returns: hdl21 module or raw SPICE string + + +.. py:function:: construct_hdl21_module(spice_netlist: dict, **kwargs) -> hdl21.Module + + This function converts a gdsfactory-spice converted netlist using the component models into a SPICE circuit. + + Part of the complexity of this function is the multiport nature of some components and models, and assigning the + parameters accordingly into the SPICE function. This is because not every SPICE component will be bi-port, + and many will have multi-ports and parameters accordingly. Each model can implement the composition into a + SPICE circuit, but they depend on a set of parameters that must be set from the instance. Another aspect is + that we may want to assign the component ID according to the type of component. However, we can also assign the + ID based on the individual instance in the circuit, which is also a reasonable approximation. However, + it could be said, that the ideal implementation would be for each component model provided to return the SPICE + instance including connectivity except for the ID. + + # TODO implement validators diff --git a/docs/autoapi/piel/integration/gdsfactory_hdl21/index.rst b/docs/autoapi/piel/integration/gdsfactory_hdl21/index.rst new file mode 100644 index 00000000..dc5fe4a8 --- /dev/null +++ b/docs/autoapi/piel/integration/gdsfactory_hdl21/index.rst @@ -0,0 +1,106 @@ +:py:mod:`piel.integration.gdsfactory_hdl21` +=========================================== + +.. py:module:: piel.integration.gdsfactory_hdl21 + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + conversion/index.rst + core/index.rst + utils/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.integration.gdsfactory_hdl21.gdsfactory_netlist_to_spice_netlist + piel.integration.gdsfactory_hdl21.construct_hdl21_module + piel.integration.gdsfactory_hdl21.convert_connections_to_tuples + piel.integration.gdsfactory_hdl21.gdsfactory_netlist_with_hdl21_generators + + + +.. py:function:: gdsfactory_netlist_to_spice_netlist(gdsfactory_netlist: dict, generators: dict, **kwargs) -> hdl21.Module + + This function converts a GDSFactory electrical netlist into a standard SPICE netlist. It follows the same + principle as the `sax` circuit composition. + + Each GDSFactory netlist has a set of instances, each with a corresponding model, and each instance with a given + set of geometrical settings that can be applied to each particular model. We know the type of SPICE model from + the instance model we provides. + + We know that the gdsfactory has a set of instances, and we can map unique models via sax through our own + composition circuit. Write the SPICE component based on the model into a total circuit representation in string + from the reshaped gdsfactory dictionary into our own structure. + + :param gdsfactory_netlist: GDSFactory netlist + :param generators: Dictionary of Generators + + :returns: hdl21 module or raw SPICE string + + +.. py:function:: construct_hdl21_module(spice_netlist: dict, **kwargs) -> hdl21.Module + + This function converts a gdsfactory-spice converted netlist using the component models into a SPICE circuit. + + Part of the complexity of this function is the multiport nature of some components and models, and assigning the + parameters accordingly into the SPICE function. This is because not every SPICE component will be bi-port, + and many will have multi-ports and parameters accordingly. Each model can implement the composition into a + SPICE circuit, but they depend on a set of parameters that must be set from the instance. Another aspect is + that we may want to assign the component ID according to the type of component. However, we can also assign the + ID based on the individual instance in the circuit, which is also a reasonable approximation. However, + it could be said, that the ideal implementation would be for each component model provided to return the SPICE + instance including connectivity except for the ID. + + # TODO implement validators + + +.. py:function:: convert_connections_to_tuples(connections: dict) + + Convert from: + + .. code-block:: + + { + 'straight_1,e1': 'taper_1,e2', + 'straight_1,e2': 'taper_2,e2', + 'taper_1,e1': 'via_stack_1,e3', + 'taper_2,e1': 'via_stack_2,e1' + } + + to: + + .. code-block:: + + [(('straight_1', 'e1'), ('taper_1', 'e2')), (('straight_1', 'e2'), ('taper_2', 'e2')), (('taper_1', 'e1'), + ('via_stack_1', 'e3')), (('taper_2', 'e1'), ('via_stack_2', 'e1'))] + + +.. py:function:: gdsfactory_netlist_with_hdl21_generators(gdsfactory_netlist: dict, generators=None) + + This function allows us to map the ``hdl21`` models dictionary in a `sax`-like implementation to the ``GDSFactory`` netlist. This allows us to iterate over each instance in the netlist and construct a circuit after this function.] + + Example usage: + + .. code-block:: + + >>> import gdsfactory as gf + >>> from piel.integration.gdsfactory_hdl21.conversion import gdsfactory_netlist_with_hdl21_generators + >>> from piel.models.physical.electronic import get_default_models + >>> gdsfactory_netlist_with_hdl21_generators(gdsfactory_netlist=gf.components.mzi2x2_2x2_phase_shifter().get_netlist(exclude_port_types="optical"),generators=get_default_models()) + + :param gdsfactory_netlist: The netlist from ``GDSFactory`` to map to the ``hdl21`` models dictionary. + :param generators: The ``hdl21`` models dictionary to map to the ``GDSFactory`` netlist. + + :returns: The ``GDSFactory`` netlist with the ``hdl21`` models dictionary. diff --git a/docs/autoapi/piel/integration/gdsfactory_hdl21/utils/index.rst b/docs/autoapi/piel/integration/gdsfactory_hdl21/utils/index.rst new file mode 100644 index 00000000..864abb1d --- /dev/null +++ b/docs/autoapi/piel/integration/gdsfactory_hdl21/utils/index.rst @@ -0,0 +1,29 @@ +:py:mod:`piel.integration.gdsfactory_hdl21.utils` +================================================= + +.. py:module:: piel.integration.gdsfactory_hdl21.utils + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.integration.gdsfactory_hdl21.utils.rename_gdsfactory_connections_to_spice + piel.integration.gdsfactory_hdl21.utils.convert_tuples_to_strings + + + +.. py:function:: rename_gdsfactory_connections_to_spice(connections: dict) + + We convert the connection connectivity of the gdsfactory netlist into names that can be integrated into a SPICE + netlist. It iterates on each key value pair, and replaces each comma with an underscore. + + # TODO docs + + +.. py:function:: convert_tuples_to_strings(tuple_list) diff --git a/docs/autoapi/piel/integration/gdsfactory_openlane/index.rst b/docs/autoapi/piel/integration/gdsfactory_openlane/index.rst new file mode 100644 index 00000000..261a0a55 --- /dev/null +++ b/docs/autoapi/piel/integration/gdsfactory_openlane/index.rst @@ -0,0 +1,45 @@ +:py:mod:`piel.integration.gdsfactory_openlane` +============================================== + +.. py:module:: piel.integration.gdsfactory_openlane + +.. autoapi-nested-parse:: + + There are a number of ways to generate gdsfactory integration. + + It is worth noting that GDSFactory has already the following PDKs installed: + * SKY130nm https://gdsfactory.github.io/skywater130/ + * GF180nm https://gdsfactory.github.io/gf180/ + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.integration.gdsfactory_openlane.create_gdsfactory_component_from_openlane + + + +.. py:function:: create_gdsfactory_component_from_openlane(design_name_v1: str | None = None, design_directory: piel.config.piel_path_types | None = None, run_name: str | None = None, v1: bool = True) -> gdsfactory.Component + + This function cretes a gdsfactory layout component that can be included in the network codesign of the device, or that can be used for interconnection codesign. + + It will look into the latest design run and extract the final OpenLane-generated GDS. You do not have to have run this with OpenLane2 as it just looks at the latest run. + + :param design_name_v1: Design name of the v1 design that can be found within `$OPENLANE_ROOT/""/designs`. + :type design_name_v1: str + :param design_directory: Design directory PATH. + :type design_directory: piel_path_types + :param run_name: Name of the run to extract the GDS from. If None, it will look at the latest run. + :type run_name: str + :param v1: If True, it will import the design from the OpenLane v1 configuration. + :type v1: bool + + :returns: GDSFactory component. + :rtype: component(gf.Component) diff --git a/docs/autoapi/piel/integration/index.rst b/docs/autoapi/piel/integration/index.rst new file mode 100644 index 00000000..d0f7ab9a --- /dev/null +++ b/docs/autoapi/piel/integration/index.rst @@ -0,0 +1,247 @@ +:py:mod:`piel.integration` +========================== + +.. py:module:: piel.integration + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + gdsfactory_hdl21/index.rst + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + cocotb_sax/index.rst + gdsfactory_openlane/index.rst + sax_qutip/index.rst + sax_thewalrus/index.rst + thewalrus_qutip/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.integration.create_gdsfactory_component_from_openlane + piel.integration.gdsfactory_netlist_to_spice_netlist + piel.integration.construct_hdl21_module + piel.integration.convert_connections_to_tuples + piel.integration.gdsfactory_netlist_with_hdl21_generators + piel.integration.sax_circuit_permanent + piel.integration.unitary_permanent + piel.integration.sax_to_ideal_qutip_unitary + piel.integration.fock_transition_probability_amplitude + + + +.. py:function:: create_gdsfactory_component_from_openlane(design_name_v1: str | None = None, design_directory: piel.config.piel_path_types | None = None, run_name: str | None = None, v1: bool = True) -> gdsfactory.Component + + This function cretes a gdsfactory layout component that can be included in the network codesign of the device, or that can be used for interconnection codesign. + + It will look into the latest design run and extract the final OpenLane-generated GDS. You do not have to have run this with OpenLane2 as it just looks at the latest run. + + :param design_name_v1: Design name of the v1 design that can be found within `$OPENLANE_ROOT/""/designs`. + :type design_name_v1: str + :param design_directory: Design directory PATH. + :type design_directory: piel_path_types + :param run_name: Name of the run to extract the GDS from. If None, it will look at the latest run. + :type run_name: str + :param v1: If True, it will import the design from the OpenLane v1 configuration. + :type v1: bool + + :returns: GDSFactory component. + :rtype: component(gf.Component) + + +.. py:function:: gdsfactory_netlist_to_spice_netlist(gdsfactory_netlist: dict, generators: dict, **kwargs) -> hdl21.Module + + This function converts a GDSFactory electrical netlist into a standard SPICE netlist. It follows the same + principle as the `sax` circuit composition. + + Each GDSFactory netlist has a set of instances, each with a corresponding model, and each instance with a given + set of geometrical settings that can be applied to each particular model. We know the type of SPICE model from + the instance model we provides. + + We know that the gdsfactory has a set of instances, and we can map unique models via sax through our own + composition circuit. Write the SPICE component based on the model into a total circuit representation in string + from the reshaped gdsfactory dictionary into our own structure. + + :param gdsfactory_netlist: GDSFactory netlist + :param generators: Dictionary of Generators + + :returns: hdl21 module or raw SPICE string + + +.. py:function:: construct_hdl21_module(spice_netlist: dict, **kwargs) -> hdl21.Module + + This function converts a gdsfactory-spice converted netlist using the component models into a SPICE circuit. + + Part of the complexity of this function is the multiport nature of some components and models, and assigning the + parameters accordingly into the SPICE function. This is because not every SPICE component will be bi-port, + and many will have multi-ports and parameters accordingly. Each model can implement the composition into a + SPICE circuit, but they depend on a set of parameters that must be set from the instance. Another aspect is + that we may want to assign the component ID according to the type of component. However, we can also assign the + ID based on the individual instance in the circuit, which is also a reasonable approximation. However, + it could be said, that the ideal implementation would be for each component model provided to return the SPICE + instance including connectivity except for the ID. + + # TODO implement validators + + +.. py:function:: convert_connections_to_tuples(connections: dict) + + Convert from: + + .. code-block:: + + { + 'straight_1,e1': 'taper_1,e2', + 'straight_1,e2': 'taper_2,e2', + 'taper_1,e1': 'via_stack_1,e3', + 'taper_2,e1': 'via_stack_2,e1' + } + + to: + + .. code-block:: + + [(('straight_1', 'e1'), ('taper_1', 'e2')), (('straight_1', 'e2'), ('taper_2', 'e2')), (('taper_1', 'e1'), + ('via_stack_1', 'e3')), (('taper_2', 'e1'), ('via_stack_2', 'e1'))] + + +.. py:function:: gdsfactory_netlist_with_hdl21_generators(gdsfactory_netlist: dict, generators=None) + + This function allows us to map the ``hdl21`` models dictionary in a `sax`-like implementation to the ``GDSFactory`` netlist. This allows us to iterate over each instance in the netlist and construct a circuit after this function.] + + Example usage: + + .. code-block:: + + >>> import gdsfactory as gf + >>> from piel.integration.gdsfactory_hdl21.conversion import gdsfactory_netlist_with_hdl21_generators + >>> from piel.models.physical.electronic import get_default_models + >>> gdsfactory_netlist_with_hdl21_generators(gdsfactory_netlist=gf.components.mzi2x2_2x2_phase_shifter().get_netlist(exclude_port_types="optical"),generators=get_default_models()) + + :param gdsfactory_netlist: The netlist from ``GDSFactory`` to map to the ``hdl21`` models dictionary. + :param generators: The ``hdl21`` models dictionary to map to the ``GDSFactory`` netlist. + + :returns: The ``GDSFactory`` netlist with the ``hdl21`` models dictionary. + + +.. py:function:: sax_circuit_permanent(sax_input: sax.SType) -> tuple + + The permanent of a unitary is used to determine the state probability of combinatorial Gaussian boson samping systems. + + ``thewalrus`` Ryser's algorithm permananet implementation is described here: https://the-walrus.readthedocs.io/en/latest/gallery/permanent_tutorial.html + + # TODO maybe implement subroutine if computation is taking forever. + + :param sax_input: The sax S-parameter dictionary. + :type sax_input: sax.SType + + :returns: The circuit permanent and the time it took to compute it. + :rtype: tuple + + +.. py:function:: unitary_permanent(unitary_matrix: jax.numpy.ndarray) -> tuple + + The permanent of a unitary is used to determine the state probability of combinatorial Gaussian boson samping systems. + + ``thewalrus`` Ryser's algorithm permananet implementation is described here: https://the-walrus.readthedocs.io/en/latest/gallery/permanent_tutorial.html + + Note that this function needs to be as optimised as possible, so we need to minimise our computational complexity of our operation. + + # TODO implement validation + # TODO maybe implement subroutine if computation is taking forever. + # TODO why two outputs? Understand this properly later. + + :param unitary_permanent: The unitary matrix. + :type unitary_permanent: np.ndarray + + :returns: The circuit permanent and the time it took to compute it. + :rtype: tuple + + +.. py:function:: sax_to_ideal_qutip_unitary(sax_input: sax.SType) + + This function converts the calculated S-parameters into a standard Unitary matrix topology so that the shape and + dimensions of the matrix can be observed. + + I think this means we need to transpose the output of the filtered sax SDense matrix to map it to a QuTip matrix. + Note that the documentation and formatting of the standard `sax` mapping to a S-parameter standard notation is + already in described in piel/piel/sax/utils.py. + + From this stage we can implement a ``QObj`` matrix accordingly and perform simulations accordingly. + https://qutip.org/docs/latest/guide/qip/qip-basics.html#unitaries + + For example, a ``qutip`` representation of an s-gate gate would be: + + ..code-block:: + + import numpy as np + import qutip + # S-Gate + s_gate_matrix = np.array([[1., 0], [0., 1.j]]) + s_gate = qutip.Qobj(mat, dims=[[2], [2]]) + + In mathematical notation, this S-gate would be written as: + + ..math:: + + S = \begin{bmatrix} + 1 & 0 \\ + 0 & i \\ + \end{bmatrix} + + :param sax_input: A dictionary of S-parameters in the form of a SDict from `sax`. + :type sax_input: sax.SType + + :returns: A QuTip QObj representation of the S-parameters in a unitary matrix. + :rtype: qobj_unitary (qutip.Qobj) + + +.. py:function:: fock_transition_probability_amplitude(initial_fock_state: qutip.Qobj, final_fock_state: qutip.Qobj, unitary_matrix: jax.numpy.ndarray) + + This function returns the transition probability amplitude between two Fock states when propagating in between + the unitary_matrix which represents a quantum state circuit. + + Note that based on (TODO cite Jeremy), the initial Fock state corresponds to the columns of the unitary and the + final Fock states corresponds to the rows of the unitary. + + .. math :: + + ewcommand{\ket}[1]{\left|{#1} + ight + angle} + + The subunitary :math:`U_{f_1}^{f_2}` is composed from the larger unitary by selecting the rows from the output state + Fock state occupation of :math:`\ket{f_2}`, and columns from the input :math:`\ket{f_1}`. In our case, we need to select the + columns indexes :math:`(0,3)` and rows indexes :math:`(1,2)`. + + If we consider a photon number of more than one for the transition Fock states, then the Permanent needs to be + normalised. The probability amplitude for the transition is described as: + + .. math :: + a(\ket{f_1} o \ket{f_2}) = + rac{ ext{per}(U_{f_1}^{f_2})}{\sqrt{(j_1! j_2! ... j_N!)(j_1^{'}! j_2^{'}! ... j_N^{'}!)}} + + Args: + initial_fock_state (qutip.Qobj): A QuTip QObj representation of the initial Fock state. + final_fock_state (qutip.Qobj): A QuTip QObj representation of the final Fock state. + unitary_matrix (jnp.ndarray): A JAX NumPy array representation of the unitary matrix. + + Returns: + float: The transition probability amplitude between the initial and final Fock states. diff --git a/docs/autoapi/piel/integration/sax_qutip/index.rst b/docs/autoapi/piel/integration/sax_qutip/index.rst new file mode 100644 index 00000000..fc93ce66 --- /dev/null +++ b/docs/autoapi/piel/integration/sax_qutip/index.rst @@ -0,0 +1,55 @@ +:py:mod:`piel.integration.sax_qutip` +==================================== + +.. py:module:: piel.integration.sax_qutip + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.integration.sax_qutip.sax_to_ideal_qutip_unitary + + + +.. py:function:: sax_to_ideal_qutip_unitary(sax_input: sax.SType) + + This function converts the calculated S-parameters into a standard Unitary matrix topology so that the shape and + dimensions of the matrix can be observed. + + I think this means we need to transpose the output of the filtered sax SDense matrix to map it to a QuTip matrix. + Note that the documentation and formatting of the standard `sax` mapping to a S-parameter standard notation is + already in described in piel/piel/sax/utils.py. + + From this stage we can implement a ``QObj`` matrix accordingly and perform simulations accordingly. + https://qutip.org/docs/latest/guide/qip/qip-basics.html#unitaries + + For example, a ``qutip`` representation of an s-gate gate would be: + + ..code-block:: + + import numpy as np + import qutip + # S-Gate + s_gate_matrix = np.array([[1., 0], [0., 1.j]]) + s_gate = qutip.Qobj(mat, dims=[[2], [2]]) + + In mathematical notation, this S-gate would be written as: + + ..math:: + + S = \begin{bmatrix} + 1 & 0 \\ + 0 & i \\ + \end{bmatrix} + + :param sax_input: A dictionary of S-parameters in the form of a SDict from `sax`. + :type sax_input: sax.SType + + :returns: A QuTip QObj representation of the S-parameters in a unitary matrix. + :rtype: qobj_unitary (qutip.Qobj) diff --git a/docs/autoapi/piel/integration/sax_thewalrus/index.rst b/docs/autoapi/piel/integration/sax_thewalrus/index.rst new file mode 100644 index 00000000..3e549d90 --- /dev/null +++ b/docs/autoapi/piel/integration/sax_thewalrus/index.rst @@ -0,0 +1,52 @@ +:py:mod:`piel.integration.sax_thewalrus` +======================================== + +.. py:module:: piel.integration.sax_thewalrus + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.integration.sax_thewalrus.unitary_permanent + piel.integration.sax_thewalrus.sax_circuit_permanent + + + +.. py:function:: unitary_permanent(unitary_matrix: jax.numpy.ndarray) -> tuple + + The permanent of a unitary is used to determine the state probability of combinatorial Gaussian boson samping systems. + + ``thewalrus`` Ryser's algorithm permananet implementation is described here: https://the-walrus.readthedocs.io/en/latest/gallery/permanent_tutorial.html + + Note that this function needs to be as optimised as possible, so we need to minimise our computational complexity of our operation. + + # TODO implement validation + # TODO maybe implement subroutine if computation is taking forever. + # TODO why two outputs? Understand this properly later. + + :param unitary_permanent: The unitary matrix. + :type unitary_permanent: np.ndarray + + :returns: The circuit permanent and the time it took to compute it. + :rtype: tuple + + +.. py:function:: sax_circuit_permanent(sax_input: sax.SType) -> tuple + + The permanent of a unitary is used to determine the state probability of combinatorial Gaussian boson samping systems. + + ``thewalrus`` Ryser's algorithm permananet implementation is described here: https://the-walrus.readthedocs.io/en/latest/gallery/permanent_tutorial.html + + # TODO maybe implement subroutine if computation is taking forever. + + :param sax_input: The sax S-parameter dictionary. + :type sax_input: sax.SType + + :returns: The circuit permanent and the time it took to compute it. + :rtype: tuple diff --git a/docs/autoapi/piel/integration/thewalrus_qutip/index.rst b/docs/autoapi/piel/integration/thewalrus_qutip/index.rst new file mode 100644 index 00000000..f8e87760 --- /dev/null +++ b/docs/autoapi/piel/integration/thewalrus_qutip/index.rst @@ -0,0 +1,51 @@ +:py:mod:`piel.integration.thewalrus_qutip` +========================================== + +.. py:module:: piel.integration.thewalrus_qutip + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.integration.thewalrus_qutip.fock_transition_probability_amplitude + + + +.. py:function:: fock_transition_probability_amplitude(initial_fock_state: qutip.Qobj, final_fock_state: qutip.Qobj, unitary_matrix: jax.numpy.ndarray) + + This function returns the transition probability amplitude between two Fock states when propagating in between + the unitary_matrix which represents a quantum state circuit. + + Note that based on (TODO cite Jeremy), the initial Fock state corresponds to the columns of the unitary and the + final Fock states corresponds to the rows of the unitary. + + .. math :: + + ewcommand{\ket}[1]{\left|{#1} + ight + angle} + + The subunitary :math:`U_{f_1}^{f_2}` is composed from the larger unitary by selecting the rows from the output state + Fock state occupation of :math:`\ket{f_2}`, and columns from the input :math:`\ket{f_1}`. In our case, we need to select the + columns indexes :math:`(0,3)` and rows indexes :math:`(1,2)`. + + If we consider a photon number of more than one for the transition Fock states, then the Permanent needs to be + normalised. The probability amplitude for the transition is described as: + + .. math :: + a(\ket{f_1} o \ket{f_2}) = + rac{ ext{per}(U_{f_1}^{f_2})}{\sqrt{(j_1! j_2! ... j_N!)(j_1^{'}! j_2^{'}! ... j_N^{'}!)}} + + Args: + initial_fock_state (qutip.Qobj): A QuTip QObj representation of the initial Fock state. + final_fock_state (qutip.Qobj): A QuTip QObj representation of the final Fock state. + unitary_matrix (jnp.ndarray): A JAX NumPy array representation of the unitary matrix. + + Returns: + float: The transition probability amplitude between the initial and final Fock states. diff --git a/docs/autoapi/piel/models/frequency/all/index.rst b/docs/autoapi/piel/models/frequency/all/index.rst new file mode 100644 index 00000000..689eadfe --- /dev/null +++ b/docs/autoapi/piel/models/frequency/all/index.rst @@ -0,0 +1,28 @@ +:py:mod:`piel.models.frequency.all` +=================================== + +.. py:module:: piel.models.frequency.all + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.frequency.all.get_all_models + + + +.. py:function:: get_all_models(custom_library: dict | None = None) -> dict + + Returns the default models dictionary. + + :param custom_library: Custom defaults dictionary. + :type custom_library: dict + + :returns: Default models dictionary. + :rtype: dict diff --git a/docs/autoapi/piel/models/frequency/defaults/index.rst b/docs/autoapi/piel/models/frequency/defaults/index.rst new file mode 100644 index 00000000..b0d211e0 --- /dev/null +++ b/docs/autoapi/piel/models/frequency/defaults/index.rst @@ -0,0 +1,28 @@ +:py:mod:`piel.models.frequency.defaults` +======================================== + +.. py:module:: piel.models.frequency.defaults + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.frequency.defaults.get_default_models + + + +.. py:function:: get_default_models(custom_defaults: dict | None = None) -> dict + + Returns the default models dictionary. + + :param custom_defaults: Custom defaults dictionary. + :type custom_defaults: dict + + :returns: Default models dictionary. + :rtype: dict diff --git a/docs/autoapi/piel/models/frequency/electrical/index.rst b/docs/autoapi/piel/models/frequency/electrical/index.rst new file mode 100644 index 00000000..94dd23aa --- /dev/null +++ b/docs/autoapi/piel/models/frequency/electrical/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.frequency.electrical` +========================================== + +.. py:module:: piel.models.frequency.electrical diff --git a/docs/autoapi/piel/models/frequency/electro_optic/ideal/index.rst b/docs/autoapi/piel/models/frequency/electro_optic/ideal/index.rst new file mode 100644 index 00000000..1237293a --- /dev/null +++ b/docs/autoapi/piel/models/frequency/electro_optic/ideal/index.rst @@ -0,0 +1,20 @@ +:py:mod:`piel.models.frequency.electro_optic.ideal` +=================================================== + +.. py:module:: piel.models.frequency.electro_optic.ideal + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.frequency.electro_optic.ideal.ideal_active_mzi2x2_2x2 + + + +.. py:function:: ideal_active_mzi2x2_2x2() diff --git a/docs/autoapi/piel/models/frequency/electro_optic/index.rst b/docs/autoapi/piel/models/frequency/electro_optic/index.rst new file mode 100644 index 00000000..370fd25c --- /dev/null +++ b/docs/autoapi/piel/models/frequency/electro_optic/index.rst @@ -0,0 +1,13 @@ +:py:mod:`piel.models.frequency.electro_optic` +============================================= + +.. py:module:: piel.models.frequency.electro_optic + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + ideal/index.rst diff --git a/docs/autoapi/piel/models/frequency/electronic/index.rst b/docs/autoapi/piel/models/frequency/electronic/index.rst new file mode 100644 index 00000000..fd8c6cca --- /dev/null +++ b/docs/autoapi/piel/models/frequency/electronic/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.frequency.electronic` +========================================== + +.. py:module:: piel.models.frequency.electronic diff --git a/docs/autoapi/piel/models/frequency/index.rst b/docs/autoapi/piel/models/frequency/index.rst new file mode 100644 index 00000000..f9f5b8cb --- /dev/null +++ b/docs/autoapi/piel/models/frequency/index.rst @@ -0,0 +1,76 @@ +:py:mod:`piel.models.frequency` +=============================== + +.. py:module:: piel.models.frequency + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + electrical/index.rst + electro_optic/index.rst + electronic/index.rst + opto_electronic/index.rst + photonic/index.rst + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + all/index.rst + defaults/index.rst + utils/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.frequency.compose_custom_model_library_from_defaults + piel.models.frequency.get_all_models + piel.models.frequency.get_default_models + + + +.. py:function:: compose_custom_model_library_from_defaults(custom_models: dict) -> dict + + Compose the default models with the custom models. + + :param custom_models: Custom models dictionary. + :type custom_models: dict + + :returns: Composed models dictionary. + :rtype: dict + + +.. py:function:: get_all_models(custom_library: dict | None = None) -> dict + + Returns the default models dictionary. + + :param custom_library: Custom defaults dictionary. + :type custom_library: dict + + :returns: Default models dictionary. + :rtype: dict + + +.. py:function:: get_default_models(custom_defaults: dict | None = None) -> dict + + Returns the default models dictionary. + + :param custom_defaults: Custom defaults dictionary. + :type custom_defaults: dict + + :returns: Default models dictionary. + :rtype: dict diff --git a/docs/autoapi/piel/models/frequency/opto_electronic/index.rst b/docs/autoapi/piel/models/frequency/opto_electronic/index.rst new file mode 100644 index 00000000..31f58a61 --- /dev/null +++ b/docs/autoapi/piel/models/frequency/opto_electronic/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.frequency.opto_electronic` +=============================================== + +.. py:module:: piel.models.frequency.opto_electronic diff --git a/docs/autoapi/piel/models/frequency/photonic/coupler_simple/index.rst b/docs/autoapi/piel/models/frequency/photonic/coupler_simple/index.rst new file mode 100644 index 00000000..7aa28347 --- /dev/null +++ b/docs/autoapi/piel/models/frequency/photonic/coupler_simple/index.rst @@ -0,0 +1,25 @@ +:py:mod:`piel.models.frequency.photonic.coupler_simple` +======================================================= + +.. py:module:: piel.models.frequency.photonic.coupler_simple + +.. autoapi-nested-parse:: + + Translated from https://github.com/flaport/sax or https://github.com/flaport/photontorch/tree/master + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.frequency.photonic.coupler_simple.coupler + + + +.. py:function:: coupler(coupling=0.5) diff --git a/docs/autoapi/piel/models/frequency/photonic/directional_coupler_length/index.rst b/docs/autoapi/piel/models/frequency/photonic/directional_coupler_length/index.rst new file mode 100644 index 00000000..76732fef --- /dev/null +++ b/docs/autoapi/piel/models/frequency/photonic/directional_coupler_length/index.rst @@ -0,0 +1,25 @@ +:py:mod:`piel.models.frequency.photonic.directional_coupler_length` +=================================================================== + +.. py:module:: piel.models.frequency.photonic.directional_coupler_length + +.. autoapi-nested-parse:: + + Translated from https://github.com/flaport/sax or https://github.com/flaport/photontorch/tree/master + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.frequency.photonic.directional_coupler_length.directional_coupler_with_length + + + +.. py:function:: directional_coupler_with_length(length=1e-05, coupling=0.5, loss=0, neff=2.34, wl0=1.55e-06, ng=3.4, phase=0) diff --git a/docs/autoapi/piel/models/frequency/photonic/directional_coupler_real/index.rst b/docs/autoapi/piel/models/frequency/photonic/directional_coupler_real/index.rst new file mode 100644 index 00000000..b5b9b2d3 --- /dev/null +++ b/docs/autoapi/piel/models/frequency/photonic/directional_coupler_real/index.rst @@ -0,0 +1,8 @@ +:py:mod:`piel.models.frequency.photonic.directional_coupler_real` +================================================================= + +.. py:module:: piel.models.frequency.photonic.directional_coupler_real + +.. autoapi-nested-parse:: + + Translated from https://github.com/flaport/sax or https://github.com/flaport/photontorch/tree/master diff --git a/docs/autoapi/piel/models/frequency/photonic/directional_coupler_simple/index.rst b/docs/autoapi/piel/models/frequency/photonic/directional_coupler_simple/index.rst new file mode 100644 index 00000000..607d0c75 --- /dev/null +++ b/docs/autoapi/piel/models/frequency/photonic/directional_coupler_simple/index.rst @@ -0,0 +1,25 @@ +:py:mod:`piel.models.frequency.photonic.directional_coupler_simple` +=================================================================== + +.. py:module:: piel.models.frequency.photonic.directional_coupler_simple + +.. autoapi-nested-parse:: + + Translated from https://github.com/flaport/sax or https://github.com/flaport/photontorch/tree/master + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.frequency.photonic.directional_coupler_simple.directional_coupler + + + +.. py:function:: directional_coupler(coupling=0.5) diff --git a/docs/autoapi/piel/models/frequency/photonic/grating_coupler/index.rst b/docs/autoapi/piel/models/frequency/photonic/grating_coupler/index.rst new file mode 100644 index 00000000..0bfd1bcc --- /dev/null +++ b/docs/autoapi/piel/models/frequency/photonic/grating_coupler/index.rst @@ -0,0 +1,25 @@ +:py:mod:`piel.models.frequency.photonic.grating_coupler` +======================================================== + +.. py:module:: piel.models.frequency.photonic.grating_coupler + +.. autoapi-nested-parse:: + + Translated from https://github.com/flaport/sax or https://github.com/flaport/photontorch/tree/master + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.frequency.photonic.grating_coupler.grating_coupler_simple + + + +.. py:function:: grating_coupler_simple(R=0.0, R_in=0.0, Tmax=1.0, bandwidth=6e-08, wl0=1.55e-06) diff --git a/docs/autoapi/piel/models/frequency/photonic/index.rst b/docs/autoapi/piel/models/frequency/photonic/index.rst new file mode 100644 index 00000000..1a3b66ef --- /dev/null +++ b/docs/autoapi/piel/models/frequency/photonic/index.rst @@ -0,0 +1,68 @@ +:py:mod:`piel.models.frequency.photonic` +======================================== + +.. py:module:: piel.models.frequency.photonic + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + coupler_simple/index.rst + directional_coupler_length/index.rst + directional_coupler_real/index.rst + directional_coupler_simple/index.rst + grating_coupler/index.rst + mmi1x2/index.rst + mmi2x2/index.rst + straight_waveguide/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.frequency.photonic.coupler + piel.models.frequency.photonic.directional_coupler_with_length + piel.models.frequency.photonic.directional_coupler + piel.models.frequency.photonic.grating_coupler_simple + piel.models.frequency.photonic.mmi1x2_50_50 + piel.models.frequency.photonic.mmi2x2_50_50 + piel.models.frequency.photonic.ideal_active_waveguide + piel.models.frequency.photonic.waveguide + piel.models.frequency.photonic.simple_straight + + + +.. py:function:: coupler(coupling=0.5) + + +.. py:function:: directional_coupler_with_length(length=1e-05, coupling=0.5, loss=0, neff=2.34, wl0=1.55e-06, ng=3.4, phase=0) + + +.. py:function:: directional_coupler(coupling=0.5) + + +.. py:function:: grating_coupler_simple(R=0.0, R_in=0.0, Tmax=1.0, bandwidth=6e-08, wl0=1.55e-06) + + +.. py:function:: mmi1x2_50_50() + + +.. py:function:: mmi2x2_50_50() + + +.. py:function:: ideal_active_waveguide(wl=1.55, wl0=1.55, neff=2.34, ng=3.4, length=10.0, loss=0.0, active_phase_rad=0.0) + + +.. py:function:: waveguide(wl=1.55, wl0=1.55, neff=2.34, ng=3.4, length=10.0, loss=0.0) + + +.. py:function:: simple_straight(length=10.0, width=0.5) diff --git a/docs/autoapi/piel/models/frequency/photonic/mmi1x2/index.rst b/docs/autoapi/piel/models/frequency/photonic/mmi1x2/index.rst new file mode 100644 index 00000000..9a381f4a --- /dev/null +++ b/docs/autoapi/piel/models/frequency/photonic/mmi1x2/index.rst @@ -0,0 +1,25 @@ +:py:mod:`piel.models.frequency.photonic.mmi1x2` +=============================================== + +.. py:module:: piel.models.frequency.photonic.mmi1x2 + +.. autoapi-nested-parse:: + + Translated from https://github.com/flaport/sax or https://github.com/flaport/photontorch/tree/master + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.frequency.photonic.mmi1x2.mmi1x2_50_50 + + + +.. py:function:: mmi1x2_50_50() diff --git a/docs/autoapi/piel/models/frequency/photonic/mmi2x2/index.rst b/docs/autoapi/piel/models/frequency/photonic/mmi2x2/index.rst new file mode 100644 index 00000000..389d19e0 --- /dev/null +++ b/docs/autoapi/piel/models/frequency/photonic/mmi2x2/index.rst @@ -0,0 +1,25 @@ +:py:mod:`piel.models.frequency.photonic.mmi2x2` +=============================================== + +.. py:module:: piel.models.frequency.photonic.mmi2x2 + +.. autoapi-nested-parse:: + + Translated from https://github.com/flaport/sax or https://github.com/flaport/photontorch/tree/master + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.frequency.photonic.mmi2x2.mmi2x2_50_50 + + + +.. py:function:: mmi2x2_50_50() diff --git a/docs/autoapi/piel/models/frequency/photonic/straight_waveguide/index.rst b/docs/autoapi/piel/models/frequency/photonic/straight_waveguide/index.rst new file mode 100644 index 00000000..72c7fc80 --- /dev/null +++ b/docs/autoapi/piel/models/frequency/photonic/straight_waveguide/index.rst @@ -0,0 +1,33 @@ +:py:mod:`piel.models.frequency.photonic.straight_waveguide` +=========================================================== + +.. py:module:: piel.models.frequency.photonic.straight_waveguide + +.. autoapi-nested-parse:: + + Translated from https://github.com/flaport/sax or https://github.com/flaport/photontorch/tree/master + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.frequency.photonic.straight_waveguide.waveguide + piel.models.frequency.photonic.straight_waveguide.ideal_active_waveguide + piel.models.frequency.photonic.straight_waveguide.simple_straight + + + +.. py:function:: waveguide(wl=1.55, wl0=1.55, neff=2.34, ng=3.4, length=10.0, loss=0.0) + + +.. py:function:: ideal_active_waveguide(wl=1.55, wl0=1.55, neff=2.34, ng=3.4, length=10.0, loss=0.0, active_phase_rad=0.0) + + +.. py:function:: simple_straight(length=10.0, width=0.5) diff --git a/docs/autoapi/piel/models/frequency/utils/index.rst b/docs/autoapi/piel/models/frequency/utils/index.rst new file mode 100644 index 00000000..65b796dd --- /dev/null +++ b/docs/autoapi/piel/models/frequency/utils/index.rst @@ -0,0 +1,28 @@ +:py:mod:`piel.models.frequency.utils` +===================================== + +.. py:module:: piel.models.frequency.utils + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.frequency.utils.compose_custom_model_library_from_defaults + + + +.. py:function:: compose_custom_model_library_from_defaults(custom_models: dict) -> dict + + Compose the default models with the custom models. + + :param custom_models: Custom models dictionary. + :type custom_models: dict + + :returns: Composed models dictionary. + :rtype: dict diff --git a/docs/autoapi/piel/models/index.rst b/docs/autoapi/piel/models/index.rst new file mode 100644 index 00000000..02901f7f --- /dev/null +++ b/docs/autoapi/piel/models/index.rst @@ -0,0 +1,25 @@ +:py:mod:`piel.models` +===================== + +.. py:module:: piel.models + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + frequency/index.rst + logic/index.rst + physical/index.rst + transient/index.rst + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + utils/index.rst diff --git a/docs/autoapi/piel/models/logic/electrical/index.rst b/docs/autoapi/piel/models/logic/electrical/index.rst new file mode 100644 index 00000000..fce3722c --- /dev/null +++ b/docs/autoapi/piel/models/logic/electrical/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.logic.electrical` +====================================== + +.. py:module:: piel.models.logic.electrical diff --git a/docs/autoapi/piel/models/logic/electro_optic/index.rst b/docs/autoapi/piel/models/logic/electro_optic/index.rst new file mode 100644 index 00000000..799d50eb --- /dev/null +++ b/docs/autoapi/piel/models/logic/electro_optic/index.rst @@ -0,0 +1,68 @@ +:py:mod:`piel.models.logic.electro_optic` +========================================= + +.. py:module:: piel.models.logic.electro_optic + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + signal_mapping/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.logic.electro_optic.bits_array_from_bits_amount + piel.models.logic.electro_optic.linear_bit_phase_map + piel.models.logic.electro_optic.return_phase_array_from_data_series + + + +.. py:function:: bits_array_from_bits_amount(bits_amount: int) -> numpy.ndarray + + Returns an array of bits from a given amount of bits. + + :param bits_amount: Amount of bits to generate. + :type bits_amount: int + + :returns: Array of bits. + :rtype: bit_array(np.ndarray) + + +.. py:function:: linear_bit_phase_map(bits_amount: int, final_phase_rad: float, initial_phase_rad: float = 0, return_dataframe: bool = True, quantization_error: float = 1e-06) -> dict | pandas.DataFrame + + Returns a linear direct mapping of bits to phase. + + :param bits_amount: Amount of bits to generate. + :type bits_amount: int + :param final_phase_rad: Final phase to map to. + :type final_phase_rad: float + :param initial_phase_rad: Initial phase to map to. + :type initial_phase_rad: float + + :returns: Mapping of bits to phase. + :rtype: bit_phase_mapping(dict) + + +.. py:function:: return_phase_array_from_data_series(data_series: pandas.Series, phase_map: pandas.DataFrame | pandas.Series) -> list + + Returns a list of phases from a given data series and phase map. + # TODO optimise lookup table speed + + :param data_series: Data series to map. + :type data_series: pd.Series + :param phase_map: Phase map to use. + :type phase_map: pd.DataFrame | pd.Series + + :returns: List of phases. + :rtype: phase_array(list) diff --git a/docs/autoapi/piel/models/logic/electro_optic/signal_mapping/index.rst b/docs/autoapi/piel/models/logic/electro_optic/signal_mapping/index.rst new file mode 100644 index 00000000..638ed61e --- /dev/null +++ b/docs/autoapi/piel/models/logic/electro_optic/signal_mapping/index.rst @@ -0,0 +1,80 @@ +:py:mod:`piel.models.logic.electro_optic.signal_mapping` +======================================================== + +.. py:module:: piel.models.logic.electro_optic.signal_mapping + +.. autoapi-nested-parse:: + + In this function we implement different methods of mapping electronic signals to phase. + + One particular implementation of phase mapping would be: + + .. list-table:: Example Basic Phase Mapping + :header-rows: 1 + + * - Bit + - Phase + * - b0 + - :math:`\phi_0 \to 0` + * - b1 + - :math:`\phi_1 \to \pi` + + We can define the two corresponding angles that this would be. + + A more complex implementation of phase mapping can be similar to a DAC mapping: a bitstring within a converter bit-size can map directly to a particular phase space within a particular mapping. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.logic.electro_optic.signal_mapping.bits_array_from_bits_amount + piel.models.logic.electro_optic.signal_mapping.linear_bit_phase_map + piel.models.logic.electro_optic.signal_mapping.return_phase_array_from_data_series + + + +.. py:function:: bits_array_from_bits_amount(bits_amount: int) -> numpy.ndarray + + Returns an array of bits from a given amount of bits. + + :param bits_amount: Amount of bits to generate. + :type bits_amount: int + + :returns: Array of bits. + :rtype: bit_array(np.ndarray) + + +.. py:function:: linear_bit_phase_map(bits_amount: int, final_phase_rad: float, initial_phase_rad: float = 0, return_dataframe: bool = True, quantization_error: float = 1e-06) -> dict | pandas.DataFrame + + Returns a linear direct mapping of bits to phase. + + :param bits_amount: Amount of bits to generate. + :type bits_amount: int + :param final_phase_rad: Final phase to map to. + :type final_phase_rad: float + :param initial_phase_rad: Initial phase to map to. + :type initial_phase_rad: float + + :returns: Mapping of bits to phase. + :rtype: bit_phase_mapping(dict) + + +.. py:function:: return_phase_array_from_data_series(data_series: pandas.Series, phase_map: pandas.DataFrame | pandas.Series) -> list + + Returns a list of phases from a given data series and phase map. + # TODO optimise lookup table speed + + :param data_series: Data series to map. + :type data_series: pd.Series + :param phase_map: Phase map to use. + :type phase_map: pd.DataFrame | pd.Series + + :returns: List of phases. + :rtype: phase_array(list) diff --git a/docs/autoapi/piel/models/logic/electronic/index.rst b/docs/autoapi/piel/models/logic/electronic/index.rst new file mode 100644 index 00000000..5fe874cd --- /dev/null +++ b/docs/autoapi/piel/models/logic/electronic/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.logic.electronic` +====================================== + +.. py:module:: piel.models.logic.electronic diff --git a/docs/autoapi/piel/models/logic/index.rst b/docs/autoapi/piel/models/logic/index.rst new file mode 100644 index 00000000..673eb1e8 --- /dev/null +++ b/docs/autoapi/piel/models/logic/index.rst @@ -0,0 +1,17 @@ +:py:mod:`piel.models.logic` +=========================== + +.. py:module:: piel.models.logic + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + electrical/index.rst + electro_optic/index.rst + electronic/index.rst + opto_electronic/index.rst + photonic/index.rst diff --git a/docs/autoapi/piel/models/logic/opto_electronic/index.rst b/docs/autoapi/piel/models/logic/opto_electronic/index.rst new file mode 100644 index 00000000..b8f9e55e --- /dev/null +++ b/docs/autoapi/piel/models/logic/opto_electronic/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.logic.opto_electronic` +=========================================== + +.. py:module:: piel.models.logic.opto_electronic diff --git a/docs/autoapi/piel/models/logic/photonic/index.rst b/docs/autoapi/piel/models/logic/photonic/index.rst new file mode 100644 index 00000000..576ba33c --- /dev/null +++ b/docs/autoapi/piel/models/logic/photonic/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.logic.photonic` +==================================== + +.. py:module:: piel.models.logic.photonic diff --git a/docs/autoapi/piel/models/physical/electrical/cable/index.rst b/docs/autoapi/piel/models/physical/electrical/cable/index.rst new file mode 100644 index 00000000..14488ede --- /dev/null +++ b/docs/autoapi/piel/models/physical/electrical/cable/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.physical.electrical.cable` +=============================================== + +.. py:module:: piel.models.physical.electrical.cable diff --git a/docs/autoapi/piel/models/physical/electrical/index.rst b/docs/autoapi/piel/models/physical/electrical/index.rst new file mode 100644 index 00000000..90daed94 --- /dev/null +++ b/docs/autoapi/piel/models/physical/electrical/index.rst @@ -0,0 +1,13 @@ +:py:mod:`piel.models.physical.electrical` +========================================= + +.. py:module:: piel.models.physical.electrical + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + cable/index.rst diff --git a/docs/autoapi/piel/models/physical/electro_optic/basic_heater/index.rst b/docs/autoapi/piel/models/physical/electro_optic/basic_heater/index.rst new file mode 100644 index 00000000..d8b0d604 --- /dev/null +++ b/docs/autoapi/piel/models/physical/electro_optic/basic_heater/index.rst @@ -0,0 +1,22 @@ +:py:mod:`piel.models.physical.electro_optic.basic_heater` +========================================================= + +.. py:module:: piel.models.physical.electro_optic.basic_heater + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.physical.electro_optic.basic_heater.basic_heater_spice + + + +.. py:function:: basic_heater_spice() + + This function returns the most basic SPICE model for a heater, that can be closely integrated with circuit solvers accordingly. diff --git a/docs/autoapi/piel/models/physical/electro_optic/index.rst b/docs/autoapi/piel/models/physical/electro_optic/index.rst new file mode 100644 index 00000000..7d81fcd8 --- /dev/null +++ b/docs/autoapi/piel/models/physical/electro_optic/index.rst @@ -0,0 +1,13 @@ +:py:mod:`piel.models.physical.electro_optic` +============================================ + +.. py:module:: piel.models.physical.electro_optic + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + basic_heater/index.rst diff --git a/docs/autoapi/piel/models/physical/electronic/capacitor/index.rst b/docs/autoapi/piel/models/physical/electronic/capacitor/index.rst new file mode 100644 index 00000000..e09c8a2d --- /dev/null +++ b/docs/autoapi/piel/models/physical/electronic/capacitor/index.rst @@ -0,0 +1,51 @@ +:py:mod:`piel.models.physical.electronic.capacitor` +=================================================== + +.. py:module:: piel.models.physical.electronic.capacitor + +.. autoapi-nested-parse:: + + # TODO move and update. + The way each of these models should work is that they use the settings from the `gdsfactory` component, + to create a parametric SPICE directive. + + These functions map a particular model, with an instance representation that corresponds to the given netlist + connectivity, and returns a SPICE representation of the circuit. This function will be called after parsing the + circuit netlist accordingly, and creating a mapping from the instance definitions to the fundamental components. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.physical.electronic.capacitor.add_basic_capacitor + + + +.. py:function:: add_basic_capacitor(settings) -> str + + This function takes in the settings from a gdsfactory component, some connectivity node translated directly from + the gdsfactory netlist. + + See Mike Smith “WinSpice3 User’s Manual” 25 October, 1999 + + SPICE capacitor model: + + .. code-block:: + + CXXXXXXX N+ N- VALUE + + Where the parameters are: + + .. code-block:: + + N+ = the positive terminal + N- = the negative terminal + VALUE = capacitance in farads + = starting voltage in a simulation diff --git a/docs/autoapi/piel/models/physical/electronic/defaults/index.rst b/docs/autoapi/piel/models/physical/electronic/defaults/index.rst new file mode 100644 index 00000000..bd498b2c --- /dev/null +++ b/docs/autoapi/piel/models/physical/electronic/defaults/index.rst @@ -0,0 +1,28 @@ +:py:mod:`piel.models.physical.electronic.defaults` +================================================== + +.. py:module:: piel.models.physical.electronic.defaults + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.physical.electronic.defaults.get_default_models + + + +.. py:function:: get_default_models(custom_defaults: dict | None = None) -> dict + + Returns the default models dictionary. + + :param custom_defaults: Custom defaults dictionary. + :type custom_defaults: dict + + :returns: Default models dictionary. + :rtype: dict diff --git a/docs/autoapi/piel/models/physical/electronic/index.rst b/docs/autoapi/piel/models/physical/electronic/index.rst new file mode 100644 index 00000000..f4b61b4b --- /dev/null +++ b/docs/autoapi/piel/models/physical/electronic/index.rst @@ -0,0 +1,67 @@ +:py:mod:`piel.models.physical.electronic` +========================================= + +.. py:module:: piel.models.physical.electronic + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + capacitor/index.rst + defaults/index.rst + resistor/index.rst + straight/index.rst + taper/index.rst + via_stack/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.physical.electronic.add_basic_capacitor + piel.models.physical.electronic.get_default_models + + + +.. py:function:: add_basic_capacitor(settings) -> str + + This function takes in the settings from a gdsfactory component, some connectivity node translated directly from + the gdsfactory netlist. + + See Mike Smith “WinSpice3 User’s Manual” 25 October, 1999 + + SPICE capacitor model: + + .. code-block:: + + CXXXXXXX N+ N- VALUE + + Where the parameters are: + + .. code-block:: + + N+ = the positive terminal + N- = the negative terminal + VALUE = capacitance in farads + = starting voltage in a simulation + + + +.. py:function:: get_default_models(custom_defaults: dict | None = None) -> dict + + Returns the default models dictionary. + + :param custom_defaults: Custom defaults dictionary. + :type custom_defaults: dict + + :returns: Default models dictionary. + :rtype: dict diff --git a/docs/autoapi/piel/models/physical/electronic/resistor/index.rst b/docs/autoapi/piel/models/physical/electronic/resistor/index.rst new file mode 100644 index 00000000..9ba99a84 --- /dev/null +++ b/docs/autoapi/piel/models/physical/electronic/resistor/index.rst @@ -0,0 +1,33 @@ +:py:mod:`piel.models.physical.electronic.resistor` +================================================== + +.. py:module:: piel.models.physical.electronic.resistor + +.. autoapi-nested-parse:: + + SPICE Resistor Structure + + See Mike Smith “WinSpice3 User’s Manual” 25 October, 1999 + + .. code-block:: spice + + RXXXXXXX N1 N2 + + Where the terminals are: + + .. code-block:: + + N1 = the first terminal + N2 = the second terminal + = resistance in ohms. + = name of the model used (useful for semiconductor resistors) + = length of the resistor (useful for semiconductor resistors) + = width of the resistor (useful for semiconductor resistors) + = temperature of the resistor in Kelvin (useful in noise analysis and + semiconductor resistors) + + An example is: + + .. code-block:: + + RHOT n1 n2 10k TEMP=500 diff --git a/docs/autoapi/piel/models/physical/electronic/straight/index.rst b/docs/autoapi/piel/models/physical/electronic/straight/index.rst new file mode 100644 index 00000000..68653984 --- /dev/null +++ b/docs/autoapi/piel/models/physical/electronic/straight/index.rst @@ -0,0 +1,36 @@ +:py:mod:`piel.models.physical.electronic.straight` +================================================== + +.. py:module:: piel.models.physical.electronic.straight + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + piel.models.physical.electronic.straight.StraightParameters + + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.physical.electronic.straight.straight + + + +.. py:class:: StraightParameters + + + These are all the potential parametric configuration variables + + +.. py:function:: straight(params: StraightParameters) -> hdl21.Module + + Implements a `hdl21` taper resistor class. diff --git a/docs/autoapi/piel/models/physical/electronic/taper/index.rst b/docs/autoapi/piel/models/physical/electronic/taper/index.rst new file mode 100644 index 00000000..6d579892 --- /dev/null +++ b/docs/autoapi/piel/models/physical/electronic/taper/index.rst @@ -0,0 +1,34 @@ +:py:mod:`piel.models.physical.electronic.taper` +=============================================== + +.. py:module:: piel.models.physical.electronic.taper + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + piel.models.physical.electronic.taper.TaperParameters + + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.physical.electronic.taper.taper + + + +.. py:class:: TaperParameters + + + +.. py:function:: taper(params: TaperParameters) -> hdl21.Module + + Implements a `hdl21` taper resistor class. We need to include the mapping ports as we expect our gdsfactory component to be with the instance of the model. diff --git a/docs/autoapi/piel/models/physical/electronic/via_stack/index.rst b/docs/autoapi/piel/models/physical/electronic/via_stack/index.rst new file mode 100644 index 00000000..5f9cf67a --- /dev/null +++ b/docs/autoapi/piel/models/physical/electronic/via_stack/index.rst @@ -0,0 +1,34 @@ +:py:mod:`piel.models.physical.electronic.via_stack` +=================================================== + +.. py:module:: piel.models.physical.electronic.via_stack + + +Module Contents +--------------- + +Classes +~~~~~~~ + +.. autoapisummary:: + + piel.models.physical.electronic.via_stack.ViaStackParameters + + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.physical.electronic.via_stack.via_stack + + + +.. py:class:: ViaStackParameters + + + +.. py:function:: via_stack(params: ViaStackParameters) -> hdl21.Module + + Implements a `hdl21` taper resistor class. We need to include the mapping ports as we expect our gdsfactory component to be with the instance of the model. diff --git a/docs/autoapi/piel/models/physical/geometry/index.rst b/docs/autoapi/piel/models/physical/geometry/index.rst new file mode 100644 index 00000000..55025870 --- /dev/null +++ b/docs/autoapi/piel/models/physical/geometry/index.rst @@ -0,0 +1,28 @@ +:py:mod:`piel.models.physical.geometry` +======================================= + +.. py:module:: piel.models.physical.geometry + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.physical.geometry.calculate_cross_sectional_area_m2 + + + +.. py:function:: calculate_cross_sectional_area_m2(diameter_m: float) -> float + + Calculates the cross sectional area of a circle in meters squared. + + :param diameter_m: Diameter of the circle in meters. + :type diameter_m: float + + :returns: Cross sectional area in meters squared. + :rtype: float diff --git a/docs/autoapi/piel/models/physical/index.rst b/docs/autoapi/piel/models/physical/index.rst new file mode 100644 index 00000000..dbf3a9ef --- /dev/null +++ b/docs/autoapi/piel/models/physical/index.rst @@ -0,0 +1,66 @@ +:py:mod:`piel.models.physical` +============================== + +.. py:module:: piel.models.physical + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + electrical/index.rst + electro_optic/index.rst + electronic/index.rst + opto_electronic/index.rst + photonic/index.rst + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + geometry/index.rst + thermal/index.rst + units/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.physical.calculate_cross_sectional_area_m2 + piel.models.physical.convert_awg_to_m2 + + + +.. py:function:: calculate_cross_sectional_area_m2(diameter_m: float) -> float + + Calculates the cross sectional area of a circle in meters squared. + + :param diameter_m: Diameter of the circle in meters. + :type diameter_m: float + + :returns: Cross sectional area in meters squared. + :rtype: float + + +.. py:function:: convert_awg_to_m2(awg: int) -> float + + Converts an AWG value to meters squared. + + Reference: https://en.wikipedia.org/wiki/American_wire_gauge + + :param awg: AWG value. + :type awg: ing + + :returns: Cross sectional area in meters squared. + :rtype: float diff --git a/docs/autoapi/piel/models/physical/opto_electronic/index.rst b/docs/autoapi/piel/models/physical/opto_electronic/index.rst new file mode 100644 index 00000000..98714753 --- /dev/null +++ b/docs/autoapi/piel/models/physical/opto_electronic/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.physical.opto_electronic` +============================================== + +.. py:module:: piel.models.physical.opto_electronic diff --git a/docs/autoapi/piel/models/physical/photonic/index.rst b/docs/autoapi/piel/models/physical/photonic/index.rst new file mode 100644 index 00000000..6d9dbf87 --- /dev/null +++ b/docs/autoapi/piel/models/physical/photonic/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.physical.photonic` +======================================= + +.. py:module:: piel.models.physical.photonic diff --git a/docs/autoapi/piel/models/physical/thermal/index.rst b/docs/autoapi/piel/models/physical/thermal/index.rst new file mode 100644 index 00000000..fdaf5438 --- /dev/null +++ b/docs/autoapi/piel/models/physical/thermal/index.rst @@ -0,0 +1,20 @@ +:py:mod:`piel.models.physical.thermal` +====================================== + +.. py:module:: piel.models.physical.thermal + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.physical.thermal.heat_transfer_1d_W + + + +.. py:function:: heat_transfer_1d_W(thermal_conductivity_fit, temperature_range_K, cross_sectional_area_m2, length_m) -> float diff --git a/docs/autoapi/piel/models/physical/units/index.rst b/docs/autoapi/piel/models/physical/units/index.rst new file mode 100644 index 00000000..0a2c2805 --- /dev/null +++ b/docs/autoapi/piel/models/physical/units/index.rst @@ -0,0 +1,30 @@ +:py:mod:`piel.models.physical.units` +==================================== + +.. py:module:: piel.models.physical.units + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.models.physical.units.convert_awg_to_m2 + + + +.. py:function:: convert_awg_to_m2(awg: int) -> float + + Converts an AWG value to meters squared. + + Reference: https://en.wikipedia.org/wiki/American_wire_gauge + + :param awg: AWG value. + :type awg: ing + + :returns: Cross sectional area in meters squared. + :rtype: float diff --git a/docs/autoapi/piel/models/transient/electrical/index.rst b/docs/autoapi/piel/models/transient/electrical/index.rst new file mode 100644 index 00000000..99b07461 --- /dev/null +++ b/docs/autoapi/piel/models/transient/electrical/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.transient.electrical` +========================================== + +.. py:module:: piel.models.transient.electrical diff --git a/docs/autoapi/piel/models/transient/electro_optic/index.rst b/docs/autoapi/piel/models/transient/electro_optic/index.rst new file mode 100644 index 00000000..9fc84c00 --- /dev/null +++ b/docs/autoapi/piel/models/transient/electro_optic/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.transient.electro_optic` +============================================= + +.. py:module:: piel.models.transient.electro_optic diff --git a/docs/autoapi/piel/models/transient/electronic/index.rst b/docs/autoapi/piel/models/transient/electronic/index.rst new file mode 100644 index 00000000..ea897279 --- /dev/null +++ b/docs/autoapi/piel/models/transient/electronic/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.transient.electronic` +========================================== + +.. py:module:: piel.models.transient.electronic diff --git a/docs/autoapi/piel/models/transient/index.rst b/docs/autoapi/piel/models/transient/index.rst new file mode 100644 index 00000000..3fdfb58c --- /dev/null +++ b/docs/autoapi/piel/models/transient/index.rst @@ -0,0 +1,17 @@ +:py:mod:`piel.models.transient` +=============================== + +.. py:module:: piel.models.transient + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + electrical/index.rst + electro_optic/index.rst + electronic/index.rst + opto_electronic/index.rst + photonic/index.rst diff --git a/docs/autoapi/piel/models/transient/opto_electronic/index.rst b/docs/autoapi/piel/models/transient/opto_electronic/index.rst new file mode 100644 index 00000000..cae56d94 --- /dev/null +++ b/docs/autoapi/piel/models/transient/opto_electronic/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.transient.opto_electronic` +=============================================== + +.. py:module:: piel.models.transient.opto_electronic diff --git a/docs/autoapi/piel/models/transient/photonic/index.rst b/docs/autoapi/piel/models/transient/photonic/index.rst new file mode 100644 index 00000000..5bed85a6 --- /dev/null +++ b/docs/autoapi/piel/models/transient/photonic/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.transient.photonic` +======================================== + +.. py:module:: piel.models.transient.photonic diff --git a/docs/autoapi/piel/models/utils/index.rst b/docs/autoapi/piel/models/utils/index.rst new file mode 100644 index 00000000..0a73a516 --- /dev/null +++ b/docs/autoapi/piel/models/utils/index.rst @@ -0,0 +1,4 @@ +:py:mod:`piel.models.utils` +=========================== + +.. py:module:: piel.models.utils diff --git a/docs/autoapi/piel/parametric/index.rst b/docs/autoapi/piel/parametric/index.rst new file mode 100644 index 00000000..7aadddd1 --- /dev/null +++ b/docs/autoapi/piel/parametric/index.rst @@ -0,0 +1,66 @@ +:py:mod:`piel.parametric` +========================= + +.. py:module:: piel.parametric + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.parametric.single_parameter_sweep + piel.parametric.multi_parameter_sweep + + + +.. py:function:: single_parameter_sweep(base_design_configuration: dict, parameter_name: str, parameter_sweep_values: list) + + This function takes a base_design_configuration dictionary and sweeps a single parameter over a list of values. It returns a list of dictionaries that correspond to the parameter sweep. + + :param base_design_configuration: Base design configuration dictionary. + :type base_design_configuration: dict + :param parameter_name: Name of parameter to sweep. + :type parameter_name: str + :param parameter_sweep_values: List of values to sweep. + :type parameter_sweep_values: list + + :returns: List of dictionaries that correspond to the parameter sweep. + :rtype: parameter_sweep_design_dictionary_array(list) + + +.. py:function:: multi_parameter_sweep(base_design_configuration: dict, parameter_sweep_dictionary: dict) -> list + + This multiparameter sweep is pretty cool, as it will generate designer list of dictionaries that comprise of all the possible combinations of your parameter sweeps. For example, if you are sweeping `parameter_1 = np.arange(0, 2) = array([0, 1])`, and `parameter_2 = np.arange(2, 4) = array([2, 3])`, then this function will generate list of dictionaries based on the default_design dictionary, but that will comprise of all the potential parameter combinations within this list. + + For the example above, there arould be 4 combinations [(0, 2), (0, 3), (1, 2), (1, 3)]. + + If you were instead sweeping for `parameter_1 = np.arange(0, 5)` and `parameter_2 = np.arange(0, 5)`, the dictionary generated would correspond to these parameter combinations of:: + [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 1), (1, 2), (1, 3), (1, 4), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 0), (3, 1), (3, 2), (3, 3), (3, 4), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]. + + Make sure to use the parameter_names from default_design when writing up the parameter_sweep dictionary key name. + + Example project_structure formats:: + + example_parameter_sweep_dictionary = { + "parameter_1": np.arange(1, -40, 1), + "parameter_2": np.arange(1, -40, 1), + } + + example_base_design_configuration = { + "parameter_1": 10.0, + "parameter_2": 40.0, + "parameter_3": 0, + } + + :param base_design_configuration: Dictionary of the default design configuration. + :type base_design_configuration: dict + :param parameter_sweep_dictionary: Dictionary of the parameter sweep. The keys should be the same as the keys in the base_design_configuration dictionary. + :type parameter_sweep_dictionary: dict + + :returns: List of dictionaries that comprise of all the possible combinations of your parameter sweeps. + :rtype: parameter_sweep_design_dictionary_array(list) diff --git a/docs/autoapi/piel/project_structure/index.rst b/docs/autoapi/piel/project_structure/index.rst new file mode 100644 index 00000000..08a25c02 --- /dev/null +++ b/docs/autoapi/piel/project_structure/index.rst @@ -0,0 +1,44 @@ +:py:mod:`piel.project_structure` +================================ + +.. py:module:: piel.project_structure + +.. autoapi-nested-parse:: + + This file allows us to automate several aspects of creating a fully compatible project structure. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.project_structure.read_configuration + piel.project_structure.create_setup_py_from_config_json + + + +.. py:function:: read_configuration(design_directory: piel.config.piel_path_types) -> dict + + This function reads the configuration file found in the design directory. + + :param design_directory: Design directory PATH. + :type design_directory: piel_path_types + + :returns: Configuration dictionary. + :rtype: config_dictionary(dict) + + +.. py:function:: create_setup_py_from_config_json(design_directory: piel.config.piel_path_types) -> None + + This function creates a setup.py file from the config.json file found in the design directory. + + :param design_directory: Design directory PATH or module name. + :type design_directory: piel_path_types + + :returns: None diff --git a/docs/autoapi/piel/tools/cocotb/core/index.rst b/docs/autoapi/piel/tools/cocotb/core/index.rst new file mode 100644 index 00000000..e4d03e46 --- /dev/null +++ b/docs/autoapi/piel/tools/cocotb/core/index.rst @@ -0,0 +1,118 @@ +:py:mod:`piel.tools.cocotb.core` +================================ + +.. py:module:: piel.tools.cocotb.core + +.. autoapi-nested-parse:: + + The objective of this file is to provide the simulation ports and interconnection to consider modelling digital and mixed signal logic. + + The main simulation driver is cocotb, and this generates a set of files that correspond to time-domain digital + simulations. The cocotb verification software can also be used to perform mixed signal simulation, and digital data + can be inputted as a bitstream into a photonic solver, although the ideal situation would be to have integrated + photonic time-domain models alongside the electronic simulation solver, and maybe this is where it will go. It can be + assumed that, as is currently, cocotb can interface python with multiple solvers until someone (and I'd love to do + this) writes an equivalent python-based or C++ based python time-domain simulation solver. + + The nice thing about cocotb is that as long as the photonic simulations can be written asynchronously, time-domain + simulations can be closely integrated or simulated through this verification software. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.cocotb.core.check_cocotb_testbench_exists + piel.tools.cocotb.core.configure_cocotb_simulation + piel.tools.cocotb.core.run_cocotb_simulation + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.cocotb.core.delete_simulation_output_files + + +.. py:function:: check_cocotb_testbench_exists(design_directory: str | pathlib.Path) -> bool + + Checks if a cocotb testbench exists in the design directory. + + :param design_directory: Design directory. + :type design_directory: str | pathlib.Path + + :returns: True if cocotb testbench exists. + :rtype: cocotb_testbench_exists(bool) + + +.. py:function:: configure_cocotb_simulation(design_directory: str | pathlib.Path, simulator: Literal[icarus, verilator], top_level_language: Literal[verilog, vhdl], top_level_verilog_module: str, test_python_module: str, design_sources_list: list | None = None) + + Writes a cocotb makefile. + + If no design_sources_list is provided then it adds all the design sources under the `src` folder. + + In the form + .. code-block:: + + #!/bin/sh + # Makefile + # defaults + SIM ?= icarus + TOPLEVEL_LANG ?= verilog + + # Note we need to include the test script to the PYTHONPATH + export PYTHONPATH = + + VERILOG_SOURCES += $(PWD)/my_design.sv + # use VHDL_SOURCES for VHDL files + + # TOPLEVEL is the name of the toplevel module in your Verilog or VHDL file + TOPLEVEL := my_design + + # MODULE is the basename of the Python test file + MODULE := test_my_design + + # include cocotb's make rules to take care of the simulator setup + include $(shell cocotb-config --makefiles)/Makefile.sim + + + :param design_directory: The directory where the design is located. + :type design_directory: str | pathlib.Path + :param simulator: The simulator to use. + :type simulator: Literal["icarus", "verilator"] + :param top_level_language: The top level language. + :type top_level_language: Literal["verilog", "vhdl"] + :param top_level_verilog_module: The top level verilog module. + :type top_level_verilog_module: str + :param test_python_module: The test python module. + :type test_python_module: str + :param design_sources_list: A list of design sources. Defaults to None. + :type design_sources_list: list | None, optional + + :returns: None + + +.. py:data:: delete_simulation_output_files + + + +.. py:function:: run_cocotb_simulation(design_directory: str) -> subprocess.CompletedProcess + + Equivalent to running the cocotb makefile + .. code-block:: + + make + + :param design_directory: The directory where the design is located. + :type design_directory: str + + :returns: The subprocess.CompletedProcess object. + :rtype: subprocess.CompletedProcess diff --git a/docs/autoapi/piel/tools/cocotb/data/index.rst b/docs/autoapi/piel/tools/cocotb/data/index.rst new file mode 100644 index 00000000..909b942d --- /dev/null +++ b/docs/autoapi/piel/tools/cocotb/data/index.rst @@ -0,0 +1,61 @@ +:py:mod:`piel.tools.cocotb.data` +================================ + +.. py:module:: piel.tools.cocotb.data + +.. autoapi-nested-parse:: + + This file contains a range of functions used to read, plot and analyse cocotb simulations in a data-flow standard as suggested + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.cocotb.data.get_simulation_output_files_from_design + piel.tools.cocotb.data.read_simulation_data + piel.tools.cocotb.data.simple_plot_simulation_data + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.cocotb.data.get_simulation_output_files + + +.. py:data:: get_simulation_output_files + + + +.. py:function:: get_simulation_output_files_from_design(design_directory: piel.config.piel_path_types, extension: str = 'csv') + + This function returns a list of all the simulation output files in the design directory. + + :param design_directory: The path to the design directory. + :type design_directory: piel_path_types + + :returns: List of all the simulation output files in the design directory. + :rtype: output_files (list) + + +.. py:function:: read_simulation_data(file_path: piel.config.piel_path_types) + + This function returns a Pandas dataframe that contains all the simulation data outputted from the simulation run. + + :param file_path: The path to the simulation data file. + :type file_path: piel_path_types + + :returns: The simulation data in a Pandas dataframe. + :rtype: simulation_data (pd.DataFrame) + + +.. py:function:: simple_plot_simulation_data(simulation_data: pandas.DataFrame) diff --git a/docs/autoapi/piel/tools/cocotb/index.rst b/docs/autoapi/piel/tools/cocotb/index.rst new file mode 100644 index 00000000..c8bd82b5 --- /dev/null +++ b/docs/autoapi/piel/tools/cocotb/index.rst @@ -0,0 +1,146 @@ +:py:mod:`piel.tools.cocotb` +=========================== + +.. py:module:: piel.tools.cocotb + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + core/index.rst + data/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.cocotb.check_cocotb_testbench_exists + piel.tools.cocotb.configure_cocotb_simulation + piel.tools.cocotb.run_cocotb_simulation + piel.tools.cocotb.get_simulation_output_files_from_design + piel.tools.cocotb.read_simulation_data + piel.tools.cocotb.simple_plot_simulation_data + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.cocotb.delete_simulation_output_files + piel.tools.cocotb.get_simulation_output_files + + +.. py:function:: check_cocotb_testbench_exists(design_directory: str | pathlib.Path) -> bool + + Checks if a cocotb testbench exists in the design directory. + + :param design_directory: Design directory. + :type design_directory: str | pathlib.Path + + :returns: True if cocotb testbench exists. + :rtype: cocotb_testbench_exists(bool) + + +.. py:function:: configure_cocotb_simulation(design_directory: str | pathlib.Path, simulator: Literal[icarus, verilator], top_level_language: Literal[verilog, vhdl], top_level_verilog_module: str, test_python_module: str, design_sources_list: list | None = None) + + Writes a cocotb makefile. + + If no design_sources_list is provided then it adds all the design sources under the `src` folder. + + In the form + .. code-block:: + + #!/bin/sh + # Makefile + # defaults + SIM ?= icarus + TOPLEVEL_LANG ?= verilog + + # Note we need to include the test script to the PYTHONPATH + export PYTHONPATH = + + VERILOG_SOURCES += $(PWD)/my_design.sv + # use VHDL_SOURCES for VHDL files + + # TOPLEVEL is the name of the toplevel module in your Verilog or VHDL file + TOPLEVEL := my_design + + # MODULE is the basename of the Python test file + MODULE := test_my_design + + # include cocotb's make rules to take care of the simulator setup + include $(shell cocotb-config --makefiles)/Makefile.sim + + + :param design_directory: The directory where the design is located. + :type design_directory: str | pathlib.Path + :param simulator: The simulator to use. + :type simulator: Literal["icarus", "verilator"] + :param top_level_language: The top level language. + :type top_level_language: Literal["verilog", "vhdl"] + :param top_level_verilog_module: The top level verilog module. + :type top_level_verilog_module: str + :param test_python_module: The test python module. + :type test_python_module: str + :param design_sources_list: A list of design sources. Defaults to None. + :type design_sources_list: list | None, optional + + :returns: None + + +.. py:data:: delete_simulation_output_files + + + +.. py:function:: run_cocotb_simulation(design_directory: str) -> subprocess.CompletedProcess + + Equivalent to running the cocotb makefile + .. code-block:: + + make + + :param design_directory: The directory where the design is located. + :type design_directory: str + + :returns: The subprocess.CompletedProcess object. + :rtype: subprocess.CompletedProcess + + +.. py:data:: get_simulation_output_files + + + +.. py:function:: get_simulation_output_files_from_design(design_directory: piel.config.piel_path_types, extension: str = 'csv') + + This function returns a list of all the simulation output files in the design directory. + + :param design_directory: The path to the design directory. + :type design_directory: piel_path_types + + :returns: List of all the simulation output files in the design directory. + :rtype: output_files (list) + + +.. py:function:: read_simulation_data(file_path: piel.config.piel_path_types) + + This function returns a Pandas dataframe that contains all the simulation data outputted from the simulation run. + + :param file_path: The path to the simulation data file. + :type file_path: piel_path_types + + :returns: The simulation data in a Pandas dataframe. + :rtype: simulation_data (pd.DataFrame) + + +.. py:function:: simple_plot_simulation_data(simulation_data: pandas.DataFrame) diff --git a/docs/autoapi/piel/tools/gdsfactory/index.rst b/docs/autoapi/piel/tools/gdsfactory/index.rst new file mode 100644 index 00000000..3f96a870 --- /dev/null +++ b/docs/autoapi/piel/tools/gdsfactory/index.rst @@ -0,0 +1,100 @@ +:py:mod:`piel.tools.gdsfactory` +=============================== + +.. py:module:: piel.tools.gdsfactory + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + netlist/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.gdsfactory.get_input_ports_index + piel.tools.gdsfactory.get_matched_ports_tuple_index + + + +.. py:function:: get_input_ports_index(ports_index: dict, sorting_algorithm: Literal[get_input_ports_index.prefix] = 'prefix', prefix: str = 'in') -> tuple + + This function returns the input ports of a component. However, input ports may have different sets of prefixes and suffixes. This function implements different sorting algorithms for different ports names. The default algorithm is `prefix`, which sorts the ports by their prefix. The Endianness implementation means that the tuple order is determined according to the last numerical index order of the port numbering. + + .. code-block:: python + + raw_ports_index = { + "in_o_0": 0, + "out_o_0": 1, + "out_o_1": 2, + "out_o_2": 3, + "out_o_3": 4, + "in_o_1": 5, + "in_o_2": 6, + "in_o_3": 7, + } + + get_input_ports_index(ports_index=raw_ports_index) + + # Output + ((0, "in_o_0"), (5, "in_o_1"), (6, "in_o_2"), (7, "in_o_3")) + + :param ports_index: The ports index dictionary. + :type ports_index: dict + :param sorting_algorithm: The sorting algorithm to use. Defaults to "prefix". + :type sorting_algorithm: Literal["prefix"], optional + :param prefix: The prefix to use for the sorting algorithm. Defaults to "in". + :type prefix: str, optional + + :returns: The ordered input ports index tuple. + :rtype: tuple + + +.. py:function:: get_matched_ports_tuple_index(ports_index: dict, selected_ports_tuple: Optional[tuple] = None, sorting_algorithm: Literal[get_matched_ports_tuple_index.prefix, selected_ports] = 'prefix', prefix: str = 'in') -> (tuple, tuple) + + This function returns the input ports of a component. However, input ports may have different sets of prefixes + and suffixes. This function implements different sorting algorithms for different ports names. The default + algorithm is `prefix`, which sorts the ports by their prefix. The Endianness implementation means that the tuple + order is determined according to the last numerical index order of the port numbering. Returns just a tuple of + the index. + + .. code-block:: python + + raw_ports_index = { + "in_o_0": 0, + "out_o_0": 1, + "out_o_1": 2, + "out_o_2": 3, + "out_o_3": 4, + "in_o_1": 5, + "in_o_2": 6, + "in_o_3": 7, + } + + get_input_ports_tuple_index(ports_index=raw_ports_index) + + # Output + (0, 5, 6, 7) + + :param ports_index: The ports index dictionary. + :type ports_index: dict + :param selected_ports_tuple: The selected ports tuple. Defaults to None. + :type selected_ports_tuple: tuple, optional + :param sorting_algorithm: The sorting algorithm to use. Defaults to "prefix". + :type sorting_algorithm: Literal["prefix"], optional + :param prefix: The prefix to use for the sorting algorithm. Defaults to "in". + :type prefix: str, optional + + :returns: The ordered input ports index tuple. + matched_ports_name_tuple_order(tuple): The ordered input ports name tuple. + :rtype: matches_ports_index_tuple_order(tuple) diff --git a/docs/autoapi/piel/tools/gdsfactory/netlist/index.rst b/docs/autoapi/piel/tools/gdsfactory/netlist/index.rst new file mode 100644 index 00000000..5bcc12c0 --- /dev/null +++ b/docs/autoapi/piel/tools/gdsfactory/netlist/index.rst @@ -0,0 +1,91 @@ +:py:mod:`piel.tools.gdsfactory.netlist` +======================================= + +.. py:module:: piel.tools.gdsfactory.netlist + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.gdsfactory.netlist.get_matched_ports_tuple_index + piel.tools.gdsfactory.netlist.get_input_ports_index + + + +.. py:function:: get_matched_ports_tuple_index(ports_index: dict, selected_ports_tuple: Optional[tuple] = None, sorting_algorithm: Literal[get_matched_ports_tuple_index.prefix, selected_ports] = 'prefix', prefix: str = 'in') -> (tuple, tuple) + + This function returns the input ports of a component. However, input ports may have different sets of prefixes + and suffixes. This function implements different sorting algorithms for different ports names. The default + algorithm is `prefix`, which sorts the ports by their prefix. The Endianness implementation means that the tuple + order is determined according to the last numerical index order of the port numbering. Returns just a tuple of + the index. + + .. code-block:: python + + raw_ports_index = { + "in_o_0": 0, + "out_o_0": 1, + "out_o_1": 2, + "out_o_2": 3, + "out_o_3": 4, + "in_o_1": 5, + "in_o_2": 6, + "in_o_3": 7, + } + + get_input_ports_tuple_index(ports_index=raw_ports_index) + + # Output + (0, 5, 6, 7) + + :param ports_index: The ports index dictionary. + :type ports_index: dict + :param selected_ports_tuple: The selected ports tuple. Defaults to None. + :type selected_ports_tuple: tuple, optional + :param sorting_algorithm: The sorting algorithm to use. Defaults to "prefix". + :type sorting_algorithm: Literal["prefix"], optional + :param prefix: The prefix to use for the sorting algorithm. Defaults to "in". + :type prefix: str, optional + + :returns: The ordered input ports index tuple. + matched_ports_name_tuple_order(tuple): The ordered input ports name tuple. + :rtype: matches_ports_index_tuple_order(tuple) + + +.. py:function:: get_input_ports_index(ports_index: dict, sorting_algorithm: Literal[get_input_ports_index.prefix] = 'prefix', prefix: str = 'in') -> tuple + + This function returns the input ports of a component. However, input ports may have different sets of prefixes and suffixes. This function implements different sorting algorithms for different ports names. The default algorithm is `prefix`, which sorts the ports by their prefix. The Endianness implementation means that the tuple order is determined according to the last numerical index order of the port numbering. + + .. code-block:: python + + raw_ports_index = { + "in_o_0": 0, + "out_o_0": 1, + "out_o_1": 2, + "out_o_2": 3, + "out_o_3": 4, + "in_o_1": 5, + "in_o_2": 6, + "in_o_3": 7, + } + + get_input_ports_index(ports_index=raw_ports_index) + + # Output + ((0, "in_o_0"), (5, "in_o_1"), (6, "in_o_2"), (7, "in_o_3")) + + :param ports_index: The ports index dictionary. + :type ports_index: dict + :param sorting_algorithm: The sorting algorithm to use. Defaults to "prefix". + :type sorting_algorithm: Literal["prefix"], optional + :param prefix: The prefix to use for the sorting algorithm. Defaults to "in". + :type prefix: str, optional + + :returns: The ordered input ports index tuple. + :rtype: tuple diff --git a/docs/autoapi/piel/tools/hdl21/circuit/index.rst b/docs/autoapi/piel/tools/hdl21/circuit/index.rst new file mode 100644 index 00000000..675b71a8 --- /dev/null +++ b/docs/autoapi/piel/tools/hdl21/circuit/index.rst @@ -0,0 +1,22 @@ +:py:mod:`piel.tools.hdl21.circuit` +================================== + +.. py:module:: piel.tools.hdl21.circuit + +.. autoapi-nested-parse:: + + The way the construction of the SPICE models is implemented in ``piel`` is also microservice-esque. Larger + circuits are constructed out of smaller building blocks. This means that simulation configurations and so on are + constructed upon a provided initial circuit, and the SPICE directives are appended accordingly. + + As mentioned previously, ``piel`` creates circuits based on fundamental SPICE because this opens the possibility to + large scale integration of these circuit models on different SPICE solvers, including proprietary ones as long as the + SPICE circuit can be written to particular directories. However, due to the ease of circuit integration, + and translation that ``hdl21`` provides, it's API can also be used to implement parametrised functionality, + although it is easy to export the circuit as a raw SPICE directive after composition. + + This composition tends to be implemented in a `SubCircuit` hierarchical implementation, as this allows for more modularisation of the netlisted devices. + + Let's assume that we can get an extracted SPICE netlist of our circuit, that includes all nodes, and component + circuit definitions. This could then be simulated accordingly for the whole circuit between inputs and outputs. This + would have to be constructed out of component models and a provided netlist in a similar fashion to ``SAX``. diff --git a/docs/autoapi/piel/tools/hdl21/index.rst b/docs/autoapi/piel/tools/hdl21/index.rst new file mode 100644 index 00000000..880a9c0e --- /dev/null +++ b/docs/autoapi/piel/tools/hdl21/index.rst @@ -0,0 +1,33 @@ +:py:mod:`piel.tools.hdl21` +========================== + +.. py:module:: piel.tools.hdl21 + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + circuit/index.rst + simulator/index.rst + units/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.hdl21.convert_numeric_to_prefix + + + +.. py:function:: convert_numeric_to_prefix(value: float) + + This function converts a numeric value to a number under a SPICE unit closest to the base prefix. This allows us to connect a particular number real output, into a term that can be used in a SPICE netlist. diff --git a/docs/autoapi/piel/tools/hdl21/simulator/index.rst b/docs/autoapi/piel/tools/hdl21/simulator/index.rst new file mode 100644 index 00000000..1f44d9e7 --- /dev/null +++ b/docs/autoapi/piel/tools/hdl21/simulator/index.rst @@ -0,0 +1,22 @@ +:py:mod:`piel.tools.hdl21.simulator` +==================================== + +.. py:module:: piel.tools.hdl21.simulator + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.hdl21.simulator.configure_transient_simulation + + + +.. py:function:: configure_transient_simulation(circuit: hdl21.Module, stop_time_s: float, step_time_s: float) + + This function configures the transient simulation for the circuit. diff --git a/docs/autoapi/piel/tools/hdl21/units/index.rst b/docs/autoapi/piel/tools/hdl21/units/index.rst new file mode 100644 index 00000000..742dbb7d --- /dev/null +++ b/docs/autoapi/piel/tools/hdl21/units/index.rst @@ -0,0 +1,39 @@ +:py:mod:`piel.tools.hdl21.units` +================================ + +.. py:module:: piel.tools.hdl21.units + +.. autoapi-nested-parse:: + + These are the corresponding prefixes from `hdl21`: + + f = FEMTO = Prefix.FEMTO + p = PICO = Prefix.PICO + n = NANO = Prefix.NANO + µ = u = MICRO = Prefix.MICRO # Note both `u` and `µ` are valid + m = MILLI = Prefix.MILLI + K = KILO = Prefix.KILO + M = MEGA = Prefix.MEGA + G = GIGA = Prefix.GIGA + T = TERA = Prefix.TERA + P = PETA = Prefix.PETA + UNIT = Prefix.UNIT + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.hdl21.units.convert_numeric_to_prefix + + + +.. py:function:: convert_numeric_to_prefix(value: float) + + This function converts a numeric value to a number under a SPICE unit closest to the base prefix. This allows us to connect a particular number real output, into a term that can be used in a SPICE netlist. diff --git a/docs/autoapi/piel/tools/index.rst b/docs/autoapi/piel/tools/index.rst new file mode 100644 index 00000000..65c59153 --- /dev/null +++ b/docs/autoapi/piel/tools/index.rst @@ -0,0 +1,873 @@ +:py:mod:`piel.tools` +==================== + +.. py:module:: piel.tools + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + cocotb/index.rst + gdsfactory/index.rst + hdl21/index.rst + openlane/index.rst + qutip/index.rst + sax/index.rst + thewalrus/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.check_cocotb_testbench_exists + piel.tools.configure_cocotb_simulation + piel.tools.run_cocotb_simulation + piel.tools.get_simulation_output_files_from_design + piel.tools.read_simulation_data + piel.tools.simple_plot_simulation_data + piel.tools.get_input_ports_index + piel.tools.get_matched_ports_tuple_index + piel.tools.get_design_from_openlane_migration + piel.tools.find_design_run + piel.tools.check_config_json_exists_openlane_v1 + piel.tools.check_design_exists_openlane_v1 + piel.tools.configure_and_run_design_openlane_v1 + piel.tools.configure_parametric_designs_openlane_v1 + piel.tools.configure_flow_script_openlane_v1 + piel.tools.create_parametric_designs_openlane_v1 + piel.tools.get_design_directory_from_root_openlane_v1 + piel.tools.get_latest_version_root_openlane_v1 + piel.tools.read_configuration_openlane_v1 + piel.tools.write_configuration_openlane_v1 + piel.tools.filter_timing_sta_files + piel.tools.filter_power_sta_files + piel.tools.get_all_timing_sta_files + piel.tools.get_all_power_sta_files + piel.tools.calculate_max_frame_amount + piel.tools.calculate_propagation_delay_from_file + piel.tools.calculate_propagation_delay_from_timing_data + piel.tools.configure_timing_data_rows + piel.tools.configure_frame_id + piel.tools.filter_timing_data_by_net_name_and_type + piel.tools.get_frame_meta_data + piel.tools.get_frame_lines_data + piel.tools.get_frame_timing_data + piel.tools.get_all_timing_data_from_file + piel.tools.read_sta_rpt_fwf_file + piel.tools.contains_in_lines + piel.tools.create_file_lines_dataframe + piel.tools.get_file_line_by_keyword + piel.tools.read_file_lines + piel.tools.run_openlane_flow + piel.tools.convert_numeric_to_prefix + piel.tools.get_sdense_ports_index + piel.tools.sax_to_s_parameters_standard_matrix + piel.tools.fock_state_nonzero_indexes + piel.tools.fock_state_to_photon_number_factorial + piel.tools.verify_matrix_is_unitary + piel.tools.subunitary_selection_on_range + piel.tools.subunitary_selection_on_index + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.delete_simulation_output_files + piel.tools.get_simulation_output_files + piel.tools.snet + piel.tools.standard_s_parameters_to_qutip_qobj + + +.. py:function:: check_cocotb_testbench_exists(design_directory: str | pathlib.Path) -> bool + + Checks if a cocotb testbench exists in the design directory. + + :param design_directory: Design directory. + :type design_directory: str | pathlib.Path + + :returns: True if cocotb testbench exists. + :rtype: cocotb_testbench_exists(bool) + + +.. py:function:: configure_cocotb_simulation(design_directory: str | pathlib.Path, simulator: Literal[icarus, verilator], top_level_language: Literal[verilog, vhdl], top_level_verilog_module: str, test_python_module: str, design_sources_list: list | None = None) + + Writes a cocotb makefile. + + If no design_sources_list is provided then it adds all the design sources under the `src` folder. + + In the form + .. code-block:: + + #!/bin/sh + # Makefile + # defaults + SIM ?= icarus + TOPLEVEL_LANG ?= verilog + + # Note we need to include the test script to the PYTHONPATH + export PYTHONPATH = + + VERILOG_SOURCES += $(PWD)/my_design.sv + # use VHDL_SOURCES for VHDL files + + # TOPLEVEL is the name of the toplevel module in your Verilog or VHDL file + TOPLEVEL := my_design + + # MODULE is the basename of the Python test file + MODULE := test_my_design + + # include cocotb's make rules to take care of the simulator setup + include $(shell cocotb-config --makefiles)/Makefile.sim + + + :param design_directory: The directory where the design is located. + :type design_directory: str | pathlib.Path + :param simulator: The simulator to use. + :type simulator: Literal["icarus", "verilator"] + :param top_level_language: The top level language. + :type top_level_language: Literal["verilog", "vhdl"] + :param top_level_verilog_module: The top level verilog module. + :type top_level_verilog_module: str + :param test_python_module: The test python module. + :type test_python_module: str + :param design_sources_list: A list of design sources. Defaults to None. + :type design_sources_list: list | None, optional + + :returns: None + + +.. py:data:: delete_simulation_output_files + + + +.. py:function:: run_cocotb_simulation(design_directory: str) -> subprocess.CompletedProcess + + Equivalent to running the cocotb makefile + .. code-block:: + + make + + :param design_directory: The directory where the design is located. + :type design_directory: str + + :returns: The subprocess.CompletedProcess object. + :rtype: subprocess.CompletedProcess + + +.. py:data:: get_simulation_output_files + + + +.. py:function:: get_simulation_output_files_from_design(design_directory: piel.config.piel_path_types, extension: str = 'csv') + + This function returns a list of all the simulation output files in the design directory. + + :param design_directory: The path to the design directory. + :type design_directory: piel_path_types + + :returns: List of all the simulation output files in the design directory. + :rtype: output_files (list) + + +.. py:function:: read_simulation_data(file_path: piel.config.piel_path_types) + + This function returns a Pandas dataframe that contains all the simulation data outputted from the simulation run. + + :param file_path: The path to the simulation data file. + :type file_path: piel_path_types + + :returns: The simulation data in a Pandas dataframe. + :rtype: simulation_data (pd.DataFrame) + + +.. py:function:: simple_plot_simulation_data(simulation_data: pandas.DataFrame) + + +.. py:function:: get_input_ports_index(ports_index: dict, sorting_algorithm: Literal[get_input_ports_index.prefix] = 'prefix', prefix: str = 'in') -> tuple + + This function returns the input ports of a component. However, input ports may have different sets of prefixes and suffixes. This function implements different sorting algorithms for different ports names. The default algorithm is `prefix`, which sorts the ports by their prefix. The Endianness implementation means that the tuple order is determined according to the last numerical index order of the port numbering. + + .. code-block:: python + + raw_ports_index = { + "in_o_0": 0, + "out_o_0": 1, + "out_o_1": 2, + "out_o_2": 3, + "out_o_3": 4, + "in_o_1": 5, + "in_o_2": 6, + "in_o_3": 7, + } + + get_input_ports_index(ports_index=raw_ports_index) + + # Output + ((0, "in_o_0"), (5, "in_o_1"), (6, "in_o_2"), (7, "in_o_3")) + + :param ports_index: The ports index dictionary. + :type ports_index: dict + :param sorting_algorithm: The sorting algorithm to use. Defaults to "prefix". + :type sorting_algorithm: Literal["prefix"], optional + :param prefix: The prefix to use for the sorting algorithm. Defaults to "in". + :type prefix: str, optional + + :returns: The ordered input ports index tuple. + :rtype: tuple + + +.. py:function:: get_matched_ports_tuple_index(ports_index: dict, selected_ports_tuple: Optional[tuple] = None, sorting_algorithm: Literal[get_matched_ports_tuple_index.prefix, selected_ports] = 'prefix', prefix: str = 'in') -> (tuple, tuple) + + This function returns the input ports of a component. However, input ports may have different sets of prefixes + and suffixes. This function implements different sorting algorithms for different ports names. The default + algorithm is `prefix`, which sorts the ports by their prefix. The Endianness implementation means that the tuple + order is determined according to the last numerical index order of the port numbering. Returns just a tuple of + the index. + + .. code-block:: python + + raw_ports_index = { + "in_o_0": 0, + "out_o_0": 1, + "out_o_1": 2, + "out_o_2": 3, + "out_o_3": 4, + "in_o_1": 5, + "in_o_2": 6, + "in_o_3": 7, + } + + get_input_ports_tuple_index(ports_index=raw_ports_index) + + # Output + (0, 5, 6, 7) + + :param ports_index: The ports index dictionary. + :type ports_index: dict + :param selected_ports_tuple: The selected ports tuple. Defaults to None. + :type selected_ports_tuple: tuple, optional + :param sorting_algorithm: The sorting algorithm to use. Defaults to "prefix". + :type sorting_algorithm: Literal["prefix"], optional + :param prefix: The prefix to use for the sorting algorithm. Defaults to "in". + :type prefix: str, optional + + :returns: The ordered input ports index tuple. + matched_ports_name_tuple_order(tuple): The ordered input ports name tuple. + :rtype: matches_ports_index_tuple_order(tuple) + + +.. py:function:: get_design_from_openlane_migration(v1: bool = True, design_name_v1: str | None = None, design_directory: str | pathlib.Path | None = None, root_directory_v1: str | pathlib.Path | None = None) -> (str, pathlib.Path) + + This function provides the integration mechanism for easily migrating the interconnection with other toolsets from an OpenLane v1 design to an OpenLane v2 design. + + This function checks if the inputs are to be treated as v1 inputs. If so, and a `design_name` is provided then it will set the `design_directory` to the corresponding `design_name` directory in the corresponding `root_directory_v1 / designs`. If no `root_directory` is provided then it returns `$OPENLANE_ROOT/""/. If a `design_directory` is provided then this will always take precedence even with a `v1` flag. + + :param v1: If True, it will migrate from v1 to v2. + :type v1: bool + :param design_name_v1: Design name of the v1 design that can be found within `$OPENLANE_ROOT/""/designs`. + :type design_name_v1: str + :param design_directory: Design directory PATH. Optional path for v2-based designs. + :type design_directory: str + :param root_directory_v1: Root directory of OpenLane v1. If set to None it will return `$OPENLANE_ROOT/""` + :type root_directory_v1: str + + :returns: None + + +.. py:function:: find_design_run(design_directory: piel.config.piel_path_types, run_name: str | None = None) -> pathlib.Path + + For a given `design_directory`, the `openlane` output can be found in the `runs` subdirectory. + + They get sorted based on a reverse `list.sort()` method. + + # TODO docs + + +.. py:function:: check_config_json_exists_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> bool + + Checks if a design has a `config.json` file. + + :param design_name: Name of the design. + :type design_name: str + + :returns: True if `config.json` exists. + :rtype: config_json_exists(bool) + + +.. py:function:: check_design_exists_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> bool + + Checks if a design exists in the OpenLane v1 design folder. + + Lists all designs inside the Openlane V1 design root. + + :param design_name: Name of the design. + :type design_name: str + + :returns: True if design exists. + :rtype: design_exists(bool) + + +.. py:function:: configure_and_run_design_openlane_v1(design_name: str, configuration: dict | None = None, root_directory: str | pathlib.Path | None = None) -> None + + Configures and runs an OpenLane v1 design. + + This function does the following: + 1. Check that the design_directory provided is under $OPENLANE_ROOT//designs + 2. Check if `config.json` has already been provided for this design. If a configuration dictionary is inputted into the function parameters, then it overwrites the default `config.json`. + 3. Create a script directory, a script is written and permissions are provided for it to be executable. + 4. Permit and execute the `openlane_flow.sh` script in the `scripts` directory. + + :param design_name: Name of the design. + :type design_name: str + :param configuration: Configuration dictionary. + :type configuration: dict | None + :param root_directory: Design directory. + :type root_directory: str | pathlib.Path + + :returns: None + + +.. py:function:: configure_parametric_designs_openlane_v1(design_name: str, parameter_sweep_dictionary: dict, add_id: bool = True) -> list + + For a given `source_design_directory`, this function reads in the config.json file and returns a set of parametric sweeps that gets used when creating a set of parametric designs. + + :param add_id: Add an ID to the design name. Defaults to True. + :type add_id: bool + :param parameter_sweep_dictionary: Dictionary of parameters to sweep. + :type parameter_sweep_dictionary: dict + :param source_design_directory: Source design directory. + :type source_design_directory: str | pathlib.Path + + :returns: List of configurations to sweep. + :rtype: configuration_sweep(list) + + +.. py:function:: configure_flow_script_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> None + + Configures the OpenLane v1 flow script after checking that the design directory exists. + + :param design_directory: Design directory. Defaults to latest OpenLane root. + :type design_directory: str | pathlib.Path | None + + :returns: None + + +.. py:function:: create_parametric_designs_openlane_v1(design_name: str, parameter_sweep_dictionary: dict, target_directory: str | pathlib.Path | None = None) -> None + + Takes a OpenLane v1 source directory and creates a parametric combination of these designs. + + :param design_name: Name of the design. + :type design_name: str + :param parameter_sweep_dictionary: Dictionary of parameters to sweep. + :type parameter_sweep_dictionary: dict + :param target_directory: Optional target directory. + :type target_directory: str | pathlib.Path | None + + :returns: None + + +.. py:function:: get_design_directory_from_root_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> pathlib.Path + + Gets the design directory from the root directory. + + :param design_name: Name of the design. + :type design_name: str + :param root_directory: Design directory. + :type root_directory: str | pathlib.Path + + :returns: Design directory. + :rtype: design_directory(pathlib.Path) + + +.. py:function:: get_latest_version_root_openlane_v1() -> pathlib.Path + + Gets the latest version root of OpenLane v1. + + +.. py:function:: read_configuration_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> dict + + Reads a `config.json` from a design directory. + + :param design_name: Design name. + :type design_name: str + :param root_directory: Design directory. + :type root_directory: str | pathlib.Path + + :returns: Configuration dictionary. + :rtype: configuration(dict) + + +.. py:function:: write_configuration_openlane_v1(configuration: dict, design_directory: str | pathlib.Path) -> None + + Writes a `config.json` onto a `design_directory` + + :param configuration: OpenLane configuration dictionary. + :type configuration: dict + :param design_directory: Design directory PATH. + :type design_directory: str + + :returns: None + + +.. py:function:: filter_timing_sta_files(file_list) + + Filter the timing sta files from the list of files + + :param file_list: List containing the file paths + :type file_list: list + + :returns: List containing the timing sta files + :rtype: timing_sta_files (list) + + +.. py:function:: filter_power_sta_files(file_list) + + Filter the power sta files from the list of files + + :param file_list: List containing the file paths + :type file_list: list + + :returns: List containing the power sta files + :rtype: power_sta_files (list) + + +.. py:function:: get_all_timing_sta_files(run_directory) + + This function aims to list and perform analysis on all the relevant files in a particular run between all the corners. + + :param run_directory: The run directory to perform the analysis on. Defaults to None. + :type run_directory: str, optional + + :returns: List of all the .rpt files in the run directory. + :rtype: timing_sta_files_list (list) + + +.. py:function:: get_all_power_sta_files(run_directory) + + This function aims to list and perform analysis on all the relevant files in a particular run between all the corners. + + :param run_directory: The run directory to perform the analysis on. Defaults to None. + :type run_directory: str, optional + + :returns: List of all the .rpt files in the run directory. + :rtype: power_sta_files_list (list) + + +.. py:function:: calculate_max_frame_amount(file_lines_data: pandas.DataFrame) + + Calculate the maximum frame amount based on the frame IDs in the DataFrame + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Maximum number of frames in the file + :rtype: maximum_frame_amount (int) + + +.. py:function:: calculate_propagation_delay_from_file(file_path: str | pathlib.Path) + + Calculate the propagation delay for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: Dictionary containing the propagation delay + :rtype: propagation_delay (dict) + + +.. py:function:: calculate_propagation_delay_from_timing_data(net_name_in: str, net_name_out: str, timing_data: pandas.DataFrame) + + Calculate the propagation delay between two nets + + :param net_name_in: Name of the input net + :type net_name_in: str + :param net_name_out: Name of the output net + :type net_name_out: str + :param timing_data: Dataframe containing the timing data + :type timing_data: pd.DataFrame + + :returns: Dataframe containing the propagation delay + :rtype: propagation_delay_dataframe (pd.DataFrame) + + +.. py:function:: configure_timing_data_rows(file_lines_data: pandas.DataFrame) + + Identify the timing data lines for each frame and creates a metadata dictionary for frames. + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Dictionary containing the frame metadata + :rtype: frame_meta_data (dict) + + +.. py:function:: configure_frame_id(file_lines_data: pandas.DataFrame) + + Identify the frame delimiters and assign frame ID to each line in the file + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: filter_timing_data_by_net_name_and_type(timing_data: pandas.DataFrame, net_name: str, net_type: str) + + Filter the timing data by net name and type + + :param timing_data: DataFrame containing the timing data + :type timing_data: pd.DataFrame + :param net_name: Net name to be filtered + :type net_name: str + :param net_type: Net type to be filtered + :type net_type: str + + :returns: DataFrame containing the timing data + :rtype: timing_data (pd.DataFrame) + + +.. py:function:: get_frame_meta_data(file_lines_data) + + Get the frame metadata + + :param file_lines_data: DataFrame containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: DataFrame containing the start point name + end_point_name (pd.DataFrame): DataFrame containing the end point name + path_group_name (pd.DataFrame): DataFrame containing the path group name + path_type_name (pd.DataFrame): DataFrame containing the path type name + :rtype: start_point_name (pd.DataFrame) + + +.. py:function:: get_frame_lines_data(file_path: str | pathlib.Path) + + Calculate the timing data for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: DataFrame containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: get_frame_timing_data(file: str | pathlib.Path, frame_meta_data: dict, frame_id: int = 0) + + Extract the timing data from the file + + :param file: Address of the file + :type file: str | pathlib.Path + :param frame_meta_data: Dictionary containing the frame metadata + :type frame_meta_data: dict + :param frame_id: Frame ID to be read + :type frame_id: int + + :returns: DataFrame containing the timing data + :rtype: timing_data (pd.DataFrame) + + +.. py:function:: get_all_timing_data_from_file(file_path: str | pathlib.Path) + + Calculate the timing data for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: Dictionary containing the timing data for each frame + :rtype: frame_timing_data (dict) + + +.. py:function:: read_sta_rpt_fwf_file(file: str | pathlib.Path, frame_meta_data: dict, frame_id: int = 0) + + Read the fixed width file and return a DataFrame + + :param file: Address of the file + :type file: str | pathlib.Path + :param frame_meta_data: Dictionary containing the frame metadata + :type frame_meta_data: dict + :param frame_id: Frame ID to be read + :type frame_id: int + + :returns: DataFrame containing the file data + :rtype: file_data (pd.DataFrame) + + +.. py:function:: contains_in_lines(file_lines_data: pandas.DataFrame, keyword: str) + + Check if the keyword is contained in the file lines + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + :param keyword: Keyword to search for + :type keyword: str + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: create_file_lines_dataframe(file_lines_raw) + + Create a DataFrame from the raw lines of a file + + :param file_lines_raw: list containing the file lines + :type file_lines_raw: list + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: get_file_line_by_keyword(file_lines_data: pandas.DataFrame, keyword: str, regex: str) + + Extract the data from the file lines using the given keyword and regex + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + :param keyword: Keyword to search for + :type keyword: str + :param regex: Regex to extract the data + :type regex: str + + :returns: Dataframe containing the extracted values + :rtype: extracted_values (pd.DataFrame) + + +.. py:function:: read_file_lines(file_path: str | pathlib.Path) + + Extract lines from the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: list containing the file lines + :rtype: file_lines_raw (list) + + +.. py:function:: run_openlane_flow(configuration: dict | None = test_spm_open_lane_configuration, design_directory: piel.config.piel_path_types = '/foss/designs/spm') -> None + + Runs the OpenLane flow. + + :param configuration: OpenLane configuration dictionary. If none is present it will default to the config.json file on the design_directory. + :type configuration: dict + :param design_directory: Design directory PATH. + :type design_directory: piel_path_types + + :returns: None + + +.. py:function:: convert_numeric_to_prefix(value: float) + + This function converts a numeric value to a number under a SPICE unit closest to the base prefix. This allows us to connect a particular number real output, into a term that can be used in a SPICE netlist. + + +.. py:function:: get_sdense_ports_index(input_ports_order: tuple, all_ports_index: dict) -> dict + + This function returns the ports index of the sax dense S-parameter matrix. + + Given that the order of the iteration is provided by the user, the dictionary keys will also be ordered + accordingly when iterating over them. This requires the user to provide a set of ordered. + + TODO verify reasonable iteration order. + + .. code-block:: python + + # The input_ports_order can be a tuple of tuples that contain the index and port name. Eg. + input_ports_order = ((0, "in_o_0"), (5, "in_o_1"), (6, "in_o_2"), (7, "in_o_3")) + # The all_ports_index is a dictionary of the ports index. Eg. + all_ports_index = { + "in_o_0": 0, + "out_o_0": 1, + "out_o_1": 2, + "out_o_2": 3, + "out_o_3": 4, + "in_o_1": 5, + "in_o_2": 6, + "in_o_3": 7, + } + # Output + {"in_o_0": 0, "in_o_1": 5, "in_o_2": 6, "in_o_3": 7} + + :param input_ports_order: The ports order tuple. Can be a tuple of tuples that contain the index and port name. + :type input_ports_order: tuple + :param all_ports_index: The ports index dictionary. + :type all_ports_index: dict + + :returns: The ordered input ports index tuple. + :rtype: tuple + + +.. py:function:: sax_to_s_parameters_standard_matrix(sax_input: sax.SType, input_ports_order: tuple | None = None) -> tuple + + A ``sax`` S-parameter SDict is provided as a dictionary of tuples with (port0, port1) as the key. This + determines the direction of the scattering relationship. It means that the number of terms in an S-parameter + matrix is the number of ports squared. + + In order to generalise, this function returns both the S-parameter matrices and the indexing ports based on the + amount provided. In terms of computational speed, we definitely would like this function to be algorithmically + very fast. For now, I will write a simple python implementation and optimise in the future. + + It is possible to see the `sax` SDense notation equivalence here: + https://flaport.github.io/sax/nbs/08_backends.html + + .. code-block:: python + + import jax.numpy as jnp + from sax.core import SDense + + # Directional coupler SDense representation + dc_sdense: SDense = ( + jnp.array([[0, 0, τ, κ], [0, 0, κ, τ], [τ, κ, 0, 0], [κ, τ, 0, 0]]), + {"in0": 0, "in1": 1, "out0": 2, "out1": 3}, + ) + + + # Directional coupler SDict representation + # Taken from https://flaport.github.io/sax/nbs/05_models.html + def coupler(*, coupling: float = 0.5) -> SDict: + kappa = coupling**0.5 + tau = (1 - coupling) ** 0.5 + sdict = reciprocal( + { + ("in0", "out0"): tau, + ("in0", "out1"): 1j * kappa, + ("in1", "out0"): 1j * kappa, + ("in1", "out1"): tau, + } + ) + return sdict + + If we were to relate the mapping accordingly based on the ports indexes, a S-Parameter matrix in the form of + :math:`S_{(output,i),(input,i)}` would be: + + .. math:: + + S = \begin{bmatrix} + S_{00} & S_{10} \\ + S_{01} & S_{11} \\ + \end{bmatrix} = + \begin{bmatrix} + \tau & j \kappa \\ + j \kappa & \tau \\ + \end{bmatrix} + + Note that the standard S-parameter and hence unitary representation is in the form of: + + .. math:: + + S = \begin{bmatrix} + S_{00} & S_{01} \\ + S_{10} & S_{11} \\ + \end{bmatrix} + + + .. math:: + + \begin{bmatrix} + b_{1} \\ + \vdots \\ + b_{n} + \end{bmatrix} + = + \begin{bmatrix} + S_{11} & \dots & S_{1n} \\ + \vdots & \ddots & \vdots \\ + S_{n1} & \dots & S_{nn} + \end{bmatrix} + \begin{bmatrix} + a_{1} \\ + \vdots \\ + a_{n} + \end{bmatrix} + + TODO check with Floris, does this mean we need to transpose the matrix? + + :param sax_input: The sax S-parameter dictionary. + :type sax_input: sax.SType + :param input_ports_order: The ports order tuple containing the names and order of the input ports. + :type input_ports_order: tuple + + :returns: The S-parameter matrix and the input ports index tuple in the standard S-parameter notation. + :rtype: tuple + + +.. py:data:: snet + + + +.. py:function:: fock_state_nonzero_indexes(fock_state: qutip.Qobj) + + This function returns the indexes of the nonzero elements of a Fock state. + + :param fock_state: A QuTip QObj representation of the Fock state. + :type fock_state: qutip.Qobj + + :returns: The indexes of the nonzero elements of the Fock state. + :rtype: tuple + + +.. py:function:: fock_state_to_photon_number_factorial(fock_state: qutip.Qobj) + + This function converts a Fock state defined as: + + .. math:: + + ewcommand{\ket}[1]{\left|{#1} + ight + angle} + \ket{f_1} = \ket{j_1, j_2, ... j_N}$ + + and returns: + + .. math:: + + j_1^{'}! j_2^{'}! ... j_N^{'}! + + Args: + fock_state (qutip.Qobj): A QuTip QObj representation of the Fock state. + + Returns: + float: The photon number factorial of the Fock state. + + + +.. py:data:: standard_s_parameters_to_qutip_qobj + + + +.. py:function:: verify_matrix_is_unitary(matrix: jax.numpy.ndarray) -> bool + + Verify that the matrix is unitary. + + :param matrix: The matrix to verify. + :type matrix: jnp.ndarray + + :returns: True if the matrix is unitary, False otherwise. + :rtype: bool + + +.. py:function:: subunitary_selection_on_range(unitary_matrix: jax.numpy.ndarray, stop_index: tuple, start_index: Optional[tuple] = (0, 0)) + + This function returns a unitary between the indexes selected, and verifies the indexes are valid by checking that + the output matrix is also a unitary. + + TODO implement validation of a 2D matrix. + + +.. py:function:: subunitary_selection_on_index(unitary_matrix: jax.numpy.ndarray, rows_index: jax.numpy.ndarray | tuple, columns_index: jax.numpy.ndarray | tuple) + + This function returns a unitary between the indexes selected, and verifies the indexes are valid by checking that + the output matrix is also a unitary. + + TODO implement validation of a 2D matrix. diff --git a/docs/autoapi/piel/tools/openlane/index.rst b/docs/autoapi/piel/tools/openlane/index.rst new file mode 100644 index 00000000..61751817 --- /dev/null +++ b/docs/autoapi/piel/tools/openlane/index.rst @@ -0,0 +1,468 @@ +:py:mod:`piel.tools.openlane` +============================= + +.. py:module:: piel.tools.openlane + + +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + + parse/index.rst + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + migrate/index.rst + utils/index.rst + v1/index.rst + v2/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.openlane.get_design_from_openlane_migration + piel.tools.openlane.find_design_run + piel.tools.openlane.check_config_json_exists_openlane_v1 + piel.tools.openlane.check_design_exists_openlane_v1 + piel.tools.openlane.configure_and_run_design_openlane_v1 + piel.tools.openlane.configure_parametric_designs_openlane_v1 + piel.tools.openlane.configure_flow_script_openlane_v1 + piel.tools.openlane.create_parametric_designs_openlane_v1 + piel.tools.openlane.get_design_directory_from_root_openlane_v1 + piel.tools.openlane.get_latest_version_root_openlane_v1 + piel.tools.openlane.read_configuration_openlane_v1 + piel.tools.openlane.write_configuration_openlane_v1 + piel.tools.openlane.filter_timing_sta_files + piel.tools.openlane.filter_power_sta_files + piel.tools.openlane.get_all_timing_sta_files + piel.tools.openlane.get_all_power_sta_files + piel.tools.openlane.calculate_max_frame_amount + piel.tools.openlane.calculate_propagation_delay_from_file + piel.tools.openlane.calculate_propagation_delay_from_timing_data + piel.tools.openlane.configure_timing_data_rows + piel.tools.openlane.configure_frame_id + piel.tools.openlane.filter_timing_data_by_net_name_and_type + piel.tools.openlane.get_frame_meta_data + piel.tools.openlane.get_frame_lines_data + piel.tools.openlane.get_frame_timing_data + piel.tools.openlane.get_all_timing_data_from_file + piel.tools.openlane.read_sta_rpt_fwf_file + piel.tools.openlane.contains_in_lines + piel.tools.openlane.create_file_lines_dataframe + piel.tools.openlane.get_file_line_by_keyword + piel.tools.openlane.read_file_lines + piel.tools.openlane.run_openlane_flow + + + +.. py:function:: get_design_from_openlane_migration(v1: bool = True, design_name_v1: str | None = None, design_directory: str | pathlib.Path | None = None, root_directory_v1: str | pathlib.Path | None = None) -> (str, pathlib.Path) + + This function provides the integration mechanism for easily migrating the interconnection with other toolsets from an OpenLane v1 design to an OpenLane v2 design. + + This function checks if the inputs are to be treated as v1 inputs. If so, and a `design_name` is provided then it will set the `design_directory` to the corresponding `design_name` directory in the corresponding `root_directory_v1 / designs`. If no `root_directory` is provided then it returns `$OPENLANE_ROOT/""/. If a `design_directory` is provided then this will always take precedence even with a `v1` flag. + + :param v1: If True, it will migrate from v1 to v2. + :type v1: bool + :param design_name_v1: Design name of the v1 design that can be found within `$OPENLANE_ROOT/""/designs`. + :type design_name_v1: str + :param design_directory: Design directory PATH. Optional path for v2-based designs. + :type design_directory: str + :param root_directory_v1: Root directory of OpenLane v1. If set to None it will return `$OPENLANE_ROOT/""` + :type root_directory_v1: str + + :returns: None + + +.. py:function:: find_design_run(design_directory: piel.config.piel_path_types, run_name: str | None = None) -> pathlib.Path + + For a given `design_directory`, the `openlane` output can be found in the `runs` subdirectory. + + They get sorted based on a reverse `list.sort()` method. + + # TODO docs + + +.. py:function:: check_config_json_exists_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> bool + + Checks if a design has a `config.json` file. + + :param design_name: Name of the design. + :type design_name: str + + :returns: True if `config.json` exists. + :rtype: config_json_exists(bool) + + +.. py:function:: check_design_exists_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> bool + + Checks if a design exists in the OpenLane v1 design folder. + + Lists all designs inside the Openlane V1 design root. + + :param design_name: Name of the design. + :type design_name: str + + :returns: True if design exists. + :rtype: design_exists(bool) + + +.. py:function:: configure_and_run_design_openlane_v1(design_name: str, configuration: dict | None = None, root_directory: str | pathlib.Path | None = None) -> None + + Configures and runs an OpenLane v1 design. + + This function does the following: + 1. Check that the design_directory provided is under $OPENLANE_ROOT//designs + 2. Check if `config.json` has already been provided for this design. If a configuration dictionary is inputted into the function parameters, then it overwrites the default `config.json`. + 3. Create a script directory, a script is written and permissions are provided for it to be executable. + 4. Permit and execute the `openlane_flow.sh` script in the `scripts` directory. + + :param design_name: Name of the design. + :type design_name: str + :param configuration: Configuration dictionary. + :type configuration: dict | None + :param root_directory: Design directory. + :type root_directory: str | pathlib.Path + + :returns: None + + +.. py:function:: configure_parametric_designs_openlane_v1(design_name: str, parameter_sweep_dictionary: dict, add_id: bool = True) -> list + + For a given `source_design_directory`, this function reads in the config.json file and returns a set of parametric sweeps that gets used when creating a set of parametric designs. + + :param add_id: Add an ID to the design name. Defaults to True. + :type add_id: bool + :param parameter_sweep_dictionary: Dictionary of parameters to sweep. + :type parameter_sweep_dictionary: dict + :param source_design_directory: Source design directory. + :type source_design_directory: str | pathlib.Path + + :returns: List of configurations to sweep. + :rtype: configuration_sweep(list) + + +.. py:function:: configure_flow_script_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> None + + Configures the OpenLane v1 flow script after checking that the design directory exists. + + :param design_directory: Design directory. Defaults to latest OpenLane root. + :type design_directory: str | pathlib.Path | None + + :returns: None + + +.. py:function:: create_parametric_designs_openlane_v1(design_name: str, parameter_sweep_dictionary: dict, target_directory: str | pathlib.Path | None = None) -> None + + Takes a OpenLane v1 source directory and creates a parametric combination of these designs. + + :param design_name: Name of the design. + :type design_name: str + :param parameter_sweep_dictionary: Dictionary of parameters to sweep. + :type parameter_sweep_dictionary: dict + :param target_directory: Optional target directory. + :type target_directory: str | pathlib.Path | None + + :returns: None + + +.. py:function:: get_design_directory_from_root_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> pathlib.Path + + Gets the design directory from the root directory. + + :param design_name: Name of the design. + :type design_name: str + :param root_directory: Design directory. + :type root_directory: str | pathlib.Path + + :returns: Design directory. + :rtype: design_directory(pathlib.Path) + + +.. py:function:: get_latest_version_root_openlane_v1() -> pathlib.Path + + Gets the latest version root of OpenLane v1. + + +.. py:function:: read_configuration_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> dict + + Reads a `config.json` from a design directory. + + :param design_name: Design name. + :type design_name: str + :param root_directory: Design directory. + :type root_directory: str | pathlib.Path + + :returns: Configuration dictionary. + :rtype: configuration(dict) + + +.. py:function:: write_configuration_openlane_v1(configuration: dict, design_directory: str | pathlib.Path) -> None + + Writes a `config.json` onto a `design_directory` + + :param configuration: OpenLane configuration dictionary. + :type configuration: dict + :param design_directory: Design directory PATH. + :type design_directory: str + + :returns: None + + +.. py:function:: filter_timing_sta_files(file_list) + + Filter the timing sta files from the list of files + + :param file_list: List containing the file paths + :type file_list: list + + :returns: List containing the timing sta files + :rtype: timing_sta_files (list) + + +.. py:function:: filter_power_sta_files(file_list) + + Filter the power sta files from the list of files + + :param file_list: List containing the file paths + :type file_list: list + + :returns: List containing the power sta files + :rtype: power_sta_files (list) + + +.. py:function:: get_all_timing_sta_files(run_directory) + + This function aims to list and perform analysis on all the relevant files in a particular run between all the corners. + + :param run_directory: The run directory to perform the analysis on. Defaults to None. + :type run_directory: str, optional + + :returns: List of all the .rpt files in the run directory. + :rtype: timing_sta_files_list (list) + + +.. py:function:: get_all_power_sta_files(run_directory) + + This function aims to list and perform analysis on all the relevant files in a particular run between all the corners. + + :param run_directory: The run directory to perform the analysis on. Defaults to None. + :type run_directory: str, optional + + :returns: List of all the .rpt files in the run directory. + :rtype: power_sta_files_list (list) + + +.. py:function:: calculate_max_frame_amount(file_lines_data: pandas.DataFrame) + + Calculate the maximum frame amount based on the frame IDs in the DataFrame + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Maximum number of frames in the file + :rtype: maximum_frame_amount (int) + + +.. py:function:: calculate_propagation_delay_from_file(file_path: str | pathlib.Path) + + Calculate the propagation delay for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: Dictionary containing the propagation delay + :rtype: propagation_delay (dict) + + +.. py:function:: calculate_propagation_delay_from_timing_data(net_name_in: str, net_name_out: str, timing_data: pandas.DataFrame) + + Calculate the propagation delay between two nets + + :param net_name_in: Name of the input net + :type net_name_in: str + :param net_name_out: Name of the output net + :type net_name_out: str + :param timing_data: Dataframe containing the timing data + :type timing_data: pd.DataFrame + + :returns: Dataframe containing the propagation delay + :rtype: propagation_delay_dataframe (pd.DataFrame) + + +.. py:function:: configure_timing_data_rows(file_lines_data: pandas.DataFrame) + + Identify the timing data lines for each frame and creates a metadata dictionary for frames. + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Dictionary containing the frame metadata + :rtype: frame_meta_data (dict) + + +.. py:function:: configure_frame_id(file_lines_data: pandas.DataFrame) + + Identify the frame delimiters and assign frame ID to each line in the file + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: filter_timing_data_by_net_name_and_type(timing_data: pandas.DataFrame, net_name: str, net_type: str) + + Filter the timing data by net name and type + + :param timing_data: DataFrame containing the timing data + :type timing_data: pd.DataFrame + :param net_name: Net name to be filtered + :type net_name: str + :param net_type: Net type to be filtered + :type net_type: str + + :returns: DataFrame containing the timing data + :rtype: timing_data (pd.DataFrame) + + +.. py:function:: get_frame_meta_data(file_lines_data) + + Get the frame metadata + + :param file_lines_data: DataFrame containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: DataFrame containing the start point name + end_point_name (pd.DataFrame): DataFrame containing the end point name + path_group_name (pd.DataFrame): DataFrame containing the path group name + path_type_name (pd.DataFrame): DataFrame containing the path type name + :rtype: start_point_name (pd.DataFrame) + + +.. py:function:: get_frame_lines_data(file_path: str | pathlib.Path) + + Calculate the timing data for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: DataFrame containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: get_frame_timing_data(file: str | pathlib.Path, frame_meta_data: dict, frame_id: int = 0) + + Extract the timing data from the file + + :param file: Address of the file + :type file: str | pathlib.Path + :param frame_meta_data: Dictionary containing the frame metadata + :type frame_meta_data: dict + :param frame_id: Frame ID to be read + :type frame_id: int + + :returns: DataFrame containing the timing data + :rtype: timing_data (pd.DataFrame) + + +.. py:function:: get_all_timing_data_from_file(file_path: str | pathlib.Path) + + Calculate the timing data for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: Dictionary containing the timing data for each frame + :rtype: frame_timing_data (dict) + + +.. py:function:: read_sta_rpt_fwf_file(file: str | pathlib.Path, frame_meta_data: dict, frame_id: int = 0) + + Read the fixed width file and return a DataFrame + + :param file: Address of the file + :type file: str | pathlib.Path + :param frame_meta_data: Dictionary containing the frame metadata + :type frame_meta_data: dict + :param frame_id: Frame ID to be read + :type frame_id: int + + :returns: DataFrame containing the file data + :rtype: file_data (pd.DataFrame) + + +.. py:function:: contains_in_lines(file_lines_data: pandas.DataFrame, keyword: str) + + Check if the keyword is contained in the file lines + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + :param keyword: Keyword to search for + :type keyword: str + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: create_file_lines_dataframe(file_lines_raw) + + Create a DataFrame from the raw lines of a file + + :param file_lines_raw: list containing the file lines + :type file_lines_raw: list + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: get_file_line_by_keyword(file_lines_data: pandas.DataFrame, keyword: str, regex: str) + + Extract the data from the file lines using the given keyword and regex + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + :param keyword: Keyword to search for + :type keyword: str + :param regex: Regex to extract the data + :type regex: str + + :returns: Dataframe containing the extracted values + :rtype: extracted_values (pd.DataFrame) + + +.. py:function:: read_file_lines(file_path: str | pathlib.Path) + + Extract lines from the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: list containing the file lines + :rtype: file_lines_raw (list) + + +.. py:function:: run_openlane_flow(configuration: dict | None = test_spm_open_lane_configuration, design_directory: piel.config.piel_path_types = '/foss/designs/spm') -> None + + Runs the OpenLane flow. + + :param configuration: OpenLane configuration dictionary. If none is present it will default to the config.json file on the design_directory. + :type configuration: dict + :param design_directory: Design directory PATH. + :type design_directory: piel_path_types + + :returns: None diff --git a/docs/autoapi/piel/tools/openlane/migrate/index.rst b/docs/autoapi/piel/tools/openlane/migrate/index.rst new file mode 100644 index 00000000..a84d2536 --- /dev/null +++ b/docs/autoapi/piel/tools/openlane/migrate/index.rst @@ -0,0 +1,40 @@ +:py:mod:`piel.tools.openlane.migrate` +===================================== + +.. py:module:: piel.tools.openlane.migrate + +.. autoapi-nested-parse:: + + These functions provide easy tools for easily migrating between OpenLane v1 and v2 based designs. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.openlane.migrate.get_design_from_openlane_migration + + + +.. py:function:: get_design_from_openlane_migration(v1: bool = True, design_name_v1: str | None = None, design_directory: str | pathlib.Path | None = None, root_directory_v1: str | pathlib.Path | None = None) -> (str, pathlib.Path) + + This function provides the integration mechanism for easily migrating the interconnection with other toolsets from an OpenLane v1 design to an OpenLane v2 design. + + This function checks if the inputs are to be treated as v1 inputs. If so, and a `design_name` is provided then it will set the `design_directory` to the corresponding `design_name` directory in the corresponding `root_directory_v1 / designs`. If no `root_directory` is provided then it returns `$OPENLANE_ROOT/""/. If a `design_directory` is provided then this will always take precedence even with a `v1` flag. + + :param v1: If True, it will migrate from v1 to v2. + :type v1: bool + :param design_name_v1: Design name of the v1 design that can be found within `$OPENLANE_ROOT/""/designs`. + :type design_name_v1: str + :param design_directory: Design directory PATH. Optional path for v2-based designs. + :type design_directory: str + :param root_directory_v1: Root directory of OpenLane v1. If set to None it will return `$OPENLANE_ROOT/""` + :type root_directory_v1: str + + :returns: None diff --git a/docs/autoapi/piel/tools/openlane/parse/index.rst b/docs/autoapi/piel/tools/openlane/parse/index.rst new file mode 100644 index 00000000..a1961bb7 --- /dev/null +++ b/docs/autoapi/piel/tools/openlane/parse/index.rst @@ -0,0 +1,287 @@ +:py:mod:`piel.tools.openlane.parse` +=================================== + +.. py:module:: piel.tools.openlane.parse + +.. autoapi-nested-parse:: + + These functions aim to provide functionality to parse data from any OpenLanes v1 design into Python. + + They are ported from the old: github.com/daquintero/porf + + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + run_output/index.rst + sta_rpt/index.rst + utils/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.openlane.parse.filter_timing_sta_files + piel.tools.openlane.parse.filter_power_sta_files + piel.tools.openlane.parse.get_all_timing_sta_files + piel.tools.openlane.parse.get_all_power_sta_files + piel.tools.openlane.parse.calculate_max_frame_amount + piel.tools.openlane.parse.calculate_propagation_delay_from_file + piel.tools.openlane.parse.calculate_propagation_delay_from_timing_data + piel.tools.openlane.parse.configure_timing_data_rows + piel.tools.openlane.parse.configure_frame_id + piel.tools.openlane.parse.filter_timing_data_by_net_name_and_type + piel.tools.openlane.parse.get_frame_meta_data + piel.tools.openlane.parse.get_frame_lines_data + piel.tools.openlane.parse.get_frame_timing_data + piel.tools.openlane.parse.get_all_timing_data_from_file + piel.tools.openlane.parse.read_sta_rpt_fwf_file + piel.tools.openlane.parse.contains_in_lines + piel.tools.openlane.parse.create_file_lines_dataframe + piel.tools.openlane.parse.get_file_line_by_keyword + piel.tools.openlane.parse.read_file_lines + + + +.. py:function:: filter_timing_sta_files(file_list) + + Filter the timing sta files from the list of files + + :param file_list: List containing the file paths + :type file_list: list + + :returns: List containing the timing sta files + :rtype: timing_sta_files (list) + + +.. py:function:: filter_power_sta_files(file_list) + + Filter the power sta files from the list of files + + :param file_list: List containing the file paths + :type file_list: list + + :returns: List containing the power sta files + :rtype: power_sta_files (list) + + +.. py:function:: get_all_timing_sta_files(run_directory) + + This function aims to list and perform analysis on all the relevant files in a particular run between all the corners. + + :param run_directory: The run directory to perform the analysis on. Defaults to None. + :type run_directory: str, optional + + :returns: List of all the .rpt files in the run directory. + :rtype: timing_sta_files_list (list) + + +.. py:function:: get_all_power_sta_files(run_directory) + + This function aims to list and perform analysis on all the relevant files in a particular run between all the corners. + + :param run_directory: The run directory to perform the analysis on. Defaults to None. + :type run_directory: str, optional + + :returns: List of all the .rpt files in the run directory. + :rtype: power_sta_files_list (list) + + +.. py:function:: calculate_max_frame_amount(file_lines_data: pandas.DataFrame) + + Calculate the maximum frame amount based on the frame IDs in the DataFrame + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Maximum number of frames in the file + :rtype: maximum_frame_amount (int) + + +.. py:function:: calculate_propagation_delay_from_file(file_path: str | pathlib.Path) + + Calculate the propagation delay for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: Dictionary containing the propagation delay + :rtype: propagation_delay (dict) + + +.. py:function:: calculate_propagation_delay_from_timing_data(net_name_in: str, net_name_out: str, timing_data: pandas.DataFrame) + + Calculate the propagation delay between two nets + + :param net_name_in: Name of the input net + :type net_name_in: str + :param net_name_out: Name of the output net + :type net_name_out: str + :param timing_data: Dataframe containing the timing data + :type timing_data: pd.DataFrame + + :returns: Dataframe containing the propagation delay + :rtype: propagation_delay_dataframe (pd.DataFrame) + + +.. py:function:: configure_timing_data_rows(file_lines_data: pandas.DataFrame) + + Identify the timing data lines for each frame and creates a metadata dictionary for frames. + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Dictionary containing the frame metadata + :rtype: frame_meta_data (dict) + + +.. py:function:: configure_frame_id(file_lines_data: pandas.DataFrame) + + Identify the frame delimiters and assign frame ID to each line in the file + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: filter_timing_data_by_net_name_and_type(timing_data: pandas.DataFrame, net_name: str, net_type: str) + + Filter the timing data by net name and type + + :param timing_data: DataFrame containing the timing data + :type timing_data: pd.DataFrame + :param net_name: Net name to be filtered + :type net_name: str + :param net_type: Net type to be filtered + :type net_type: str + + :returns: DataFrame containing the timing data + :rtype: timing_data (pd.DataFrame) + + +.. py:function:: get_frame_meta_data(file_lines_data) + + Get the frame metadata + + :param file_lines_data: DataFrame containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: DataFrame containing the start point name + end_point_name (pd.DataFrame): DataFrame containing the end point name + path_group_name (pd.DataFrame): DataFrame containing the path group name + path_type_name (pd.DataFrame): DataFrame containing the path type name + :rtype: start_point_name (pd.DataFrame) + + +.. py:function:: get_frame_lines_data(file_path: str | pathlib.Path) + + Calculate the timing data for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: DataFrame containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: get_frame_timing_data(file: str | pathlib.Path, frame_meta_data: dict, frame_id: int = 0) + + Extract the timing data from the file + + :param file: Address of the file + :type file: str | pathlib.Path + :param frame_meta_data: Dictionary containing the frame metadata + :type frame_meta_data: dict + :param frame_id: Frame ID to be read + :type frame_id: int + + :returns: DataFrame containing the timing data + :rtype: timing_data (pd.DataFrame) + + +.. py:function:: get_all_timing_data_from_file(file_path: str | pathlib.Path) + + Calculate the timing data for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: Dictionary containing the timing data for each frame + :rtype: frame_timing_data (dict) + + +.. py:function:: read_sta_rpt_fwf_file(file: str | pathlib.Path, frame_meta_data: dict, frame_id: int = 0) + + Read the fixed width file and return a DataFrame + + :param file: Address of the file + :type file: str | pathlib.Path + :param frame_meta_data: Dictionary containing the frame metadata + :type frame_meta_data: dict + :param frame_id: Frame ID to be read + :type frame_id: int + + :returns: DataFrame containing the file data + :rtype: file_data (pd.DataFrame) + + +.. py:function:: contains_in_lines(file_lines_data: pandas.DataFrame, keyword: str) + + Check if the keyword is contained in the file lines + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + :param keyword: Keyword to search for + :type keyword: str + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: create_file_lines_dataframe(file_lines_raw) + + Create a DataFrame from the raw lines of a file + + :param file_lines_raw: list containing the file lines + :type file_lines_raw: list + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: get_file_line_by_keyword(file_lines_data: pandas.DataFrame, keyword: str, regex: str) + + Extract the data from the file lines using the given keyword and regex + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + :param keyword: Keyword to search for + :type keyword: str + :param regex: Regex to extract the data + :type regex: str + + :returns: Dataframe containing the extracted values + :rtype: extracted_values (pd.DataFrame) + + +.. py:function:: read_file_lines(file_path: str | pathlib.Path) + + Extract lines from the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: list containing the file lines + :rtype: file_lines_raw (list) diff --git a/docs/autoapi/piel/tools/openlane/parse/sta_rpt/index.rst b/docs/autoapi/piel/tools/openlane/parse/sta_rpt/index.rst new file mode 100644 index 00000000..912a3ea8 --- /dev/null +++ b/docs/autoapi/piel/tools/openlane/parse/sta_rpt/index.rst @@ -0,0 +1,167 @@ +:py:mod:`piel.tools.openlane.parse.sta_rpt` +=========================================== + +.. py:module:: piel.tools.openlane.parse.sta_rpt + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.openlane.parse.sta_rpt.calculate_max_frame_amount + piel.tools.openlane.parse.sta_rpt.calculate_propagation_delay_from_timing_data + piel.tools.openlane.parse.sta_rpt.calculate_propagation_delay_from_file + piel.tools.openlane.parse.sta_rpt.configure_timing_data_rows + piel.tools.openlane.parse.sta_rpt.configure_frame_id + piel.tools.openlane.parse.sta_rpt.filter_timing_data_by_net_name_and_type + piel.tools.openlane.parse.sta_rpt.get_frame_meta_data + piel.tools.openlane.parse.sta_rpt.get_frame_lines_data + piel.tools.openlane.parse.sta_rpt.get_frame_timing_data + piel.tools.openlane.parse.sta_rpt.get_all_timing_data_from_file + piel.tools.openlane.parse.sta_rpt.read_sta_rpt_fwf_file + + + +.. py:function:: calculate_max_frame_amount(file_lines_data: pandas.DataFrame) + + Calculate the maximum frame amount based on the frame IDs in the DataFrame + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Maximum number of frames in the file + :rtype: maximum_frame_amount (int) + + +.. py:function:: calculate_propagation_delay_from_timing_data(net_name_in: str, net_name_out: str, timing_data: pandas.DataFrame) + + Calculate the propagation delay between two nets + + :param net_name_in: Name of the input net + :type net_name_in: str + :param net_name_out: Name of the output net + :type net_name_out: str + :param timing_data: Dataframe containing the timing data + :type timing_data: pd.DataFrame + + :returns: Dataframe containing the propagation delay + :rtype: propagation_delay_dataframe (pd.DataFrame) + + +.. py:function:: calculate_propagation_delay_from_file(file_path: str | pathlib.Path) + + Calculate the propagation delay for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: Dictionary containing the propagation delay + :rtype: propagation_delay (dict) + + +.. py:function:: configure_timing_data_rows(file_lines_data: pandas.DataFrame) + + Identify the timing data lines for each frame and creates a metadata dictionary for frames. + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Dictionary containing the frame metadata + :rtype: frame_meta_data (dict) + + +.. py:function:: configure_frame_id(file_lines_data: pandas.DataFrame) + + Identify the frame delimiters and assign frame ID to each line in the file + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: filter_timing_data_by_net_name_and_type(timing_data: pandas.DataFrame, net_name: str, net_type: str) + + Filter the timing data by net name and type + + :param timing_data: DataFrame containing the timing data + :type timing_data: pd.DataFrame + :param net_name: Net name to be filtered + :type net_name: str + :param net_type: Net type to be filtered + :type net_type: str + + :returns: DataFrame containing the timing data + :rtype: timing_data (pd.DataFrame) + + +.. py:function:: get_frame_meta_data(file_lines_data) + + Get the frame metadata + + :param file_lines_data: DataFrame containing the file lines + :type file_lines_data: pd.DataFrame + + :returns: DataFrame containing the start point name + end_point_name (pd.DataFrame): DataFrame containing the end point name + path_group_name (pd.DataFrame): DataFrame containing the path group name + path_type_name (pd.DataFrame): DataFrame containing the path type name + :rtype: start_point_name (pd.DataFrame) + + +.. py:function:: get_frame_lines_data(file_path: str | pathlib.Path) + + Calculate the timing data for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: DataFrame containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: get_frame_timing_data(file: str | pathlib.Path, frame_meta_data: dict, frame_id: int = 0) + + Extract the timing data from the file + + :param file: Address of the file + :type file: str | pathlib.Path + :param frame_meta_data: Dictionary containing the frame metadata + :type frame_meta_data: dict + :param frame_id: Frame ID to be read + :type frame_id: int + + :returns: DataFrame containing the timing data + :rtype: timing_data (pd.DataFrame) + + +.. py:function:: get_all_timing_data_from_file(file_path: str | pathlib.Path) + + Calculate the timing data for each frame in the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: Dictionary containing the timing data for each frame + :rtype: frame_timing_data (dict) + + +.. py:function:: read_sta_rpt_fwf_file(file: str | pathlib.Path, frame_meta_data: dict, frame_id: int = 0) + + Read the fixed width file and return a DataFrame + + :param file: Address of the file + :type file: str | pathlib.Path + :param frame_meta_data: Dictionary containing the frame metadata + :type frame_meta_data: dict + :param frame_id: Frame ID to be read + :type frame_id: int + + :returns: DataFrame containing the file data + :rtype: file_data (pd.DataFrame) diff --git a/docs/autoapi/piel/tools/openlane/parse/utils/index.rst b/docs/autoapi/piel/tools/openlane/parse/utils/index.rst new file mode 100644 index 00000000..8315394c --- /dev/null +++ b/docs/autoapi/piel/tools/openlane/parse/utils/index.rst @@ -0,0 +1,70 @@ +:py:mod:`piel.tools.openlane.parse.utils` +========================================= + +.. py:module:: piel.tools.openlane.parse.utils + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.openlane.parse.utils.contains_in_lines + piel.tools.openlane.parse.utils.create_file_lines_dataframe + piel.tools.openlane.parse.utils.get_file_line_by_keyword + piel.tools.openlane.parse.utils.read_file_lines + + + +.. py:function:: contains_in_lines(file_lines_data: pandas.DataFrame, keyword: str) + + Check if the keyword is contained in the file lines + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + :param keyword: Keyword to search for + :type keyword: str + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: create_file_lines_dataframe(file_lines_raw) + + Create a DataFrame from the raw lines of a file + + :param file_lines_raw: list containing the file lines + :type file_lines_raw: list + + :returns: Dataframe containing the file lines + :rtype: file_lines_data (pd.DataFrame) + + +.. py:function:: get_file_line_by_keyword(file_lines_data: pandas.DataFrame, keyword: str, regex: str) + + Extract the data from the file lines using the given keyword and regex + + :param file_lines_data: Dataframe containing the file lines + :type file_lines_data: pd.DataFrame + :param keyword: Keyword to search for + :type keyword: str + :param regex: Regex to extract the data + :type regex: str + + :returns: Dataframe containing the extracted values + :rtype: extracted_values (pd.DataFrame) + + +.. py:function:: read_file_lines(file_path: str | pathlib.Path) + + Extract lines from the file + + :param file_path: Path to the file + :type file_path: str | pathlib.Path + + :returns: list containing the file lines + :rtype: file_lines_raw (list) diff --git a/docs/autoapi/piel/tools/openlane/utils/index.rst b/docs/autoapi/piel/tools/openlane/utils/index.rst new file mode 100644 index 00000000..805fa429 --- /dev/null +++ b/docs/autoapi/piel/tools/openlane/utils/index.rst @@ -0,0 +1,26 @@ +:py:mod:`piel.tools.openlane.utils` +=================================== + +.. py:module:: piel.tools.openlane.utils + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.openlane.utils.find_design_run + + + +.. py:function:: find_design_run(design_directory: piel.config.piel_path_types, run_name: str | None = None) -> pathlib.Path + + For a given `design_directory`, the `openlane` output can be found in the `runs` subdirectory. + + They get sorted based on a reverse `list.sort()` method. + + # TODO docs diff --git a/docs/autoapi/piel/tools/openlane/v1/index.rst b/docs/autoapi/piel/tools/openlane/v1/index.rst new file mode 100644 index 00000000..2151d540 --- /dev/null +++ b/docs/autoapi/piel/tools/openlane/v1/index.rst @@ -0,0 +1,157 @@ +:py:mod:`piel.tools.openlane.v1` +================================ + +.. py:module:: piel.tools.openlane.v1 + +.. autoapi-nested-parse:: + + These set of functions aim to provide functionality to automate interacting with OpenLanes v1 design into Python environment, whilst `OpenLanes2` is under development. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.openlane.v1.check_config_json_exists_openlane_v1 + piel.tools.openlane.v1.check_design_exists_openlane_v1 + piel.tools.openlane.v1.configure_and_run_design_openlane_v1 + piel.tools.openlane.v1.configure_flow_script_openlane_v1 + piel.tools.openlane.v1.configure_parametric_designs_openlane_v1 + piel.tools.openlane.v1.create_parametric_designs_openlane_v1 + piel.tools.openlane.v1.get_latest_version_root_openlane_v1 + piel.tools.openlane.v1.get_design_directory_from_root_openlane_v1 + piel.tools.openlane.v1.read_configuration_openlane_v1 + piel.tools.openlane.v1.write_configuration_openlane_v1 + + + +.. py:function:: check_config_json_exists_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> bool + + Checks if a design has a `config.json` file. + + :param design_name: Name of the design. + :type design_name: str + + :returns: True if `config.json` exists. + :rtype: config_json_exists(bool) + + +.. py:function:: check_design_exists_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> bool + + Checks if a design exists in the OpenLane v1 design folder. + + Lists all designs inside the Openlane V1 design root. + + :param design_name: Name of the design. + :type design_name: str + + :returns: True if design exists. + :rtype: design_exists(bool) + + +.. py:function:: configure_and_run_design_openlane_v1(design_name: str, configuration: dict | None = None, root_directory: str | pathlib.Path | None = None) -> None + + Configures and runs an OpenLane v1 design. + + This function does the following: + 1. Check that the design_directory provided is under $OPENLANE_ROOT//designs + 2. Check if `config.json` has already been provided for this design. If a configuration dictionary is inputted into the function parameters, then it overwrites the default `config.json`. + 3. Create a script directory, a script is written and permissions are provided for it to be executable. + 4. Permit and execute the `openlane_flow.sh` script in the `scripts` directory. + + :param design_name: Name of the design. + :type design_name: str + :param configuration: Configuration dictionary. + :type configuration: dict | None + :param root_directory: Design directory. + :type root_directory: str | pathlib.Path + + :returns: None + + +.. py:function:: configure_flow_script_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> None + + Configures the OpenLane v1 flow script after checking that the design directory exists. + + :param design_directory: Design directory. Defaults to latest OpenLane root. + :type design_directory: str | pathlib.Path | None + + :returns: None + + +.. py:function:: configure_parametric_designs_openlane_v1(design_name: str, parameter_sweep_dictionary: dict, add_id: bool = True) -> list + + For a given `source_design_directory`, this function reads in the config.json file and returns a set of parametric sweeps that gets used when creating a set of parametric designs. + + :param add_id: Add an ID to the design name. Defaults to True. + :type add_id: bool + :param parameter_sweep_dictionary: Dictionary of parameters to sweep. + :type parameter_sweep_dictionary: dict + :param source_design_directory: Source design directory. + :type source_design_directory: str | pathlib.Path + + :returns: List of configurations to sweep. + :rtype: configuration_sweep(list) + + +.. py:function:: create_parametric_designs_openlane_v1(design_name: str, parameter_sweep_dictionary: dict, target_directory: str | pathlib.Path | None = None) -> None + + Takes a OpenLane v1 source directory and creates a parametric combination of these designs. + + :param design_name: Name of the design. + :type design_name: str + :param parameter_sweep_dictionary: Dictionary of parameters to sweep. + :type parameter_sweep_dictionary: dict + :param target_directory: Optional target directory. + :type target_directory: str | pathlib.Path | None + + :returns: None + + +.. py:function:: get_latest_version_root_openlane_v1() -> pathlib.Path + + Gets the latest version root of OpenLane v1. + + +.. py:function:: get_design_directory_from_root_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> pathlib.Path + + Gets the design directory from the root directory. + + :param design_name: Name of the design. + :type design_name: str + :param root_directory: Design directory. + :type root_directory: str | pathlib.Path + + :returns: Design directory. + :rtype: design_directory(pathlib.Path) + + +.. py:function:: read_configuration_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) -> dict + + Reads a `config.json` from a design directory. + + :param design_name: Design name. + :type design_name: str + :param root_directory: Design directory. + :type root_directory: str | pathlib.Path + + :returns: Configuration dictionary. + :rtype: configuration(dict) + + +.. py:function:: write_configuration_openlane_v1(configuration: dict, design_directory: str | pathlib.Path) -> None + + Writes a `config.json` onto a `design_directory` + + :param configuration: OpenLane configuration dictionary. + :type configuration: dict + :param design_directory: Design directory PATH. + :type design_directory: str + + :returns: None diff --git a/docs/autoapi/piel/tools/openlane/v2/index.rst b/docs/autoapi/piel/tools/openlane/v2/index.rst new file mode 100644 index 00000000..8f903041 --- /dev/null +++ b/docs/autoapi/piel/tools/openlane/v2/index.rst @@ -0,0 +1,29 @@ +:py:mod:`piel.tools.openlane.v2` +================================ + +.. py:module:: piel.tools.openlane.v2 + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.openlane.v2.run_openlane_flow + + + +.. py:function:: run_openlane_flow(configuration: dict | None = test_spm_open_lane_configuration, design_directory: piel.config.piel_path_types = '/foss/designs/spm') -> None + + Runs the OpenLane flow. + + :param configuration: OpenLane configuration dictionary. If none is present it will default to the config.json file on the design_directory. + :type configuration: dict + :param design_directory: Design directory PATH. + :type design_directory: piel_path_types + + :returns: None diff --git a/docs/autoapi/piel/tools/qutip/fock/index.rst b/docs/autoapi/piel/tools/qutip/fock/index.rst new file mode 100644 index 00000000..94ad12d6 --- /dev/null +++ b/docs/autoapi/piel/tools/qutip/fock/index.rst @@ -0,0 +1,54 @@ +:py:mod:`piel.tools.qutip.fock` +=============================== + +.. py:module:: piel.tools.qutip.fock + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.qutip.fock.fock_state_to_photon_number_factorial + piel.tools.qutip.fock.fock_state_nonzero_indexes + + + +.. py:function:: fock_state_to_photon_number_factorial(fock_state: qutip.Qobj) + + This function converts a Fock state defined as: + + .. math:: + + ewcommand{\ket}[1]{\left|{#1} + ight + angle} + \ket{f_1} = \ket{j_1, j_2, ... j_N}$ + + and returns: + + .. math:: + + j_1^{'}! j_2^{'}! ... j_N^{'}! + + Args: + fock_state (qutip.Qobj): A QuTip QObj representation of the Fock state. + + Returns: + float: The photon number factorial of the Fock state. + + + +.. py:function:: fock_state_nonzero_indexes(fock_state: qutip.Qobj) + + This function returns the indexes of the nonzero elements of a Fock state. + + :param fock_state: A QuTip QObj representation of the Fock state. + :type fock_state: qutip.Qobj + + :returns: The indexes of the nonzero elements of the Fock state. + :rtype: tuple diff --git a/docs/autoapi/piel/tools/qutip/index.rst b/docs/autoapi/piel/tools/qutip/index.rst new file mode 100644 index 00000000..dc5fd50e --- /dev/null +++ b/docs/autoapi/piel/tools/qutip/index.rst @@ -0,0 +1,106 @@ +:py:mod:`piel.tools.qutip` +========================== + +.. py:module:: piel.tools.qutip + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + fock/index.rst + unitary/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.qutip.fock_state_nonzero_indexes + piel.tools.qutip.fock_state_to_photon_number_factorial + piel.tools.qutip.verify_matrix_is_unitary + piel.tools.qutip.subunitary_selection_on_range + piel.tools.qutip.subunitary_selection_on_index + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.qutip.standard_s_parameters_to_qutip_qobj + + +.. py:function:: fock_state_nonzero_indexes(fock_state: qutip.Qobj) + + This function returns the indexes of the nonzero elements of a Fock state. + + :param fock_state: A QuTip QObj representation of the Fock state. + :type fock_state: qutip.Qobj + + :returns: The indexes of the nonzero elements of the Fock state. + :rtype: tuple + + +.. py:function:: fock_state_to_photon_number_factorial(fock_state: qutip.Qobj) + + This function converts a Fock state defined as: + + .. math:: + + ewcommand{\ket}[1]{\left|{#1} + ight + angle} + \ket{f_1} = \ket{j_1, j_2, ... j_N}$ + + and returns: + + .. math:: + + j_1^{'}! j_2^{'}! ... j_N^{'}! + + Args: + fock_state (qutip.Qobj): A QuTip QObj representation of the Fock state. + + Returns: + float: The photon number factorial of the Fock state. + + + +.. py:data:: standard_s_parameters_to_qutip_qobj + + + +.. py:function:: verify_matrix_is_unitary(matrix: jax.numpy.ndarray) -> bool + + Verify that the matrix is unitary. + + :param matrix: The matrix to verify. + :type matrix: jnp.ndarray + + :returns: True if the matrix is unitary, False otherwise. + :rtype: bool + + +.. py:function:: subunitary_selection_on_range(unitary_matrix: jax.numpy.ndarray, stop_index: tuple, start_index: Optional[tuple] = (0, 0)) + + This function returns a unitary between the indexes selected, and verifies the indexes are valid by checking that + the output matrix is also a unitary. + + TODO implement validation of a 2D matrix. + + +.. py:function:: subunitary_selection_on_index(unitary_matrix: jax.numpy.ndarray, rows_index: jax.numpy.ndarray | tuple, columns_index: jax.numpy.ndarray | tuple) + + This function returns a unitary between the indexes selected, and verifies the indexes are valid by checking that + the output matrix is also a unitary. + + TODO implement validation of a 2D matrix. diff --git a/docs/autoapi/piel/tools/qutip/unitary/index.rst b/docs/autoapi/piel/tools/qutip/unitary/index.rst new file mode 100644 index 00000000..f828430a --- /dev/null +++ b/docs/autoapi/piel/tools/qutip/unitary/index.rst @@ -0,0 +1,57 @@ +:py:mod:`piel.tools.qutip.unitary` +================================== + +.. py:module:: piel.tools.qutip.unitary + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.qutip.unitary.subunitary_selection_on_index + piel.tools.qutip.unitary.subunitary_selection_on_range + piel.tools.qutip.unitary.verify_matrix_is_unitary + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.qutip.unitary.standard_s_parameters_to_qutip_qobj + + +.. py:function:: subunitary_selection_on_index(unitary_matrix: jax.numpy.ndarray, rows_index: jax.numpy.ndarray | tuple, columns_index: jax.numpy.ndarray | tuple) + + This function returns a unitary between the indexes selected, and verifies the indexes are valid by checking that + the output matrix is also a unitary. + + TODO implement validation of a 2D matrix. + + +.. py:function:: subunitary_selection_on_range(unitary_matrix: jax.numpy.ndarray, stop_index: tuple, start_index: Optional[tuple] = (0, 0)) + + This function returns a unitary between the indexes selected, and verifies the indexes are valid by checking that + the output matrix is also a unitary. + + TODO implement validation of a 2D matrix. + + +.. py:function:: verify_matrix_is_unitary(matrix: jax.numpy.ndarray) -> bool + + Verify that the matrix is unitary. + + :param matrix: The matrix to verify. + :type matrix: jnp.ndarray + + :returns: True if the matrix is unitary, False otherwise. + :rtype: bool + + +.. py:data:: standard_s_parameters_to_qutip_qobj diff --git a/docs/autoapi/piel/tools/sax/index.rst b/docs/autoapi/piel/tools/sax/index.rst new file mode 100644 index 00000000..437c504b --- /dev/null +++ b/docs/autoapi/piel/tools/sax/index.rst @@ -0,0 +1,168 @@ +:py:mod:`piel.tools.sax` +======================== + +.. py:module:: piel.tools.sax + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + utils/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.sax.get_sdense_ports_index + piel.tools.sax.sax_to_s_parameters_standard_matrix + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.sax.snet + + +.. py:function:: get_sdense_ports_index(input_ports_order: tuple, all_ports_index: dict) -> dict + + This function returns the ports index of the sax dense S-parameter matrix. + + Given that the order of the iteration is provided by the user, the dictionary keys will also be ordered + accordingly when iterating over them. This requires the user to provide a set of ordered. + + TODO verify reasonable iteration order. + + .. code-block:: python + + # The input_ports_order can be a tuple of tuples that contain the index and port name. Eg. + input_ports_order = ((0, "in_o_0"), (5, "in_o_1"), (6, "in_o_2"), (7, "in_o_3")) + # The all_ports_index is a dictionary of the ports index. Eg. + all_ports_index = { + "in_o_0": 0, + "out_o_0": 1, + "out_o_1": 2, + "out_o_2": 3, + "out_o_3": 4, + "in_o_1": 5, + "in_o_2": 6, + "in_o_3": 7, + } + # Output + {"in_o_0": 0, "in_o_1": 5, "in_o_2": 6, "in_o_3": 7} + + :param input_ports_order: The ports order tuple. Can be a tuple of tuples that contain the index and port name. + :type input_ports_order: tuple + :param all_ports_index: The ports index dictionary. + :type all_ports_index: dict + + :returns: The ordered input ports index tuple. + :rtype: tuple + + +.. py:function:: sax_to_s_parameters_standard_matrix(sax_input: sax.SType, input_ports_order: tuple | None = None) -> tuple + + A ``sax`` S-parameter SDict is provided as a dictionary of tuples with (port0, port1) as the key. This + determines the direction of the scattering relationship. It means that the number of terms in an S-parameter + matrix is the number of ports squared. + + In order to generalise, this function returns both the S-parameter matrices and the indexing ports based on the + amount provided. In terms of computational speed, we definitely would like this function to be algorithmically + very fast. For now, I will write a simple python implementation and optimise in the future. + + It is possible to see the `sax` SDense notation equivalence here: + https://flaport.github.io/sax/nbs/08_backends.html + + .. code-block:: python + + import jax.numpy as jnp + from sax.core import SDense + + # Directional coupler SDense representation + dc_sdense: SDense = ( + jnp.array([[0, 0, τ, κ], [0, 0, κ, τ], [τ, κ, 0, 0], [κ, τ, 0, 0]]), + {"in0": 0, "in1": 1, "out0": 2, "out1": 3}, + ) + + + # Directional coupler SDict representation + # Taken from https://flaport.github.io/sax/nbs/05_models.html + def coupler(*, coupling: float = 0.5) -> SDict: + kappa = coupling**0.5 + tau = (1 - coupling) ** 0.5 + sdict = reciprocal( + { + ("in0", "out0"): tau, + ("in0", "out1"): 1j * kappa, + ("in1", "out0"): 1j * kappa, + ("in1", "out1"): tau, + } + ) + return sdict + + If we were to relate the mapping accordingly based on the ports indexes, a S-Parameter matrix in the form of + :math:`S_{(output,i),(input,i)}` would be: + + .. math:: + + S = \begin{bmatrix} + S_{00} & S_{10} \\ + S_{01} & S_{11} \\ + \end{bmatrix} = + \begin{bmatrix} + \tau & j \kappa \\ + j \kappa & \tau \\ + \end{bmatrix} + + Note that the standard S-parameter and hence unitary representation is in the form of: + + .. math:: + + S = \begin{bmatrix} + S_{00} & S_{01} \\ + S_{10} & S_{11} \\ + \end{bmatrix} + + + .. math:: + + \begin{bmatrix} + b_{1} \\ + \vdots \\ + b_{n} + \end{bmatrix} + = + \begin{bmatrix} + S_{11} & \dots & S_{1n} \\ + \vdots & \ddots & \vdots \\ + S_{n1} & \dots & S_{nn} + \end{bmatrix} + \begin{bmatrix} + a_{1} \\ + \vdots \\ + a_{n} + \end{bmatrix} + + TODO check with Floris, does this mean we need to transpose the matrix? + + :param sax_input: The sax S-parameter dictionary. + :type sax_input: sax.SType + :param input_ports_order: The ports order tuple containing the names and order of the input ports. + :type input_ports_order: tuple + + :returns: The S-parameter matrix and the input ports index tuple in the standard S-parameter notation. + :rtype: tuple + + +.. py:data:: snet diff --git a/docs/autoapi/piel/tools/sax/utils/index.rst b/docs/autoapi/piel/tools/sax/utils/index.rst new file mode 100644 index 00000000..adb099b5 --- /dev/null +++ b/docs/autoapi/piel/tools/sax/utils/index.rst @@ -0,0 +1,164 @@ +:py:mod:`piel.tools.sax.utils` +============================== + +.. py:module:: piel.tools.sax.utils + +.. autoapi-nested-parse:: + + This file provides a set of utilities that allow much easier integration between `sax` and the relevant tools that we use. + + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.sax.utils.get_sdense_ports_index + piel.tools.sax.utils.sax_to_s_parameters_standard_matrix + + + +Attributes +~~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.sax.utils.snet + + +.. py:function:: get_sdense_ports_index(input_ports_order: tuple, all_ports_index: dict) -> dict + + This function returns the ports index of the sax dense S-parameter matrix. + + Given that the order of the iteration is provided by the user, the dictionary keys will also be ordered + accordingly when iterating over them. This requires the user to provide a set of ordered. + + TODO verify reasonable iteration order. + + .. code-block:: python + + # The input_ports_order can be a tuple of tuples that contain the index and port name. Eg. + input_ports_order = ((0, "in_o_0"), (5, "in_o_1"), (6, "in_o_2"), (7, "in_o_3")) + # The all_ports_index is a dictionary of the ports index. Eg. + all_ports_index = { + "in_o_0": 0, + "out_o_0": 1, + "out_o_1": 2, + "out_o_2": 3, + "out_o_3": 4, + "in_o_1": 5, + "in_o_2": 6, + "in_o_3": 7, + } + # Output + {"in_o_0": 0, "in_o_1": 5, "in_o_2": 6, "in_o_3": 7} + + :param input_ports_order: The ports order tuple. Can be a tuple of tuples that contain the index and port name. + :type input_ports_order: tuple + :param all_ports_index: The ports index dictionary. + :type all_ports_index: dict + + :returns: The ordered input ports index tuple. + :rtype: tuple + + +.. py:function:: sax_to_s_parameters_standard_matrix(sax_input: sax.SType, input_ports_order: tuple | None = None) -> tuple + + A ``sax`` S-parameter SDict is provided as a dictionary of tuples with (port0, port1) as the key. This + determines the direction of the scattering relationship. It means that the number of terms in an S-parameter + matrix is the number of ports squared. + + In order to generalise, this function returns both the S-parameter matrices and the indexing ports based on the + amount provided. In terms of computational speed, we definitely would like this function to be algorithmically + very fast. For now, I will write a simple python implementation and optimise in the future. + + It is possible to see the `sax` SDense notation equivalence here: + https://flaport.github.io/sax/nbs/08_backends.html + + .. code-block:: python + + import jax.numpy as jnp + from sax.core import SDense + + # Directional coupler SDense representation + dc_sdense: SDense = ( + jnp.array([[0, 0, τ, κ], [0, 0, κ, τ], [τ, κ, 0, 0], [κ, τ, 0, 0]]), + {"in0": 0, "in1": 1, "out0": 2, "out1": 3}, + ) + + + # Directional coupler SDict representation + # Taken from https://flaport.github.io/sax/nbs/05_models.html + def coupler(*, coupling: float = 0.5) -> SDict: + kappa = coupling**0.5 + tau = (1 - coupling) ** 0.5 + sdict = reciprocal( + { + ("in0", "out0"): tau, + ("in0", "out1"): 1j * kappa, + ("in1", "out0"): 1j * kappa, + ("in1", "out1"): tau, + } + ) + return sdict + + If we were to relate the mapping accordingly based on the ports indexes, a S-Parameter matrix in the form of + :math:`S_{(output,i),(input,i)}` would be: + + .. math:: + + S = \begin{bmatrix} + S_{00} & S_{10} \\ + S_{01} & S_{11} \\ + \end{bmatrix} = + \begin{bmatrix} + \tau & j \kappa \\ + j \kappa & \tau \\ + \end{bmatrix} + + Note that the standard S-parameter and hence unitary representation is in the form of: + + .. math:: + + S = \begin{bmatrix} + S_{00} & S_{01} \\ + S_{10} & S_{11} \\ + \end{bmatrix} + + + .. math:: + + \begin{bmatrix} + b_{1} \\ + \vdots \\ + b_{n} + \end{bmatrix} + = + \begin{bmatrix} + S_{11} & \dots & S_{1n} \\ + \vdots & \ddots & \vdots \\ + S_{n1} & \dots & S_{nn} + \end{bmatrix} + \begin{bmatrix} + a_{1} \\ + \vdots \\ + a_{n} + \end{bmatrix} + + TODO check with Floris, does this mean we need to transpose the matrix? + + :param sax_input: The sax S-parameter dictionary. + :type sax_input: sax.SType + :param input_ports_order: The ports order tuple containing the names and order of the input ports. + :type input_ports_order: tuple + + :returns: The S-parameter matrix and the input ports index tuple in the standard S-parameter notation. + :rtype: tuple + + +.. py:data:: snet diff --git a/docs/autoapi/piel/tools/thewalrus/index.rst b/docs/autoapi/piel/tools/thewalrus/index.rst new file mode 100644 index 00000000..9d78ba55 --- /dev/null +++ b/docs/autoapi/piel/tools/thewalrus/index.rst @@ -0,0 +1,45 @@ +:py:mod:`piel.tools.thewalrus` +============================== + +.. py:module:: piel.tools.thewalrus + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + operations/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.thewalrus.unitary_permanent + + + +.. py:function:: unitary_permanent(unitary_matrix: jax.numpy.ndarray) -> tuple + + The permanent of a unitary is used to determine the state probability of combinatorial Gaussian boson samping systems. + + ``thewalrus`` Ryser's algorithm permananet implementation is described here: https://the-walrus.readthedocs.io/en/latest/gallery/permanent_tutorial.html + + Note that this function needs to be as optimised as possible, so we need to minimise our computational complexity of our operation. + + # TODO implement validation + # TODO maybe implement subroutine if computation is taking forever. + # TODO why two outputs? Understand this properly later. + + :param unitary_permanent: The unitary matrix. + :type unitary_permanent: np.ndarray + + :returns: The circuit permanent and the time it took to compute it. + :rtype: tuple diff --git a/docs/autoapi/piel/tools/thewalrus/operations/index.rst b/docs/autoapi/piel/tools/thewalrus/operations/index.rst new file mode 100644 index 00000000..33e62822 --- /dev/null +++ b/docs/autoapi/piel/tools/thewalrus/operations/index.rst @@ -0,0 +1,36 @@ +:py:mod:`piel.tools.thewalrus.operations` +========================================= + +.. py:module:: piel.tools.thewalrus.operations + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.tools.thewalrus.operations.unitary_permanent + + + +.. py:function:: unitary_permanent(unitary_matrix: jax.numpy.ndarray) -> tuple + + The permanent of a unitary is used to determine the state probability of combinatorial Gaussian boson samping systems. + + ``thewalrus`` Ryser's algorithm permananet implementation is described here: https://the-walrus.readthedocs.io/en/latest/gallery/permanent_tutorial.html + + Note that this function needs to be as optimised as possible, so we need to minimise our computational complexity of our operation. + + # TODO implement validation + # TODO maybe implement subroutine if computation is taking forever. + # TODO why two outputs? Understand this properly later. + + :param unitary_permanent: The unitary matrix. + :type unitary_permanent: np.ndarray + + :returns: The circuit permanent and the time it took to compute it. + :rtype: tuple diff --git a/docs/autoapi/piel/visual/auto_plot_multiple/index.rst b/docs/autoapi/piel/visual/auto_plot_multiple/index.rst new file mode 100644 index 00000000..cd3a8f39 --- /dev/null +++ b/docs/autoapi/piel/visual/auto_plot_multiple/index.rst @@ -0,0 +1,41 @@ +:py:mod:`piel.visual.auto_plot_multiple` +======================================== + +.. py:module:: piel.visual.auto_plot_multiple + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.visual.auto_plot_multiple.plot_simple_multi_row + piel.visual.auto_plot_multiple.plot_multi_row + + + +.. py:function:: plot_simple_multi_row(data: pandas.DataFrame, x_axis_column_name: str = 't', row_list: list | None = None, y_axis_title_list: list | None = None, x_axis_title: str | None = None) + + Plot multiple rows of data on the same plot. Each row is a different line. Each row is a different y axis. The x + axis is the same for all rows. The y axis title is the same for all rows. + + :param data: Data to plot. + :type data: pd.DataFrame + :param x_axis_column_name: Column name of the x axis. Defaults to "t". + :type x_axis_column_name: str, optional + :param row_list: List of column names to plot. Defaults to None. + :type row_list: list, optional + :param y_axis_title_list: List of y axis titles. Defaults to None. + :type y_axis_title_list: list, optional + :param x_axis_title: Title of the x axis. Defaults to None. + :type x_axis_title: str, optional + + :returns: Matplotlib plot. + :rtype: plt + + +.. py:function:: plot_multi_row(data: pandas.DataFrame) diff --git a/docs/autoapi/piel/visual/data_conversion/index.rst b/docs/autoapi/piel/visual/data_conversion/index.rst new file mode 100644 index 00000000..6989c496 --- /dev/null +++ b/docs/autoapi/piel/visual/data_conversion/index.rst @@ -0,0 +1,70 @@ +:py:mod:`piel.visual.data_conversion` +===================================== + +.. py:module:: piel.visual.data_conversion + + +Module Contents +--------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.visual.data_conversion.append_row_to_dict + piel.visual.data_conversion.points_to_lines_fixed_transient + + + +.. py:function:: append_row_to_dict(data: dict, copy_index: int, set_value: dict) + + Get all the rows of the dictionary. We want to copy and append a row at a particular index of the dictionary values. + Operates on existing data + + :param data: Dictionary of data to be appended. + :param copy_index: Index of the row to be copied. + :param set_value: Dictionary of values to be set at the copied index. + + :returns: None + + +.. py:function:: points_to_lines_fixed_transient(data: pandas.DataFrame | dict, time_index_name: str, fixed_transient_time=1, return_dict: bool = False) + + This function converts specific steady-state point data into steady-state lines with a defined transient time in order to plot digital-style data. + + For example, VCD data tends to be structured in this form: + + .. code-block:: text + + #2001 + b1001 " + b10010 # + b1001 ! + #4001 + b1011 " + b1011 # + b0 ! + #6001 + b101 " + + This means that even when tokenizing the data, when visualising it in a wave plotter such as GTKWave, the signals + get converted from token specific times to transient signals by a corresponding transient rise time. If we want + to plot the data correspondingly in Python, it is necessary to add some form of transient signal translation. + Note that this operates on a dataframe where the electrical time signals are clearly defined. It copies the + corresponding steady-state data points whilst adding data points for the time-index accordingly. + + It starts by creating a copy of the initial dataframe as to not overwrite the existing data. We have an initial + time data point that tends to start at time 0. This means we need to add a point just before the next steady + state point transition. So what we want to do is copy the existing row and just change the time to be the + `fixed_transient_time` before the next transition. + + Doesn't append on penultimate row. + + :param data: Dataframe or dictionary of data to be converted. + :param time_index_name: Name of the time index column. + :param fixed_transient_time: Time of the transient signal. + :param return_dict: Return a dictionary instead of a dataframe. + + :returns: Dataframe or dictionary of data with steady-state lines. diff --git a/docs/autoapi/piel/visual/index.rst b/docs/autoapi/piel/visual/index.rst new file mode 100644 index 00000000..f9c3bf92 --- /dev/null +++ b/docs/autoapi/piel/visual/index.rst @@ -0,0 +1,105 @@ +:py:mod:`piel.visual` +===================== + +.. py:module:: piel.visual + + +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + + auto_plot_multiple/index.rst + data_conversion/index.rst + + +Package Contents +---------------- + + +Functions +~~~~~~~~~ + +.. autoapisummary:: + + piel.visual.plot_simple_multi_row + piel.visual.plot_multi_row + piel.visual.append_row_to_dict + piel.visual.points_to_lines_fixed_transient + + + +.. py:function:: plot_simple_multi_row(data: pandas.DataFrame, x_axis_column_name: str = 't', row_list: list | None = None, y_axis_title_list: list | None = None, x_axis_title: str | None = None) + + Plot multiple rows of data on the same plot. Each row is a different line. Each row is a different y axis. The x + axis is the same for all rows. The y axis title is the same for all rows. + + :param data: Data to plot. + :type data: pd.DataFrame + :param x_axis_column_name: Column name of the x axis. Defaults to "t". + :type x_axis_column_name: str, optional + :param row_list: List of column names to plot. Defaults to None. + :type row_list: list, optional + :param y_axis_title_list: List of y axis titles. Defaults to None. + :type y_axis_title_list: list, optional + :param x_axis_title: Title of the x axis. Defaults to None. + :type x_axis_title: str, optional + + :returns: Matplotlib plot. + :rtype: plt + + +.. py:function:: plot_multi_row(data: pandas.DataFrame) + + +.. py:function:: append_row_to_dict(data: dict, copy_index: int, set_value: dict) + + Get all the rows of the dictionary. We want to copy and append a row at a particular index of the dictionary values. + Operates on existing data + + :param data: Dictionary of data to be appended. + :param copy_index: Index of the row to be copied. + :param set_value: Dictionary of values to be set at the copied index. + + :returns: None + + +.. py:function:: points_to_lines_fixed_transient(data: pandas.DataFrame | dict, time_index_name: str, fixed_transient_time=1, return_dict: bool = False) + + This function converts specific steady-state point data into steady-state lines with a defined transient time in order to plot digital-style data. + + For example, VCD data tends to be structured in this form: + + .. code-block:: text + + #2001 + b1001 " + b10010 # + b1001 ! + #4001 + b1011 " + b1011 # + b0 ! + #6001 + b101 " + + This means that even when tokenizing the data, when visualising it in a wave plotter such as GTKWave, the signals + get converted from token specific times to transient signals by a corresponding transient rise time. If we want + to plot the data correspondingly in Python, it is necessary to add some form of transient signal translation. + Note that this operates on a dataframe where the electrical time signals are clearly defined. It copies the + corresponding steady-state data points whilst adding data points for the time-index accordingly. + + It starts by creating a copy of the initial dataframe as to not overwrite the existing data. We have an initial + time data point that tends to start at time 0. This means we need to add a point just before the next steady + state point transition. So what we want to do is copy the existing row and just change the time to be the + `fixed_transient_time` before the next transition. + + Doesn't append on penultimate row. + + :param data: Dataframe or dictionary of data to be converted. + :param time_index_name: Name of the time index column. + :param fixed_transient_time: Time of the transient signal. + :param return_dict: Return a dictionary instead of a dataframe. + + :returns: Dataframe or dictionary of data with steady-state lines.