piel

Contents

piel#

Top-level package for piel.

Subpackages#

Submodules#

Package Contents#

Functions#

check_path_exists(→ bool)

Checks if a directory exists.

check_example_design(→ bool)

We copy the example simple_design from docs to the /foss/designs in the iic-osic-tools environment.

copy_source_folder(→ None)

Copies the files from a source_directory to a target_directory

copy_example_design(→ None)

We copy the example simple_design from docs to the /foss/designs in the iic-osic-tools environment.

create_new_directory(→ bool)

Creates a new directory.

create_piel_home_directory(→ None)

Creates the piel home directory.

delete_path(→ None)

Deletes a path.

delete_path_list_in_directory(→ None)

Deletes a list of files in a directory.

get_files_recursively_in_directory(path[, extension])

Returns a list of files in a directory.

get_top_level_script_directory(→ pathlib.Path)

Attempts to return the top-level script directory when this file is run,

get_id_map_directory_dictionary(path_list, target_prefix)

Returns a dictionary of ids to directories.

list_prefix_match_directories(output_directory, ...)

Returns a list of directories that match a prefix.

permit_directory_all(→ None)

Permits a directory to be read, written and executed. Use with care as it can be a source for security issues.

permit_script_execution(→ None)

Permits the execution of a script.

read_json(→ dict)

Reads a JSON file.

rename_file(→ None)

Renames a file.

rename_files_in_directory(→ None)

Renames all files in a directory.

replace_string_in_file(file_path, match_string, ...)

Replaces a string in a file.

replace_string_in_directory_files(target_directory, ...)

Replaces a string in all files in a directory.

return_path(→ pathlib.Path)

Returns a pathlib.Path to be able to perform operations accordingly internally.

run_script(→ None)

Runs a script on the filesystem script_path.

write_file(→ None)

Records a script_name in the scripts project directory.

create_gdsfactory_component_from_openlane(...)

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.

gdsfactory_netlist_to_spice_netlist(→ hdl21.Module)

This function converts a GDSFactory electrical netlist into a standard SPICE netlist. It follows the same

construct_hdl21_module(→ hdl21.Module)

This function converts a gdsfactory-spice converted netlist using the component models into a SPICE circuit.

convert_connections_to_tuples(connections)

Convert from:

gdsfactory_netlist_with_hdl21_generators(...[, generators])

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.]

sax_circuit_permanent(→ tuple)

The permanent of a unitary is used to determine the state probability of combinatorial Gaussian boson samping systems.

unitary_permanent(→ tuple)

The permanent of a unitary is used to determine the state probability of combinatorial Gaussian boson samping systems.

sax_to_ideal_qutip_unitary(sax_input[, input_ports_order])

This function converts the calculated S-parameters into a standard Unitary matrix topology so that the shape and

verify_sax_model_is_unitary(→ bool)

Verify that the model is unitary.

fock_transition_probability_amplitude(...)

This function returns the transition probability amplitude between two Fock states when propagating in between

convert_2d_array_to_string(list_2D)

This function is particularly useful to convert digital data when it is represented as a 2D array into a set of strings.

convert_array_type(array, output_type)

absolute_to_threshold(→ package_array_types)

This function converts the computed optical transmission arrays to single bit digital signals.

single_parameter_sweep(base_design_configuration, ...)

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.

