Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ bazel-*
requirements_lock.txt

chipcompiler/tools/ecc_dreamplace/dreamplace
chipcompiler/tools/ecc_sizer/bin/

.humanize/
humanize-*
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@
[submodule "chipcompiler/thirdparty/ecc-dreamplace"]
path = chipcompiler/thirdparty/ecc-dreamplace
url = https://github.com/openecos-projects/ecc-dreamplace.git
[submodule "chipcompiler/thirdparty/ecc-sizer"]
path = chipcompiler/thirdparty/ecc-sizer
url = https://github.com/openecos-projects/ecc-sizer.git
7 changes: 7 additions & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ local_source_repo(
path = "chipcompiler/thirdparty/ecc-tools",
)

# ECC-Sizer source tree, imported without BUILD/WORKSPACE files so the CMake
# build can traverse its OpenROAD submodule when initialized.
local_source_repo(
name = "ecc_sizer_src",
path = "chipcompiler/thirdparty/ecc-sizer",
)

bazel_dep(name = "ecc-dreamplace", version = "0.1.0-alpha.4")
local_path_override(
module_name = "ecc-dreamplace",
Expand Down
324 changes: 162 additions & 162 deletions MODULE.bazel.lock

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions bazel/scripts/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ sh_binary(
srcs = ["prepare-dev.sh"],
data = [
"install-dreamplace.sh",
"install-sizer.sh",
"//chipcompiler/thirdparty:ecc_bundle",
"//chipcompiler/thirdparty:ecc_sizer_cmake",
"@ecc-dreamplace//:dreamplace_cmake",
],
args = [
"$(rlocationpath //chipcompiler/thirdparty:ecc_bundle)",
"$(locations @ecc-dreamplace//:dreamplace_cmake)",
"$(locations //chipcompiler/thirdparty:ecc_sizer_cmake)",
],
)

Expand Down Expand Up @@ -48,3 +51,20 @@ sh_binary(
srcs = ["install-dreamplace.sh"],
args = ["--clean"],
)

sh_binary(
name = "install_sizer",
srcs = ["install-sizer.sh"],
data = [
"//chipcompiler/thirdparty:ecc_sizer_cmake",
],
args = [
"$(locations //chipcompiler/thirdparty:ecc_sizer_cmake)",
],
)

sh_binary(
name = "clean_sizer",
srcs = ["install-sizer.sh"],
args = ["--clean"],
)
57 changes: 57 additions & 0 deletions bazel/scripts/install-sizer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/env bash
# Install ECC-Sizer Bazel build artifacts into the source tree for dev use.
# Usage: bazel run //bazel/scripts:install_sizer
# bazel run //bazel/scripts:install_sizer -- --clean
set -euo pipefail

WS="${BUILD_WORKSPACE_DIRECTORY:?Must run via: bazel run //bazel/scripts:install_sizer}"
SIZER_RUNTIME_DIR="${WS}/chipcompiler/tools/ecc_sizer/bin"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is sizer added to chipcompiler/tools/ecc_sizer/bin as an executable file? I think injecting the executable file path into get_sizer_command is a better way to handle it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Due to the need to distribute ecc cli, it may be necessary to consider building sizer as an independent python wheel or ecc monorepo.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CC @Anillc

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be better to build outside the tree and provide the executable by PATH like yosys.

MANIFEST="${SIZER_RUNTIME_DIR}/.install_manifest.txt"

if [[ "${1:-}" == "--clean" ]]; then
if [[ ! -f "${MANIFEST}" ]]; then
echo "Nothing to clean (no install manifest found)."
exit 0
fi
echo "Cleaning installed ECC-Sizer artifacts..."
while IFS= read -r file; do
rm -f "${SIZER_RUNTIME_DIR}/${file}"
echo " Removed: chipcompiler/tools/ecc_sizer/bin/${file}"
done < "${MANIFEST}"
rm -f "${MANIFEST}"
rmdir "${SIZER_RUNTIME_DIR}" 2>/dev/null || true
echo "Done."
exit 0
fi

RF="${RUNFILES_DIR:-${BASH_SOURCE[0]}.runfiles}"
SIZER_BIN=""
for arg in "$@"; do
for candidate_root in "$arg" "${RF}/_main/${arg}" "${RF}/${arg}"; do
if [[ -f "${candidate_root}" && "$(basename "${candidate_root}")" == "Sizer" ]]; then
SIZER_BIN="${candidate_root}"
break 2
fi
if [[ -d "${candidate_root}" ]]; then
found="$(find "${candidate_root}" -type f -name Sizer -perm /111 -print -quit)"
if [[ -n "${found}" ]]; then
SIZER_BIN="${found}"
break 2
fi
fi
done
done

if [[ -z "${SIZER_BIN}" ]]; then
echo "ERROR: Could not locate Sizer executable in args: $*" >&2
exit 1
fi

echo "Bazel output: ${SIZER_BIN}"
echo "Installing to: ${SIZER_RUNTIME_DIR}/"

mkdir -p "${SIZER_RUNTIME_DIR}"
cp -f --no-preserve=ownership "${SIZER_BIN}" "${SIZER_RUNTIME_DIR}/Sizer"
chmod +x "${SIZER_RUNTIME_DIR}/Sizer"
echo "Sizer" > "${MANIFEST}"
echo "Done. Installed chipcompiler/tools/ecc_sizer/bin/Sizer."
6 changes: 6 additions & 0 deletions bazel/scripts/prepare-dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,18 @@ if ! RUNFILES_DIR="${RF}" "${RF}/_main/bazel/scripts/install-dreamplace.sh" "$@"
echo -e "${YELLOW} You can retry with: bazel run //bazel/scripts:install_dreamplace${RESET}"
fi

if ! RUNFILES_DIR="${RF}" "${RF}/_main/bazel/scripts/install-sizer.sh" "$@"; then
echo -e "${YELLOW}WARNING: ECC-Sizer install failed. Sizer timing optimization will not be available.${RESET}"
echo -e "${YELLOW} Ensure chipcompiler/thirdparty/ecc-sizer submodules are initialized, then retry with: bazel run //bazel/scripts:install_sizer${RESET}"
fi

echo ""
echo -e "${GREEN}Dev environment is ready.${RESET}"
echo -e "${CYAN}Run 'source .venv/bin/activate' to activate the venv.${RESET}"
echo ""
echo "Next steps:"
echo " bazel build //:raw_wheel Build Python wheel"
echo " bazel run //:build_wheel Build distributable wheel + smoke test"
echo " bazel run //bazel/scripts:install_sizer Build/install ECC-Sizer runtime"
echo " uv run pytest test/ Run tests"
echo " uv run chipcompiler --reload Start API server (dev mode, port 8765)"
4 changes: 4 additions & 0 deletions chipcompiler/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ filegroup(
["**/*.py"],
exclude = [
"thirdparty/ecc-tools/**",
"thirdparty/ecc-sizer/**",
],
),
)
Expand All @@ -27,6 +28,7 @@ filegroup(
],
exclude = [
"thirdparty/ecc-tools/**",
"thirdparty/ecc-sizer/**",
],
),
)
Expand All @@ -44,6 +46,7 @@ py_library(
],
exclude = [
"thirdparty/ecc-tools/**",
"thirdparty/ecc-sizer/**",
],
),
data = [":chipcompiler_runtime_data"],
Expand All @@ -68,6 +71,7 @@ py_library(
# unnecessary invalidation of this shared core library.
"cli/**/*.py",
"thirdparty/ecc-tools/**",
"thirdparty/ecc-sizer/**",
],
),
data = [":chipcompiler_runtime_data"],
Expand Down
1 change: 1 addition & 0 deletions chipcompiler/cli/workspace/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ def _load_tool_builder(tool: str):
module_alias = {
"klayout": "klayout_tool",
"dreamplace": "ecc_dreamplace",
"sizer": "ecc_sizer",
}
module_name = module_alias.get(tool, tool)
return importlib.import_module(f"chipcompiler.tools.{module_name}.builder")
Expand Down
9 changes: 9 additions & 0 deletions chipcompiler/engine/flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,15 @@ def check_step_result(self,
if not os.path.exists(spef):
break
success = True
case (
StepEnum.TIMING_OPT.value
| StepEnum.TIMING_OPT_DRV.value
| StepEnum.TIMING_OPT_HOLD.value
| StepEnum.TIMING_OPT_SETUP.value
):
if os.path.exists(workspace_step.output.get("def", "")) and \
os.path.exists(workspace_step.output.get("verilog", "")):
success = True
case default:
if os.path.exists(workspace_step.output.get("def", "")) and \
os.path.exists(workspace_step.output.get("verilog", "")) and \
Expand Down
1 change: 1 addition & 0 deletions chipcompiler/pyinstaller_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
EXCLUDED_PAYLOAD_PREFIXES = (
"chipcompiler/thirdparty/ecc-tools",
"chipcompiler/thirdparty/ecc-sizer",
"chipcompiler/thirdparty/ecc-dreamplace/test",
"chipcompiler/thirdparty/ecc-dreamplace/docs",
"chipcompiler/thirdparty/ecc-dreamplace/build",
Expand Down
22 changes: 22 additions & 0 deletions chipcompiler/thirdparty/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,28 @@ cmake(
out_data_dirs = ["lib"],
)

cmake(
name = "ecc_sizer_cmake",
lib_source = "@ecc_sizer_src//:all_sources",
cache_entries = {
"BUILD_GUI": "OFF",
"BUILD_PYTHON": "OFF",
"CMAKE_BUILD_TYPE": "Release",
"ENABLE_TESTS": "OFF",
},
targets = ["Sizer"],
generate_crosstool_file = False,
Comment thread
Copilot marked this conversation as resolved.
install = False,
postfix_script = """
mkdir -p $$INSTALLDIR/bin
find . -type f -name Sizer -perm /111 -exec cp -f {} $$INSTALLDIR/bin/Sizer \\; -quit
ls $$INSTALLDIR/bin/Sizer >/dev/null 2>&1 || { echo "ERROR: Sizer executable not found"; exit 1; }
""",
env = {"PKG_CONFIG_PATH": PKG_CONFIG_PATH},
generate_args = ["-GNinja"],
out_binaries = ["Sizer"],
)

cpp_runtime_bundle(
name = "ecc_bundle",
cmake_target = ":ecc_py_cmake",
Expand Down
1 change: 1 addition & 0 deletions chipcompiler/thirdparty/ecc-sizer
Submodule ecc-sizer added at 7ce615
1 change: 1 addition & 0 deletions chipcompiler/tools/ecc/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ def build_step(workspace: Workspace,
f"{StepEnum.FILLER.value}": f"{step.directory}/data/pl",
f"{StepEnum.CTS.value}": f"{step.directory}/data/cts",
f"{StepEnum.NETLIST_OPT.value}": f"{step.directory}/data/no",
f"{StepEnum.TIMING_OPT.value}": f"{step.directory}/data/to",
f"{StepEnum.TIMING_OPT_DRV.value}": f"{step.directory}/data/to",
f"{StepEnum.TIMING_OPT_HOLD.value}": f"{step.directory}/data/to",
f"{StepEnum.TIMING_OPT_SETUP.value}": f"{step.directory}/data/to",
Expand Down
13 changes: 13 additions & 0 deletions chipcompiler/tools/ecc_sizer/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from .builder import build_step, build_step_config, build_step_space
from .runner import run_step
from .utility import get_sizer_command, get_sizer_root, is_eda_exist

__all__ = [
"build_step",
"build_step_config",
"build_step_space",
"get_sizer_command",
"get_sizer_root",
"is_eda_exist",
"run_step",
]
119 changes: 119 additions & 0 deletions chipcompiler/tools/ecc_sizer/builder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
from __future__ import annotations

import os
import shutil

from chipcompiler.data import Workspace, WorkspaceStep
from chipcompiler.tools.ecc import builder as ecc_builder

from .utility import get_sizer_root


def build_step(
workspace: Workspace,
step_name: str,
input_def: str,
input_verilog: str,
input_db: str | None = None,
output_def: str | None = None,
output_verilog: str | None = None,
output_gds: str | None = None,
) -> WorkspaceStep:
step = ecc_builder.build_step(
workspace=workspace,
step_name=step_name,
input_def=input_def,
input_verilog=input_verilog,
input_db=input_db,
output_def=output_def,
output_verilog=output_verilog,
output_gds=output_gds,
tool="sizer",
)
step.script["sizer_env"] = f"{step.script['dir']}/{workspace.design.name}.env_file"
step.script["sizer_cmd"] = f"{step.script['dir']}/{workspace.design.name}.cmd_file"
return step


def build_step_space(step: WorkspaceStep) -> None:
ecc_builder.build_step_space(step)


def _copy_or_seed_template(template: str, target: str, fallback: str) -> None:
os.makedirs(os.path.dirname(target), exist_ok=True)
if os.path.exists(template):
shutil.copy2(template, target)
return

with open(target, "w", encoding="utf-8") as file:
file.write(fallback)


def _append_lines(path: str, lines: list[str]) -> None:
with open(path, "a", encoding="utf-8") as file:
for line in lines:
if line:
file.write(f"{line}\n")


def _sizer_templates() -> tuple[str, str]:
submit_dir = get_sizer_root() / "submit"
return str(submit_dir / "env_base_file"), str(submit_dir / "cmd_base_file")


def _tech_lines(workspace: Workspace) -> list[str]:
lines = []
if workspace.pdk.tech:
lines.append(f"-lef {workspace.pdk.tech}")
lines.extend(f"-lef {lef}" for lef in workspace.pdk.lefs)
lines.extend(f"-lib {lib}" for lib in workspace.pdk.libs)

tcl_path = get_sizer_root() / "src" / "sizer_os.tcl"
lines.append(f"-tclFile {tcl_path}")
return lines


def _route_layer_lines(workspace: Workspace) -> list[str]:
bottom = workspace.parameters.data.get("Bottom layer", "")
top = workspace.parameters.data.get("Top layer", "")

lines = []
if bottom:
lines.append(f"-min_route_layer {bottom}")
if top:
lines.append(f"-max_route_layer {top}")
return lines


def build_step_config(workspace: Workspace, step: WorkspaceStep) -> None:
env_template, cmd_template = _sizer_templates()
env_path = step.script["sizer_env"]
cmd_path = step.script["sizer_cmd"]

_copy_or_seed_template(env_template, env_path, "-num_vt 1\n")
_copy_or_seed_template(cmd_template, cmd_path, "")

output_dir = step.data.get(step.name, step.data["dir"])
cmd_lines = [
"",
f"-top {workspace.design.top_module or workspace.design.name}",
f"-def {step.input.get('def', '')}",
]
input_verilog = step.input.get("verilog", "")
if input_verilog:
cmd_lines.append(f"-v {input_verilog}")
if workspace.pdk.sdc:
cmd_lines.append(f"-sdc {workspace.pdk.sdc}")
if workspace.pdk.spef:
cmd_lines.append(f"-spef {workspace.pdk.spef}")
cmd_lines.extend(
[
f"-outputPath {output_dir}",
f"-def_out_path {step.output['def']}",
f"-verilog_out_path {step.output['verilog']}",
]
)
cmd_lines.extend(_route_layer_lines(workspace))

_append_lines(env_path, _tech_lines(workspace))
_append_lines(cmd_path, cmd_lines)
Loading
Loading