"""
These set of functions aim to provide functionality to automate interacting with OpenLanes v1 design into Python environment, whilst `OpenLanes2` is under development.
"""
import os
import pathlib
import json
from piel.utils.parametric import multi_parameter_sweep
from piel.file_system import (
copy_source_folder,
permit_script_execution,
read_json,
return_path,
run_script,
write_file,
)
from ...types import PathTypes
__all__ = [
"check_config_json_exists_openlane_v1",
"check_design_exists_openlane_v1",
"configure_and_run_design_openlane_v1",
"configure_parametric_designs_openlane_v1",
"configure_flow_script_openlane_v1",
"create_parametric_designs_openlane_v1",
"get_design_directory_from_root_openlane_v1",
"get_latest_version_root_openlane_v1",
"read_configuration_openlane_v1",
"write_configuration_openlane_v1",
]
[docs]
def 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.
Args:
design_name(str): Name of the design.
Returns:
config_json_exists(bool): True if `config.json` exists.
"""
config_json_exists = False
design_directory = get_design_directory_from_root_openlane_v1(
design_name=design_name, root_directory=root_directory
)
if (design_directory / "config.json").exists():
config_json_exists = True
return config_json_exists
[docs]
def 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.
Args:
design_name(str): Name of the design.
Returns:
design_exists(bool): True if design exists.
"""
if root_directory is None:
root_directory = get_latest_version_root_openlane_v1()
design_exists = False
openlane_v1_design_directory = root_directory / "designs"
all_openlane_v1_designs = list(openlane_v1_design_directory.iterdir())
if (openlane_v1_design_directory / design_name) in all_openlane_v1_designs:
design_exists = True
return design_exists
[docs]
def 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.
Args:
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
"""
source_design_directory = get_design_directory_from_root_openlane_v1(
design_name=design_name
)
source_design_name = design_name
if target_directory is None:
target_directory = get_latest_version_root_openlane_v1() / "designs"
parameter_sweep_configuration_list = configure_parametric_designs_openlane_v1(
add_id=True,
design_name=design_name,
parameter_sweep_dictionary=parameter_sweep_dictionary,
)
for configuration_i in parameter_sweep_configuration_list:
# Create a target directory with the name of the design and the configuration ID
target_directory_i = (
target_directory / source_design_name + "_" + str(configuration_i["id"])
)
# Copy the source design directory to the target directory
copy_source_folder(
source_directory=source_design_directory,
target_directory=target_directory_i,
)
[docs]
def get_latest_version_root_openlane_v1() -> pathlib.Path:
"""
Gets the latest version root of OpenLane v1.
"""
openlane_tool_directory = pathlib.Path(os.environ["OPENLANE_ROOT"])
latest_openlane_version = list(openlane_tool_directory.iterdir())
openlane_v1_design_directory = openlane_tool_directory / latest_openlane_version[-1]
return openlane_v1_design_directory
[docs]
def 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.
Args:
design_name(str): Name of the design.
root_directory(str | pathlib.Path): Design directory.
Returns:
design_directory(pathlib.Path): Design directory.
"""
if root_directory is None:
root_directory = get_latest_version_root_openlane_v1()
root_directory = return_path(root_directory)
design_exists = check_design_exists_openlane_v1(design_name)
if design_exists:
pass
else:
raise ValueError(
"Design: "
+ design_name
+ " is not found in "
+ str(root_directory / "designs")
)
design_directory = root_directory / "designs" / design_name
return design_directory
[docs]
def read_configuration_openlane_v1(
design_name: str,
root_directory: str | pathlib.Path | None = None,
) -> dict:
"""
Reads a `config.json` from a design directory.
Args:
design_name(str): Design name.
root_directory(str | pathlib.Path): Design directory.
Returns:
configuration(dict): Configuration dictionary.
"""
config_json_exists = check_config_json_exists_openlane_v1(design_name)
if config_json_exists:
design_directory = get_design_directory_from_root_openlane_v1(
design_name=design_name, root_directory=root_directory
)
configuration = read_json(design_directory / "config.json")
return configuration
else:
raise ValueError(
"Configuration file for design: "
+ design_name
+ " is not found in "
+ str(root_directory / "designs" / design_name)
)
[docs]
def write_configuration_openlane_v1(
configuration: dict,
design_directory: PathTypes,
) -> None:
"""
Writes a `config.json` onto a `design_directory`
Args:
configuration(dict): OpenLane configuration dictionary.
design_directory(str): Design directory PATH.
Returns:
None
"""
design_directory = return_path(design_directory)
with open(str((design_directory / "config.json").resolve()), "w") as write_file:
json.dump(configuration, write_file, indent=4)