multi_parameter_sweep(→ 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.

create_setup_py(→ None)

This function creates a setup.py file from the config.json file found in the design directory.

create_empty_piel_project(→ None)

This function creates an empty piel-structure project in the target directory. Structuring your files in this way

get_module_folder_type_location(module, folder_type)

This is an easy helper function that saves a particular file in the corresponding location of a piel project structure.

pip_install_local_module(module_path)

This function installs a local module in editable mode.

read_configuration(→ dict)

This function reads the configuration file found in the design directory.

check_cocotb_testbench_exists(→ bool)

Checks if a cocotb testbench exists in the design directory.

configure_cocotb_simulation(design_directory, ...[, ...])

Writes a cocotb makefile.

run_cocotb_simulation(→ subprocess.CompletedProcess)

Equivalent to running the cocotb makefile

get_simulation_output_files_from_design(design_directory)

This function returns a list of all the simulation output files in the design directory.

read_simulation_data(file_path)

This function returns a Pandas dataframe that contains all the simulation data outputted from the simulation run.

simple_plot_simulation_data(simulation_data)

get_input_ports_index(→ 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.

get_matched_ports_tuple_index(ports_index, ...)

This function returns the input ports of a component. However, input ports may have different sets of prefixes

straight_heater_metal_simple(...)

Returns a thermal phase shifter that has properly fixed electrical connectivity to extract a suitable electrical netlist and models.

get_design_from_openlane_migration(v1, design_name_v1, ...)

This function provides the integration mechanism for easily migrating the interconnection with other toolsets from an OpenLane v1 design to an OpenLane v2 design.

extract_datetime_from_path(→ str)

Extracts the datetime from a given run_path and returns it as a string.

find_all_design_runs(→ list[pathlib.Path])

For a given design_directory, the openlane output can be found in the runs subdirectory. This function sorts the runs according to the default notations between both openlane and openlane2 run formats.

find_latest_design_run(design_directory, run_name, ...)

For a given design_directory, the openlane output can be found in the runs subdirectory. This function sorts the runs according to the default notations between both openlane and openlane2 run formats.

get_gds_path_from_design_run(→ pathlib.Path)

Returns the path to the final GDS generated by OpenLane.

get_design_run_version(→ Literal[v1, v2])

Returns the version of the design run.

sort_design_runs(→ dict[str, list[pathlib.Path]])

For a given design_directory, the openlane output can be found in the runs subdirectory. This function sorts the runs according to the default notations between both openlane and openlane2 run formats.

check_config_json_exists_openlane_v1(→ bool)

Checks if a design has a config.json file.

check_design_exists_openlane_v1(→ bool)

Checks if a design exists in the OpenLane v1 design folder.

configure_and_run_design_openlane_v1(→ None)

Configures and runs an OpenLane v1 design.

configure_parametric_designs_openlane_v1(→ 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.

configure_flow_script_openlane_v1(→ None)

Configures the OpenLane v1 flow script after checking that the design directory exists.

create_parametric_designs_openlane_v1(→ None)

Takes a OpenLane v1 source directory and creates a parametric combination of these designs.

get_design_directory_from_root_openlane_v1(→ pathlib.Path)

Gets the design directory from the root directory.

get_latest_version_root_openlane_v1(→ pathlib.Path)

Gets the latest version root of OpenLane v1.

read_configuration_openlane_v1(→ dict)

Reads a config.json from a design directory.

write_configuration_openlane_v1(→ None)

Writes a config.json onto a design_directory

filter_timing_sta_files(file_list)

Filter the timing sta files from the list of files

filter_power_sta_files(file_list)

Filter the power sta files from the list of files

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.

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.

calculate_max_frame_amount(file_lines_data)

Calculate the maximum frame amount based on the frame IDs in the DataFrame

calculate_propagation_delay_from_file(file_path)

Calculate the propagation delay for each frame in the file

calculate_propagation_delay_from_timing_data(...)

Calculate the propagation delay between two nets

configure_timing_data_rows(file_lines_data)

Identify the timing data lines for each frame and creates a metadata dictionary for frames.

configure_frame_id(file_lines_data)

Identify the frame delimiters and assign frame ID to each line in the file

filter_timing_data_by_net_name_and_type(timing_data, ...)

Filter the timing data by net name and type

get_frame_meta_data(file_lines_data)

Get the frame metadata

get_frame_lines_data(file_path)

Calculate the timing data for each frame in the file

get_frame_timing_data(file, frame_meta_data[, frame_id])

Extract the timing data from the file

get_all_timing_data_from_file(file_path)

Calculate the timing data for each frame in the file

read_sta_rpt_fwf_file(file, frame_meta_data[, frame_id])

Read the fixed width file and return a DataFrame

contains_in_lines(file_lines_data, keyword)

Check if the keyword is contained in the file lines

create_file_lines_dataframe(file_lines_raw)

Create a DataFrame from the raw lines of a file

get_file_line_by_keyword(file_lines_data, keyword, regex)

Extract the data from the file lines using the given keyword and regex

read_file_lines(file_path)

Extract lines from the file

get_all_designs_metrics_openlane_v2(output_directory, ...)

Returns a dictionary of all the metrics for all the designs in the output directory.

read_metrics_openlane_v2(→ dict)

Read design metrics from OpenLane v2 run files.

run_openlane_flow([configuration, design_directory, ...])

Runs the OpenLane v2 flow.

configure_ngspice_simulation([run_directory])

This function configures the NGSPICE simulation for the circuit and returns a simulation class.

configure_operating_point_simulation(testbench, **kwargs)

This function configures the DC operating point simulation for the circuit and returns a simulation class.

configure_transient_simulation(testbench, stop_time_s, ...)

This function configures the transient simulation for the circuit and returns a simulation class.

run_simulation(simulation[, simulator_name, ...])

This function runs the transient simulation for the circuit and returns the results.

convert_numeric_to_prefix(value)

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.

address_value_dictionary_to_function_parameter_dictionary(...)

This function converts an address of an instance with particular parameter values in the form:

compose_recursive_instance_location(recursive_netlist, ...)

This function returns the recursive location of any matching target_component_prefix instances within the recursive_netlist. A function that returns the mapping of the matched_component in the corresponding netlist at any particular level of recursion. This function iterates over a particular level of recursion of a netlist. It returns a list of the missing required components, and updates a dictionary of models that contains a particular matching component. It returns the corresponding list of instances of a particular component at that level of recursion, so that it can be appended upon in order to construct the location of the corresponding matching elements.

get_component_instances(recursive_netlist, ...)

Returns a dictionary of all instances of a given component in a recursive netlist.

get_netlist_instances_by_prefix(→ str)

Returns a list of all instances with a given prefix in a recursive netlist.

get_matched_model_recursive_netlist_instances(...)

This function returns an active component list with a tuple mapping of the location of the active component within the recursive netlist and corresponding model. It will recursively look within a netlist to locate what models use a particular component model. At each stage of recursion, it will compose a list of the elements that implement this matching model in order to relate the model to the instance, and hence the netlist address of the component that needs to be updated in order to functionally implement the model.

get_sdense_ports_index(→ dict)

This function returns the ports index of the sax dense S-parameter matrix.

sax_to_s_parameters_standard_matrix(→ tuple)

A sax S-parameter SDict is provided as a dictionary of tuples with (port0, port1) as the key. This

all_fock_states_from_photon_number(→ list)

For a specific amount of modes, we can generate all the possible Fock states for whatever amount of input photons we desire. This returns a list of all corresponding Fock states.

convert_qobj_to_jax(→ jax.numpy.ndarray)

fock_state_nonzero_indexes(→ tuple[int])

This function returns the indexes of the nonzero elements of a Fock state.

fock_state_to_photon_number_factorial(→ float)

This function converts a Fock state defined as:

fock_states_at_mode_index(→ list)

This function returns a list of valid Fock states that fulfill a condition of having a maximum photon number at a specific mode index.

fock_states_only_individual_modes(→ list)

This function returns a list of valid Fock states where each state has a maximum photon number, but only in one mode.

verify_matrix_is_unitary(→ bool)

Verify that the matrix is unitary.

subunitary_selection_on_range(unitary_matrix, stop_index)

This function returns a unitary between the indexes selected, and verifies the indexes are valid by checking that

subunitary_selection_on_index(unitary_matrix, ...)

This function returns a unitary between the indexes selected, and verifies the indexes are valid by checking that

Attributes#

piel_path_types

array_types

tuple_int_type

package_array_types

delete_simulation_output_files

get_simulation_output_files

snet

convert_output_type

standard_s_parameters_to_qutip_qobj

__author__

__email__

__version__

piel_path_types#
check_path_exists(path: piel.types.piel_path_types, raise_errors: bool = False) bool[source]#

Checks if a directory exists.

Parameters:

path (piel_path_types) – Input path.

Returns:

True if directory exists.

Return type:

directory_exists(bool)

check_example_design(design_name: str = 'simple_design', designs_directory: piel.types.piel_path_types | None = None) bool[source]#

We copy the example simple_design from docs to the /foss/designs in the iic-osic-tools environment.

Parameters:
  • design_name (str) – Name of the design to check.

  • designs_directory (piel_path_types) – Directory that contains the DESIGNS environment flag.

  • TODO (#) –

Returns:

None

copy_source_folder(source_directory: piel.types.piel_path_types, target_directory: piel.types.piel_path_types) None[source]#

Copies the files from a source_directory to a target_directory

Parameters:
  • source_directory (piel_path_types) – Source directory.

  • target_directory (piel_path_types) – Target directory.

Returns:

None

copy_example_design(project_source: Literal[piel, openlane] = 'piel', example_name: str = 'simple_design', target_directory: piel.types.piel_path_types = None, target_project_name: str | None = None) None[source]#

We copy the example simple_design from docs to the /foss/designs in the iic-osic-tools environment.

Parameters:
  • project_source (str) – Source of the project.

  • example_name (str) – Name of the example design.

  • target_directory (piel_path_types) – Target directory.

  • target_project_name (str) – Name of the target project.

Returns:

None

create_new_directory(directory_path: str | pathlib.Path, overwrite: bool = False) bool[source]#

Creates a new directory.

If the parents of the target_directory do not exist, they will be created too.

Parameters:
  • overwrite – Overwrite directory if it already exists.

  • directory_path (str | pathlib.Path) – Input path.

Returns:

None

create_piel_home_directory() None[source]#

Creates the piel home directory.

Returns:

None

delete_path(path: str | pathlib.Path) None[source]#

Deletes a path.

Parameters:

path (str | pathlib.Path) – Input path.

Returns:

None

delete_path_list_in_directory(directory_path: piel.types.piel_path_types, path_list: list, ignore_confirmation: bool = False, validate_individual: bool = False) None[source]#

Deletes a list of files in a directory.

Usage:

```python delete_path_list_in_directory(

directory_path=directory_path, path_list=path_list, ignore_confirmation=True

)#

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

get_files_recursively_in_directory(path: piel.types.piel_path_types, extension: str = '*')[source]#

Returns a list of files in a directory.

Usage:

get_files_recursively_in_directory(‘path/to/directory’, ‘extension’)

Parameters:
  • path (piel_path_types) – Input path.

  • extension (str) – File extension.

Returns:

List of files.

Return type:

file_list(list)

get_top_level_script_directory() pathlib.Path[source]#

Attempts to return the top-level script directory when this file is run, compatible with various execution environments like Jupyter Lab, pytest, PDM, etc. TODO run full verification.

Returns:

Top level script directory.

Return type:

top_level_script_directory(pathlib.Path)

get_id_map_directory_dictionary(path_list: list[piel.types.piel_path_types], target_prefix: str)[source]#

Returns a dictionary of ids to directories.

Usage:

get_id_to_directory_dictionary(path_list, target_prefix)

Parameters:
  • path_list (list[piel_path_types]) – List of paths.

  • target_prefix (str) – Target prefix.

Returns:

Dictionary of ids to directories.

Return type:

id_dict(dict)

list_prefix_match_directories(output_directory: piel.types.piel_path_types, target_prefix: str)[source]#

Returns a list of directories that match a prefix.

Usage:

list_prefix_match_directories(‘path/to/directory’, ‘prefix’)

Parameters:
  • output_directory (piel_path_types) – Output directory.

  • target_prefix (str) – Target prefix.

Returns:

List of directories.

Return type:

matching_dirs(list)

permit_directory_all(directory_path: piel.types.piel_path_types) None[source]#

Permits a directory to be read, written and executed. Use with care as it can be a source for security issues.

Usage:

permit_directory_all(‘path/to/directory’)

Parameters:

directory_path (piel_path_types) – Input path.

Returns:

None

permit_script_execution(script_path: piel.types.piel_path_types) None[source]#

Permits the execution of a script.

Usage:

permit_script_execution(‘path/to/script’)

Parameters:

script_path (piel_path_types) – Script path.

Returns:

None

read_json(path: piel.types.piel_path_types) dict[source]#

Reads a JSON file.

Usage:

read_json(‘path/to/file.json’)

Parameters:

path (piel_path_types) – Input path.

Returns:

JSON data.

Return type:

json_data(dict)

rename_file(match_file_path: piel.types.piel_path_types, renamed_file_path: piel.types.piel_path_types) None[source]#

Renames a file.

Usage:

rename_file(‘path/to/match_file’, ‘path/to/renamed_file’)

Parameters:
  • match_file_path (piel_path_types) – Input path.

  • renamed_file_path (piel_path_types) – Input path.

Returns:

None

rename_files_in_directory(target_directory: piel.types.piel_path_types, match_string: str, renamed_string: str) None[source]#

Renames all files in a directory.

Usage:

rename_files_in_directory(‘path/to/directory’, ‘match_string’, ‘renamed_string’)

Parameters:
  • target_directory (piel_path_types) – Input path.

  • match_string (str) – String to match.

  • renamed_string (str) – String to replace.

Returns:

None

replace_string_in_file(file_path: piel.types.piel_path_types, match_string: str, replace_string: str)[source]#

Replaces a string in a file.

Usage:

replace_string_in_file(‘path/to/file’, ‘match_string’, ‘replace_string’)

Parameters:
  • file_path (piel_path_types) – Input path.

  • match_string (str) – String to match.

  • replace_string (str) – String to replace.

Returns:

None

replace_string_in_directory_files(target_directory: piel.types.piel_path_types, match_string: str, replace_string: str)[source]#

Replaces a string in all files in a directory.

Usage:

replace_string_in_directory_files(‘path/to/directory’, ‘match_string’, ‘replace_string’)

Parameters:
  • target_directory (piel_path_types) – Input path.

  • match_string (str) – String to match.

  • replace_string (str) – String to replace.

Returns:

None

return_path(input_path: piel.types.piel_path_types, as_piel_module: bool = False) pathlib.Path[source]#

Returns a pathlib.Path to be able to perform operations accordingly internally.

This allows us to maintain compatibility between POSIX and Windows systems. When the as_piel_module flag is enabled, it will analyse whether the input path can be treated as a piel module, and treat the returned path as a module would be treated. This comes useful when analysing data generated in this particular structure accordingly.

Usage:

return_path(‘path/to/file’)

Parameters:

input_path (str) – Input path.

Returns:

Pathlib path.

Return type:

pathlib.Path

run_script(script_path: piel.types.piel_path_types) None[source]#

Runs a script on the filesystem script_path.

Parameters:

script_path (piel_path_types) – Script path.

Returns:

None

write_file(directory_path: piel.types.piel_path_types, file_text: str, file_name: str) None[source]#

Records a script_name in the scripts project directory.

Parameters:
  • directory_path (piel_path_types) – Design directory.

  • file_text (str) – Script to write.

  • file_name (str) – Name of the script.

Returns:

None

create_gdsfactory_component_from_openlane(design_name_v1: str | None = None, design_directory: piel.types.piel_path_types | None = None, run_name: str | None = None, v1: bool = True) gdsfactory.Component[source]#

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.

Parameters:
  • design_name_v1 (str) – Design name of the v1 design that can be found within $OPENLANE_ROOT/”<latest>”/designs.

  • design_directory (piel_path_types) – Design directory PATH.

  • run_name (str) – Name of the run to extract the GDS from. If None, it will look at the latest run.

  • v1 (bool) – If True, it will import the design from the OpenLane v1 configuration.

Returns:

GDSFactory component.

Return type:

component(gf.Component)

gdsfactory_netlist_to_spice_netlist(gdsfactory_netlist: dict, generators: dict, **kwargs) hdl21.Module[source]#

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.

Parameters:
  • gdsfactory_netlist – GDSFactory netlist

  • generators – Dictionary of Generators

Returns:

hdl21 module or raw SPICE string

construct_hdl21_module(spice_netlist: dict, **kwargs) hdl21.Module[source]#

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

convert_connections_to_tuples(connections: dict)[source]#

Convert from:

{
'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:

[(('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'))]
gdsfactory_netlist_with_hdl21_generators(gdsfactory_netlist: dict, generators=None)[source]#

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:

>>> 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())
Parameters:
  • gdsfactory_netlist – The netlist from GDSFactory to map to the hdl21 models dictionary.

  • generators – The hdl21 models dictionary to map to the GDSFactory netlist.

Returns:

The GDSFactory netlist with the hdl21 models dictionary.

sax_circuit_permanent(sax_input: sax.SType) tuple[source]#

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.

Parameters:

sax_input (sax.SType) – The sax S-parameter dictionary.

Returns:

The circuit permanent and the time it took to compute it.

Return type:

tuple

unitary_permanent(unitary_matrix: jax.numpy.ndarray) tuple[source]#

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.

Parameters:

unitary_permanent (np.ndarray) – The unitary matrix.

Returns:

The circuit permanent and the time it took to compute it.

Return type:

tuple

sax_to_ideal_qutip_unitary(sax_input: sax.SType, input_ports_order: tuple | None = None)[source]#

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}
Parameters:
  • sax_input (sax.SType) – A dictionary of S-parameters in the form of a SDict from sax.

  • input_ports_order (tuple | None) – The order of the input ports. If None, the default order is used.

Returns:

A QuTip QObj representation of the S-parameters in a unitary matrix.

Return type:

qobj_unitary (qutip.Qobj)

verify_sax_model_is_unitary(model: sax.SType, input_ports_order: tuple | None = None) bool[source]#

Verify that the model is unitary.

Parameters:
  • model (dict) – The model to verify.

  • input_ports_order (tuple | None) – The order of the input ports. If None, the default order is used.

Returns:

True if the model is unitary, False otherwise.

Return type:

bool

fock_transition_probability_amplitude(initial_fock_state: qutip.Qobj | jax.numpy.ndarray, final_fock_state: qutip.Qobj | jax.numpy.ndarray, unitary_matrix: jax.numpy.ndarray)[source]#

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.

\[\]

ewcommand{ket}[1]{left|{#1} ight angle}

The subunitary \(U_{f_1}^{f_2}\) is composed from the larger unitary by selecting the rows from the output state Fock state occupation of \(\ket{f_2}\), and columns from the input \(\ket{f_1}\). In our case, we need to select the columns indexes \((0,3)\) and rows indexes \((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:

\[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 | jnp.ndarray): The initial Fock state. final_fock_state (qutip.Qobj | jnp.ndarray): The final Fock state. unitary_matrix (jnp.ndarray): The unitary matrix that represents the quantum state circuit.

Returns:

float: The transition probability amplitude between the initial and final Fock states.

array_types#
tuple_int_type#
package_array_types#
convert_2d_array_to_string(list_2D: list[list])[source]#

This function is particularly useful to convert digital data when it is represented as a 2D array into a set of strings.

Parameters:

list_2D (list[list]) – A 2D array of binary data.

Returns:

A string of binary data.

Return type:

binary_string (str)

Usage:

list_2D=[[0], [0], [0], [1]] convert_2d_array_to_string(list_2D) >>> “0001”

convert_array_type(array: array_types, output_type: package_array_types)[source]#
absolute_to_threshold(array: array_types, threshold: float = 1e-06, dtype_output: int | float | bool = int, output_array_type: package_array_types = 'jax') package_array_types[source]#

This function converts the computed optical transmission arrays to single bit digital signals. The function takes the absolute value of the array and compares it to a threshold to determine the digital signal.

Parameters:
  • array (array_types) – The optical transmission array of any dimension.

  • dtype_output (int | float | bool, optional) – The output type. Defaults to int.

  • threshold (float, optional) – The threshold to compare the array to. Defaults to 1e-6.

  • output_array_type (array_types, optional) – The output type. Defaults to “jax”.

Returns:

single_parameter_sweep(base_design_configuration: dict, parameter_name: str, parameter_sweep_values: list)[source]#

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.

Parameters:
  • base_design_configuration (dict) – Base design configuration dictionary.

  • parameter_name (str) – Name of parameter to sweep.

  • parameter_sweep_values (list) – List of values to sweep.

Returns:

List of dictionaries that correspond to the parameter sweep.

Return type:

parameter_sweep_design_dictionary_array(list)

multi_parameter_sweep(base_design_configuration: dict, parameter_sweep_dictionary: dict) list[source]#

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,
}
Parameters:
  • base_design_configuration (dict) – Dictionary of the default design configuration.

  • parameter_sweep_dictionary (dict) – Dictionary of the parameter sweep. The keys should be the same as the keys in the base_design_configuration dictionary.

Returns:

List of dictionaries that comprise of all the possible combinations of your parameter sweeps.

Return type:

parameter_sweep_design_dictionary_array(list)

create_setup_py(design_directory: piel.types.piel_path_types, project_name: str | None = None, from_config_json: bool = True) None[source]#

This function creates a setup.py file from the config.json file found in the design directory.

Parameters:

design_directory (piel_path_types) – Design directory PATH or module name.

Returns:

None

create_empty_piel_project(project_name: str, parent_directory: piel.types.piel_path_types) None[source]#

This function creates an empty piel-structure project in the target directory. Structuring your files in this way enables the co-design and use of the tools supported by piel whilst maintaining the design flow ordered, clean and extensible. You can read more about it in the documentation TODO add link.

TODO just make this a cookiecutter. TO BE DEPRECATED whenever I get round to that.

Parameters:
  • project_name (str) – Name of the project.

  • parent_directory (piel_path_types) – Parent directory of the project.

Returns:

None

get_module_folder_type_location(module: types.ModuleType, folder_type: Literal[digital_source, digital_testbench])[source]#

This is an easy helper function that saves a particular file in the corresponding location of a piel project structure.

TODO DOCS

pip_install_local_module(module_path: piel.types.piel_path_types)[source]#

This function installs a local module in editable mode.

Parameters:

module_path (piel_path_types) – Path to the module to be installed.

Returns:

None

read_configuration(design_directory: piel.types.piel_path_types) dict[source]#

This function reads the configuration file found in the design directory.

Parameters:

design_directory (piel_path_types) – Design directory PATH.

Returns:

Configuration dictionary.

Return type:

config_dictionary(dict)

check_cocotb_testbench_exists(design_directory: str | pathlib.Path) bool[source]#

Checks if a cocotb testbench exists in the design directory.

Parameters:

design_directory (str | pathlib.Path) – Design directory.

Returns:

True if cocotb testbench exists.

Return type:

cocotb_testbench_exists(bool)

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)[source]#

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
Parameters:
  • design_directory (str | pathlib.Path) – The directory where the design is located.

  • simulator (Literal["icarus", "verilator"]) – The simulator to use.

  • top_level_language (Literal["verilog", "vhdl"]) – The top level language.

  • top_level_verilog_module (str) – The top level verilog module.

  • test_python_module (str) – The test python module.

  • design_sources_list (list | None, optional) – A list of design sources. Defaults to None.

Returns:

None

delete_simulation_output_files#
run_cocotb_simulation(design_directory: str) subprocess.CompletedProcess[source]#

Equivalent to running the cocotb makefile .. code-block:

make
Parameters:

design_directory (str) – The directory where the design is located.

Returns:

The subprocess.CompletedProcess object.

Return type:

subprocess.CompletedProcess

get_simulation_output_files#
get_simulation_output_files_from_design(design_directory: piel.types.piel_path_types, extension: str = 'csv')[source]#

This function returns a list of all the simulation output files in the design directory.

Parameters:

design_directory (piel_path_types) – The path to the design directory.

Returns:

List of all the simulation output files in the design directory.

Return type:

output_files (list)

read_simulation_data(file_path: piel.types.piel_path_types)[source]#

This function returns a Pandas dataframe that contains all the simulation data outputted from the simulation run.

Parameters:

file_path (piel_path_types) – The path to the simulation data file.

Returns:

The simulation data in a Pandas dataframe.

Return type:

simulation_data (pd.DataFrame)

simple_plot_simulation_data(simulation_data: pandas.DataFrame)[source]#
get_input_ports_index(ports_index: dict, sorting_algorithm: Literal[get_input_ports_index.prefix] = 'prefix', prefix: str = 'in') tuple[source]#

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.

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"))
Parameters:
  • ports_index (dict) – The ports index dictionary.

  • sorting_algorithm (Literal["prefix"], optional) – The sorting algorithm to use. Defaults to “prefix”.

  • prefix (str, optional) – The prefix to use for the sorting algorithm. Defaults to “in”.

Returns:

The ordered input ports index tuple.

Return type:

tuple

get_matched_ports_tuple_index(ports_index: dict, selected_ports_tuple: tuple | None = None, sorting_algorithm: Literal[get_matched_ports_tuple_index.prefix, selected_ports] = 'prefix', prefix: str = 'in')[source]#

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.

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)
Parameters:
  • ports_index (dict) – The ports index dictionary.

  • selected_ports_tuple (tuple, optional) – The selected ports tuple. Defaults to None.

  • sorting_algorithm (Literal["prefix"], optional) – The sorting algorithm to use. Defaults to “prefix”.

  • prefix (str, optional) – The prefix to use for the sorting algorithm. Defaults to “in”.

Returns:

The ordered input ports index tuple. matched_ports_name_tuple_order(tuple): The ordered input ports name tuple.

Return type:

matches_ports_index_tuple_order(tuple)

straight_heater_metal_simple(length: float = 320.0, length_straight_input: float = 15.0, heater_width: float = 2.5, cross_section_heater: gdsfactory.typings.CrossSectionSpec = 'heater_metal', cross_section_waveguide_heater: gdsfactory.typings.CrossSectionSpec = 'strip_heater_metal', via_stack: gdsfactory.typings.ComponentSpec | None = 'via_stack_heater_mtop', port_orientation1: int | None = None, port_orientation2: int | None = None, heater_taper_length: float | None = 5.0, ohms_per_square: float | None = None, **kwargs) gdsfactory.component.Component[source]#

Returns a thermal phase shifter that has properly fixed electrical connectivity to extract a suitable electrical netlist and models. dimensions from https://doi.org/10.1364/OE.27.010456 :param length: of the waveguide. :param length_undercut_spacing: from undercut regions. :param length_undercut: length of each undercut section. :param length_straight_input: from input port to where trenches start. :param heater_width: in um. :param cross_section_heater: for heated sections. heater metal only. :param cross_section_waveguide_heater: for heated sections. :param cross_section_heater_undercut: for heated sections with undercut. :param with_undercut: isolation trenches for higher efficiency. :param via_stack: via stack. :param port_orientation1: left via stack port orientation. :param port_orientation2: right via stack port orientation. :param heater_taper_length: minimizes current concentrations from heater to via_stack. :param ohms_per_square: to calculate resistance. :param cross_section: for waveguide ports. :param kwargs: cross_section common settings.

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)[source]#

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/”<latest>”/. If a `design_directory is provided then this will always take precedence even with a v1 flag.

Parameters:
  • v1 (bool) – If True, it will migrate from v1 to v2.

  • design_name_v1 (str) – Design name of the v1 design that can be found within $OPENLANE_ROOT/”<latest>”/designs.

  • design_directory (str) – Design directory PATH. Optional path for v2-based designs.

  • root_directory_v1 (str) – Root directory of OpenLane v1. If set to None it will return $OPENLANE_ROOT/”<latest>”

Returns:

None

extract_datetime_from_path(run_path: pathlib.Path) str[source]#

Extracts the datetime from a given run_path and returns it as a string.

find_all_design_runs(design_directory: piel.types.piel_path_types, run_name: str | None = None) list[pathlib.Path][source]#

For a given design_directory, the openlane output can be found in the runs subdirectory. This function sorts the runs according to the default notations between both openlane and openlane2 run formats.

If a run_name is specified, then the function will return the exact run if it exists. Otherwise, it will return the latest run

Parameters:
  • design_directory (piel_path_types) – The path to the design directory

  • run_name (str, optional) – The name of the run to return. Defaults to None.

  • version (Literal["v1", "v2"], optional) – The version of OpenLane to use. Defaults to None.

Raises:

ValueError – If the run_name is specified but not found in the design_directory

Returns:

A list of pathlib.Path objects corresponding to the runs

Return type:

list[pathlib.Path]

find_latest_design_run(design_directory: piel.types.piel_path_types, run_name: str | None = None, version: Literal[v1, v2] | None = None)[source]#

For a given design_directory, the openlane output can be found in the runs subdirectory. This function sorts the runs according to the default notations between both openlane and openlane2 run formats.

If a run_name is specified, then the function will return the exact run if it exists. Otherwise, it will return the latest run.

Parameters:
  • design_directory (piel_path_types) – The path to the design directory

  • run_name (str, optional) – The name of the run to return. Defaults to None.

  • version (Literal["v1", "v2"], optional) – The version of the run to return. Defaults to None.

Raises:

ValueError – If the run_name is specified but not found in the design_directory

Returns:

A tuple of the latest run path and the version

Return type:

(pathlib.Path, str)

get_gds_path_from_design_run(design_directory: piel.types.piel_path_types, run_directory: piel.types.piel_path_types | None = None) pathlib.Path[source]#

Returns the path to the final GDS generated by OpenLane.

Parameters:
  • design_directory (piel_path_types) – The path to the design directory

  • run_directory (piel_path_types, optional) – The path to the run directory. Defaults to None. Otherwise gets the latest run.

Returns:

The path to the final GDS

Return type:

pathlib.Path

get_design_run_version(run_directory: piel.types.piel_path_types) Literal[v1, v2][source]#

Returns the version of the design run.

sort_design_runs(path_list: list[pathlib.Path]) dict[str, list[pathlib.Path]][source]#

For a given design_directory, the openlane output can be found in the runs subdirectory. This function sorts the runs according to the default notations between both openlane and openlane2 run formats.

Parameters:

path_list (list[pathlib.Path]) – A list of pathlib.Path objects corresponding to the runs

Returns:

A dictionary of sorted runs

Return type:

dict[str, list[pathlib.Path]]

check_config_json_exists_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) bool[source]#

Checks if a design has a config.json file.

Parameters:

design_name (str) – Name of the design.

Returns:

True if config.json exists.

Return type:

config_json_exists(bool)

check_design_exists_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) bool[source]#

Checks if a design exists in the OpenLane v1 design folder.

Lists all designs inside the Openlane V1 design root.

Parameters:

design_name (str) – Name of the design.

Returns:

True if design exists.

Return type:

design_exists(bool)

configure_and_run_design_openlane_v1(design_name: str, configuration: dict | None = None, root_directory: str | pathlib.Path | None = None) None[source]#

Configures and runs an OpenLane v1 design.

This function does the following: 1. Check that the design_directory provided is under $OPENLANE_ROOT/<latestversion>/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.

Parameters:
  • design_name (str) – Name of the design.

  • configuration (dict | None) – Configuration dictionary.

  • root_directory (str | pathlib.Path) – Design directory.

Returns:

None

configure_parametric_designs_openlane_v1(design_name: str, parameter_sweep_dictionary: dict, add_id: bool = True) list[source]#

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.

Parameters:
  • add_id (bool) – Add an ID to the design name. Defaults to True.

  • parameter_sweep_dictionary (dict) – Dictionary of parameters to sweep.

  • source_design_directory (str | pathlib.Path) – Source design directory.

Returns:

List of configurations to sweep.

Return type:

configuration_sweep(list)

configure_flow_script_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) None[source]#

Configures the OpenLane v1 flow script after checking that the design directory exists.

Parameters:

design_directory (str | pathlib.Path | None) – Design directory. Defaults to latest OpenLane root.

Returns:

None

create_parametric_designs_openlane_v1(design_name: str, parameter_sweep_dictionary: dict, target_directory: str | pathlib.Path | None = None) None[source]#

Takes a OpenLane v1 source directory and creates a parametric combination of these designs.

Parameters:
  • design_name (str) – Name of the design.

  • parameter_sweep_dictionary (dict) – Dictionary of parameters to sweep.

  • target_directory (str | pathlib.Path | None) – Optional target directory.

Returns:

None

get_design_directory_from_root_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) pathlib.Path[source]#

Gets the design directory from the root directory.

Parameters:
  • design_name (str) – Name of the design.

  • root_directory (str | pathlib.Path) – Design directory.

Returns:

Design directory.

Return type:

design_directory(pathlib.Path)

get_latest_version_root_openlane_v1() pathlib.Path[source]#

Gets the latest version root of OpenLane v1.

read_configuration_openlane_v1(design_name: str, root_directory: str | pathlib.Path | None = None) dict[source]#

Reads a config.json from a design directory.

Parameters:
  • design_name (str) – Design name.

  • root_directory (str | pathlib.Path) – Design directory.

Returns:

Configuration dictionary.

Return type:

configuration(dict)

write_configuration_openlane_v1(configuration: dict, design_directory: piel.types.piel_path_types) None[source]#

Writes a config.json onto a design_directory

Parameters:
  • configuration (dict) – OpenLane configuration dictionary.

  • design_directory (str) – Design directory PATH.

Returns:

None

filter_timing_sta_files(file_list)[source]#

Filter the timing sta files from the list of files

Parameters:

file_list (list) – List containing the file paths

Returns:

List containing the timing sta files

Return type:

timing_sta_files (list)

filter_power_sta_files(file_list)[source]#

Filter the power sta files from the list of files

Parameters:

file_list (list) – List containing the file paths

Returns:

List containing the power sta files

Return type:

power_sta_files (list)

get_all_timing_sta_files(run_directory)[source]#

This function aims to list and perform analysis on all the relevant files in a particular run between all the corners.

Parameters:

run_directory (str, optional) – The run directory to perform the analysis on. Defaults to None.

Returns:

List of all the .rpt files in the run directory.

Return type:

timing_sta_files_list (list)

get_all_power_sta_files(run_directory)[source]#

This function aims to list and perform analysis on all the relevant files in a particular run between all the corners.

Parameters:

run_directory (str, optional) – The run directory to perform the analysis on. Defaults to None.

Returns:

List of all the .rpt files in the run directory.

Return type:

power_sta_files_list (list)

calculate_max_frame_amount(file_lines_data: pandas.DataFrame)[source]#

Calculate the maximum frame amount based on the frame IDs in the DataFrame

Parameters:

file_lines_data (pd.DataFrame) – Dataframe containing the file lines

Returns:

Maximum number of frames in the file

Return type:

maximum_frame_amount (int)

calculate_propagation_delay_from_file(file_path: str | pathlib.Path)[source]#

Calculate the propagation delay for each frame in the file

Parameters:

file_path (str | pathlib.Path) – Path to the file

Returns:

Dictionary containing the propagation delay

Return type:

propagation_delay (dict)

calculate_propagation_delay_from_timing_data(net_name_in: str, net_name_out: str, timing_data: pandas.DataFrame)[source]#

Calculate the propagation delay between two nets

Parameters:
  • net_name_in (str) – Name of the input net

  • net_name_out (str) – Name of the output net

  • timing_data (pd.DataFrame) – Dataframe containing the timing data

Returns:

Dataframe containing the propagation delay

Return type:

propagation_delay_dataframe (pd.DataFrame)

configure_timing_data_rows(file_lines_data: pandas.DataFrame)[source]#

Identify the timing data lines for each frame and creates a metadata dictionary for frames.

Parameters:

file_lines_data (pd.DataFrame) – Dataframe containing the file lines

Returns:

Dictionary containing the frame metadata

Return type:

frame_meta_data (dict)

configure_frame_id(file_lines_data: pandas.DataFrame)[source]#

Identify the frame delimiters and assign frame ID to each line in the file

Parameters:

file_lines_data (pd.DataFrame) – Dataframe containing the file lines

Returns:

Dataframe containing the file lines

Return type:

file_lines_data (pd.DataFrame)

filter_timing_data_by_net_name_and_type(timing_data: pandas.DataFrame, net_name: str, net_type: str)[source]#

Filter the timing data by net name and type

Parameters:
  • timing_data (pd.DataFrame) – DataFrame containing the timing data

  • net_name (str) – Net name to be filtered

  • net_type (str) – Net type to be filtered

Returns:

DataFrame containing the timing data

Return type:

timing_data (pd.DataFrame)

get_frame_meta_data(file_lines_data)[source]#

Get the frame metadata

Parameters:

file_lines_data (pd.DataFrame) – DataFrame containing the file lines

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

Return type:

start_point_name (pd.DataFrame)

get_frame_lines_data(file_path: str | pathlib.Path)[source]#

Calculate the timing data for each frame in the file

Parameters:

file_path (str | pathlib.Path) – Path to the file

Returns:

DataFrame containing the file lines

Return type:

file_lines_data (pd.DataFrame)

get_frame_timing_data(file: str | pathlib.Path, frame_meta_data: dict, frame_id: int = 0)[source]#

Extract the timing data from the file

Parameters:
  • file (str | pathlib.Path) – Address of the file

  • frame_meta_data (dict) – Dictionary containing the frame metadata

  • frame_id (int) – Frame ID to be read

Returns:

DataFrame containing the timing data

Return type:

timing_data (pd.DataFrame)

get_all_timing_data_from_file(file_path: str | pathlib.Path)[source]#

Calculate the timing data for each frame in the file

Parameters:

file_path (str | pathlib.Path) – Path to the file

Returns:

Dictionary containing the timing data for each frame

Return type:

frame_timing_data (dict)

read_sta_rpt_fwf_file(file: str | pathlib.Path, frame_meta_data: dict, frame_id: int = 0)[source]#

Read the fixed width file and return a DataFrame

Parameters:
  • file (str | pathlib.Path) – Address of the file

  • frame_meta_data (dict) – Dictionary containing the frame metadata

  • frame_id (int) – Frame ID to be read

Returns:

DataFrame containing the file data

Return type:

file_data (pd.DataFrame)

contains_in_lines(file_lines_data: pandas.DataFrame, keyword: str)[source]#

Check if the keyword is contained in the file lines

Parameters:
  • file_lines_data (pd.DataFrame) – Dataframe containing the file lines

  • keyword (str) – Keyword to search for

Returns:

Dataframe containing the file lines

Return type:

file_lines_data (pd.DataFrame)

create_file_lines_dataframe(file_lines_raw)[source]#

Create a DataFrame from the raw lines of a file

Parameters:

file_lines_raw (list) – list containing the file lines

Returns:

Dataframe containing the file lines

Return type:

file_lines_data (pd.DataFrame)

get_file_line_by_keyword(file_lines_data: pandas.DataFrame, keyword: str, regex: str)[source]#

Extract the data from the file lines using the given keyword and regex

Parameters:
  • file_lines_data (pd.DataFrame) – Dataframe containing the file lines

  • keyword (str) – Keyword to search for

  • regex (str) – Regex to extract the data

Returns:

Dataframe containing the extracted values

Return type:

extracted_values (pd.DataFrame)

read_file_lines(file_path: str | pathlib.Path)[source]#

Extract lines from the file

Parameters:

file_path (str | pathlib.Path) – Path to the file

Returns:

list containing the file lines

Return type:

file_lines_raw (list)

get_all_designs_metrics_openlane_v2(output_directory: piel.types.piel_path_types, target_prefix: str)[source]#

Returns a dictionary of all the metrics for all the designs in the output directory.

Usage:

```python from piel.tools.openlane import get_all_designs_metrics_v2

metrics = get_all_designs_metrics_v2(

output_directory=”output”, target_prefix=”design”,

Parameters:
  • output_directory (piel_path_types) – The path to the output directory.

  • target_prefix (str) – The prefix of the designs to get the metrics for.

Returns:

A dictionary of all the metrics for all the designs in the output directory.

Return type:

dict

read_metrics_openlane_v2(design_directory: piel.types.piel_path_types) dict[source]#

Read design metrics from OpenLane v2 run files.

Parameters:

design_directory (piel_path_types) – Design directory PATH.

Returns:

Metrics dictionary.

Return type:

dict

run_openlane_flow(configuration: dict | None = None, design_directory: piel.types.piel_path_types = '.', parallel_asynchronous_run: bool = False, only_generate_flow_setup: bool = False)[source]#

Runs the OpenLane v2 flow.

Parameters:
  • configuration (dict) – OpenLane configuration dictionary. If none is present it will default to the config.json file on the design_directory.

  • design_directory (piel_path_types) – Design directory PATH.

  • parallel_asynchronous_run (bool) – Run the flow in parallel.

  • only_generate_flow_setup (bool) – Only generate the flow setup.

Returns:

configure_ngspice_simulation(run_directory: piel.types.piel_path_types = '.')[source]#

This function configures the NGSPICE simulation for the circuit and returns a simulation class.

Parameters:

run_directory (piel_path_types) – Directory where the simulation will be run

Returns:

Configured NGSPICE simulation options

Return type:

simulation_options

configure_operating_point_simulation(testbench: hdl21.Module, **kwargs)[source]#

This function configures the DC operating point simulation for the circuit and returns a simulation class.

Parameters:
  • testbench (Module) – HDL21 testbench

  • **kwargs – Additional arguments to be passed to the operating point simulation such as name.

Returns:

HDL21 simulation class

Return type:

Simulation

configure_transient_simulation(testbench: hdl21.Module, stop_time_s: float, step_time_s: float, **kwargs)[source]#

This function configures the transient simulation for the circuit and returns a simulation class.

Parameters:
  • testbench (Module) – HDL21 testbench

  • stop_time_s (float) – Stop time of the simulation in seconds

  • step_time_s (float) – Step time of the simulation in seconds

  • **kwargs – Additional arguments to be passed to the transient simulation

Returns:

HDL21 simulation class

Return type:

Simulation

run_simulation(simulation: hdl21.sim.Sim, simulator_name: Literal[ngspice] = 'ngspice', simulation_options: vlsirtools.spice.SimOptions | None = None, to_csv: bool = True)[source]#

This function runs the transient simulation for the circuit and returns the results.

Parameters:
  • simulation (h.sim.Sim) – HDL21 simulation class

  • simulator_name (Literal["ngspice"]) – Name of the simulator

  • simulation_options (Optional[vsp.SimOptions]) – Simulation options

  • to_csv (bool) – Whether to save the results to a csv file

Returns:

Simulation results

Return type:

results

convert_numeric_to_prefix(value: float)[source]#

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.

address_value_dictionary_to_function_parameter_dictionary(address_value_dictionary: dict, parameter_key: str)[source]#

This function converts an address of an instance with particular parameter values in the form:

{(‘component_lattice_gener_fb8c4da8’, ‘mzi_1’, ‘sxt’): 0, (‘component_lattice_gener_fb8c4da8’, ‘mzi_5’, ‘sxt’): 0}

to

{‘mzi_1’: {‘sxt’: {parameter_key: 0}}, (‘mzi_5’, {‘sxt’: {parameter_key: 0}}}

compose_recursive_instance_location(recursive_netlist: dict, top_level_instance_name: str, required_models: list, target_component_prefix: str, models: dict)[source]#

This function returns the recursive location of any matching target_component_prefix instances within the recursive_netlist. A function that returns the mapping of the matched_component in the corresponding netlist at any particular level of recursion. This function iterates over a particular level of recursion of a netlist. It returns a list of the missing required components, and updates a dictionary of models that contains a particular matching component. It returns the corresponding list of instances of a particular component at that level of recursion, so that it can be appended upon in order to construct the location of the corresponding matching elements.

If required_models is an empty list, it means no recursion is required and the function is complete. If a required_model_i in required_models matches target_component_prefix, then no more recursion is required down the component function.

The recursive_netlist should contain all the missing composed models that are not provided in the main models dictionary. If not, then we need to require the user to input the missing model that cannot be extracted from the composed netlist.

We know when a model is composed, and when it is already provided at every level of recursion based on the models dictionary that gets updated at each level of recursion with the corresponding models of that level, and the required_models down itself.

However, a main question appears on how to do the recursion. There needs to be a flag that determines that the recursion is complete. However, this is only valid for every particular component in the required_models list. Every component might have missing component. This means that this recursion begins component by component, updating the required_models list until all of them have been composed from the recursion or it is determined that is it missing fully.

It would be ideal to access the particular component that needs to be implemented.

Returns a tuple of model_composition_mapping, instance_composition_mapping, target_component_mapping in the form of

({‘mzi_214beef3’: [‘straight_heater_metal_s_ad3c1693’]},
{‘mzi_214beef3’: [‘mzi_1’, ‘mzi_5’],

‘mzi_d46c281f’: [‘mzi_2’, ‘mzi_3’, ‘mzi_4’]})

get_component_instances(recursive_netlist: dict, top_level_prefix: str, component_name_prefix: str)[source]#

Returns a dictionary of all instances of a given component in a recursive netlist.

Parameters:
  • recursive_netlist – The recursive netlist to search.

  • top_level_prefix – The prefix of the top level instance.

  • component_name_prefix – The name of the component to search for.

Returns:

A dictionary of all instances of the given component.

get_netlist_instances_by_prefix(recursive_netlist: dict, instance_prefix: str) str[source]#

Returns a list of all instances with a given prefix in a recursive netlist.

Parameters:
  • recursive_netlist – The recursive netlist to search.

  • instance_prefix – The prefix to search for.

Returns:

A list of all instances with the given prefix.

get_matched_model_recursive_netlist_instances(recursive_netlist: dict, top_level_instance_prefix: str, target_component_prefix: str, models: dict | None = None) list[tuple][source]#

This function returns an active component list with a tuple mapping of the location of the active component within the recursive netlist and corresponding model. It will recursively look within a netlist to locate what models use a particular component model. At each stage of recursion, it will compose a list of the elements that implement this matching model in order to relate the model to the instance, and hence the netlist address of the component that needs to be updated in order to functionally implement the model.

It takes in as a set of parameters the recursive_netlist generated by a gdsfactory netlist implementation.

Returns a list of tuples, that correspond to the phases applied with the corresponding component paths at multiple levels of recursion. eg. [(“component_lattice_gener_fb8c4da8”, “mzi_1”, “sxt”), (“component_lattice_gener_fb8c4da8”, “mzi_5”, “sxt”)] and these are our keys to our sax circuit decomposition.

get_sdense_ports_index(input_ports_order: tuple, all_ports_index: dict) dict[source]#

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.

# 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}
Parameters:
  • input_ports_order (tuple) – The ports order tuple. Can be a tuple of tuples that contain the index and port name.

  • all_ports_index (dict) – The ports index dictionary.

Returns:

The ordered input ports index tuple.

Return type:

tuple

sax_to_s_parameters_standard_matrix(sax_input: sax.SType, input_ports_order: tuple | None = None) tuple[source]#

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

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 \(S_{(output,i),(input,i)}\) would be:

\[\begin{split}S = \begin{bmatrix} S_{00} & S_{10} \\ S_{01} & S_{11} \\ \end{bmatrix} = \begin{bmatrix} \tau & j \kappa \\ j \kappa & \tau \\ \end{bmatrix}\end{split}\]

Note that the standard S-parameter and hence unitary representation is in the form of:

\[\begin{split}S = \begin{bmatrix} S_{00} & S_{01} \\ S_{10} & S_{11} \\ \end{bmatrix}\end{split}\]
\[\begin{split}\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}\end{split}\]

TODO check with Floris, does this mean we need to transpose the matrix?

Parameters:
  • sax_input (sax.SType) – The sax S-parameter dictionary.

  • input_ports_order (tuple) – The ports order tuple containing the names and order of the input ports.

Returns:

The S-parameter matrix and the input ports index tuple in the standard S-parameter notation.

Return type:

tuple

snet#
all_fock_states_from_photon_number(mode_amount: int, photon_amount: int = 1, output_type: Literal[qutip, jax] = 'qutip') list[source]#

For a specific amount of modes, we can generate all the possible Fock states for whatever amount of input photons we desire. This returns a list of all corresponding Fock states.

Parameters:
  • mode_amount (int) – The amount of modes in the system.

  • photon_amount (int, optional) – The amount of photons in the system. Defaults to 1.

  • output_type (str, optional) – The type of output. Defaults to “qutip”.

Returns:

A list of all the Fock states.

Return type:

list

convert_qobj_to_jax(qobj: qutip.Qobj) jax.numpy.ndarray[source]#
convert_output_type#
fock_state_nonzero_indexes(fock_state: qutip.Qobj | jax.numpy.ndarray) tuple[int][source]#

This function returns the indexes of the nonzero elements of a Fock state.

Parameters:

fock_state (qutip.Qobj) – A QuTip QObj representation of the Fock state.

Returns:

The indexes of the nonzero elements of the Fock state.

Return type:

tuple

fock_state_to_photon_number_factorial(fock_state: qutip.Qobj | jax.numpy.ndarray) float[source]#

This function converts a Fock state defined as:

\[\]

ewcommand{ket}[1]{left|{#1} ight angle}

ket{f_1} = ket{j_1, j_2, … j_N}$

and returns:

\[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.

fock_states_at_mode_index(mode_amount: int, target_mode_index: int, maximum_photon_amount: int | None = 1, output_type: Literal[qutip, jax] = 'qutip') list[source]#

This function returns a list of valid Fock states that fulfill a condition of having a maximum photon number at a specific mode index.

Parameters:
  • mode_amount (int) – The amount of modes in the system.

  • target_mode_index (int) – The mode index to check the photon number at.

  • maximum_photon_amount (int, optional) – The amount of photons in the system. Defaults to 1.

  • output_type (str, optional) – The type of output. Defaults to “qutip”.

Returns:

A list of all the Fock states.

Return type:

list

fock_states_only_individual_modes(mode_amount: int, maximum_photon_amount: int | None = 1, output_type: Literal[qutip, jax, numpy, list, tuple] = 'qutip') list[source]#

This function returns a list of valid Fock states where each state has a maximum photon number, but only in one mode.

Parameters:
  • mode_amount (int) – The amount of modes in the system.

  • maximum_photon_amount (int) – The maximum amount of photons in a single mode.

  • output_type (str, optional) – The type of output. Defaults to “qutip”.

Returns:

A list of all the valid Fock states.

Return type:

list

standard_s_parameters_to_qutip_qobj#
verify_matrix_is_unitary(matrix: jax.numpy.ndarray) bool[source]#

Verify that the matrix is unitary.

Parameters:

matrix (jnp.ndarray) – The matrix to verify.

Returns:

True if the matrix is unitary, False otherwise.

Return type:

bool

subunitary_selection_on_range(unitary_matrix: jax.numpy.ndarray, stop_index: tuple, start_index: tuple | None = (0, 0))[source]#

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.

subunitary_selection_on_index(unitary_matrix: jax.numpy.ndarray, rows_index: jax.numpy.ndarray | tuple, columns_index: jax.numpy.ndarray | tuple)[source]#

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.

__author__ = 'Dario Quintero'#
__email__ = 'darioaquintero@gmail.com'#
__version__ = '0.0.56'#