diff --git a/.bazelversion b/.bazelversion index 93c8ddab9f..acd405b1d6 100644 --- a/.bazelversion +++ b/.bazelversion @@ -1 +1 @@ -7.6.0 +8.6.0 diff --git a/.github/workflows/github-actions-cron-update-OR.yml b/.github/workflows/github-actions-cron-update-OR.yml index 1784acb15e..5ed3468030 100644 --- a/.github/workflows/github-actions-cron-update-OR.yml +++ b/.github/workflows/github-actions-cron-update-OR.yml @@ -24,7 +24,7 @@ jobs: git pull - if: "steps.remote-update.outputs.has_update != ''" name: Create Draft PR - uses: peter-evans/create-pull-request@v7 + uses: peter-evans/create-pull-request@v8 with: token: ${{ github.token }} signoff: true diff --git a/.github/workflows/github-actions-cron-update-yosys.yml b/.github/workflows/github-actions-cron-update-yosys.yml index 11bab5fe55..7f9f947eda 100644 --- a/.github/workflows/github-actions-cron-update-yosys.yml +++ b/.github/workflows/github-actions-cron-update-yosys.yml @@ -28,7 +28,7 @@ jobs: git checkout ${latesttag} - if: "steps.remote-update.outputs.has_update != ''" name: Create Draft PR - uses: peter-evans/create-pull-request@v7 + uses: peter-evans/create-pull-request@v8 with: token: ${{ github.token }} signoff: true diff --git a/.github/workflows/github-actions-cron-util-test.yml b/.github/workflows/github-actions-cron-util-test.yml index e2636fc7ad..0995738b48 100644 --- a/.github/workflows/github-actions-cron-util-test.yml +++ b/.github/workflows/github-actions-cron-util-test.yml @@ -4,12 +4,12 @@ on: - cron: "0 8 * * SUN" push: paths: - - 'flow/util/genElapsedTime.py' - - 'flow/test/test_genElapsedTime.py' + - 'flow/util/*.py' + - 'flow/test/test_*.py' pull_request: paths: - - 'flow/util/genElapsedTime.py' - - 'flow/test/test_genElapsedTime.py' + - 'flow/util/*.py' + - 'flow/test/test_*.py' # Allows you to run this workflow manually from the Actions tab workflow_dispatch: diff --git a/.github/workflows/github-actions-publish-docker-images.yml b/.github/workflows/github-actions-publish-docker-images.yml index ef64cc8e30..14a90d1b28 100644 --- a/.github/workflows/github-actions-publish-docker-images.yml +++ b/.github/workflows/github-actions-publish-docker-images.yml @@ -36,18 +36,18 @@ jobs: run: echo "IMAGE=ghcr.io/$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Login to GitHub Container Registry (GHCR) if: github.event_name != 'pull_request' - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ghcr.io username: gha password: ${{ github.token }} - name: Build and export codespaces image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: context: . push: true @@ -74,11 +74,11 @@ jobs: echo "IMAGE_DEPS=ghcr.io/$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')-dev/${{ matrix.os[0] }}" >> $GITHUB_ENV - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Login to GitHub Container Registry (GHCR) if: github.event_name != 'pull_request' - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ghcr.io username: gha @@ -88,7 +88,7 @@ jobs: run: cp tools/OpenROAD/etc/DependencyInstaller.sh etc/InstallerOpenROAD.sh - name: Build and export dependencies image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: context: etc push: true @@ -125,18 +125,18 @@ jobs: echo "NUM_THREADS=$(nproc)" >> $GITHUB_ENV - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Login to GitHub Container Registry (GHCR) if: github.event_name != 'pull_request' - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ghcr.io username: gha password: ${{ github.token }} - name: Build and export ORFS image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@v7 with: context: . push: true diff --git a/.github/workflows/github-actions-stale.yml b/.github/workflows/github-actions-stale.yml new file mode 100644 index 0000000000..3d53d0ace2 --- /dev/null +++ b/.github/workflows/github-actions-stale.yml @@ -0,0 +1,39 @@ +name: Mark stale issues and pull requests + +on: + schedule: + - cron: "0 0 * * *" + workflow_dispatch: + +jobs: + Stale: + runs-on: ${{ vars.USE_SELF_HOSTED == 'true' && 'self-hosted' || 'ubuntu-latest' }} + + permissions: + # Required to label and close stale issues. + issues: write + # Required to label and close stale pull requests. + pull-requests: write + # Required to save state between runs + actions: write + + steps: + - uses: actions/stale@v10 + with: + days-before-stale: 60 + days-before-close: 21 + stale-issue-label: Stale + stale-pr-label: Stale + stale-issue-message: > + This issue has been automatically marked as stale because it has not + had recent activity. It will be closed in 21 days if no further + activity occurs. Remove the `Stale` label or comment to keep it open. + stale-pr-message: > + This pull request has been automatically marked as stale because it + has not had recent activity. It will be closed in 21 days if no + further activity occurs. Remove the `Stale` label or comment to keep + it open. + close-issue-reason: not_planned + exempt-issue-labels: pinned,security + exempt-pr-labels: pinned,security + operations-per-run: 100 diff --git a/.github/workflows/github-actions-update-rules.yml b/.github/workflows/github-actions-update-rules.yml index 6f85145a7d..930a280480 100644 --- a/.github/workflows/github-actions-update-rules.yml +++ b/.github/workflows/github-actions-update-rules.yml @@ -58,7 +58,7 @@ jobs: git push origin "HEAD:refs/pull/${{ github.event.client_payload.branch }}/head" - if: "steps.remote-update.outputs.has_update == 'true' && github.event.client_payload.branch == 'master'" name: Create Draft PR - uses: peter-evans/create-pull-request@v7 + uses: peter-evans/create-pull-request@v8 with: token: ${{ github.token }} signoff: true diff --git a/.gitmodules b/.gitmodules index 32bdbc7301..170484c52b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,7 +3,7 @@ url = ../../The-OpenROAD-Project/yosys.git [submodule "tools/OpenROAD"] path = tools/OpenROAD - url = ../OpenROAD.git + url = git@github.com:eclufsc/OpenROAD_ecl.git [submodule "tools/yosys-slang"] path = tools/yosys-slang url = https://github.com/povik/yosys-slang.git diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 0000000000..21e694405f --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,6 @@ +load("@rules_shell//shell:sh_binary.bzl", "sh_binary") + +sh_binary( + name = "install_for_bazel", + srcs = ["bazel/install.sh"], +) diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000000..490967ecde --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,5 @@ +@Library('utils@main') _ + +node { + pipelineORFS() +} diff --git a/MODULE.bazel b/MODULE.bazel index 574d678f5d..9687e51c48 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -16,6 +16,7 @@ git_override( ) bazel_dep(name = "rules_python", version = "1.2.0") +bazel_dep(name = "rules_shell", version = "0.6.1") python = use_extension("@rules_python//python/extensions:python.bzl", "python") python.toolchain( diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 45ece7112e..ffe386712a 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -124,7 +124,8 @@ "https://bcr.bazel.build/modules/rules_python/1.2.0/MODULE.bazel": "5aeeb48b2a6c19d668b48adf2b8a2b209a6310c230db0ce77450f148a89846e4", "https://bcr.bazel.build/modules/rules_python/1.2.0/source.json": "5b7892685c9a843526fd5a31e7d7a93eb819c59fd7b7fc444b5b143558e1b073", "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", - "https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95", + "https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b", + "https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c", "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", "https://bcr.bazel.build/modules/stardoc/0.6.2/MODULE.bazel": "7060193196395f5dd668eda046ccbeacebfd98efc77fed418dbe2b82ffaa39fd", diff --git a/README.md b/README.md index 177c240986..05a648ff05 100644 --- a/README.md +++ b/README.md @@ -29,14 +29,16 @@ timeline : Global placement without placed IOs : IO placement (optimized) : Global placement with placed IOs - : Resizing and buffering + : Resizing and buffering (max cap / max fanout violations) : Detailed placement CTS : Clock Tree Synthesis - : Timing optimization - : Filler cell insertion + : Resizing and buffering (stup and hold violations ) Routing : Global Routing + : Resizing and buffering (max cap / max fanout violations) + : Resizing and buffering (stup and hold violations ) : Detailed Routing + : Filler cell insertion Finishing : Metal Fill insertion : Signoff timing report diff --git a/bazel/install.sh b/bazel/install.sh new file mode 100755 index 0000000000..21a3f48c01 --- /dev/null +++ b/bazel/install.sh @@ -0,0 +1,141 @@ +#!/bin/bash +set -e + +# ORFS developer install script +# Builds and installs OpenROAD, Yosys, and yosys-slang to tools/install/ +# where flow/Makefile expects them. +# +# Uses stamp files for fast no-op re-runs (seconds when nothing changed). + +WORKSPACE="${BUILD_WORKSPACE_DIRECTORY:-.}" +INSTALL_DIR="${WORKSPACE}/tools/install" +NUM_THREADS=$(nproc) + +# --- Check system dependencies for yosys/slang builds --- +check_deps() { + local missing_cmds=() + + for cmd in bison flex gawk g++ pkg-config tclsh git cmake; do + if ! command -v "$cmd" &>/dev/null; then + missing_cmds+=("$cmd") + fi + done + + if [[ ${#missing_cmds[@]} -eq 0 ]]; then + return + fi + + echo "ERROR: Missing commands: ${missing_cmds[*]}" + echo "" + + # Platform-specific install hint + if [[ "$(uname -s)" == "Darwin" ]]; then + echo " brew install bison flex gawk cmake pkg-config tcl-tk" + elif command -v apt-get &>/dev/null; then + echo " sudo apt-get install bison flex gawk g++ pkg-config tcl cmake git" + elif command -v dnf &>/dev/null; then + echo " sudo dnf install bison flex gawk gcc-c++ pkgconf tcl cmake git" + elif command -v yum &>/dev/null; then + echo " sudo yum install bison flex gawk gcc-c++ pkgconf tcl cmake git" + elif command -v zypper &>/dev/null; then + echo " sudo zypper install bison flex gawk gcc-c++ pkg-config tcl cmake git" + fi + exit 1 +} + +check_deps + +BUILD_OPENROAD=1 + +usage() { + cat <<'EOF' +Usage: bazelisk run //:install_for_bazel [-- OPTIONS] + +Options: + --help, -h Show this help + --skip-openroad Skip OpenROAD build + --threads N Compilation threads (default: nproc) +EOF + exit 0 +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --help|-h) + usage + ;; + --skip-openroad) + BUILD_OPENROAD=0 + ;; + --threads) + NUM_THREADS="$2" + shift + ;; + *) + echo "Unknown option: $1" + usage + ;; + esac + shift +done + +# --- Check submodules are initialized --- +for sub in tools/OpenROAD tools/yosys tools/yosys-slang; do + if [[ ! -d "${WORKSPACE}/${sub}" ]] || [[ -z "$(ls -A "${WORKSPACE}/${sub}" 2>/dev/null)" ]]; then + echo "ERROR: ${sub} not initialized." + echo "Run: git submodule update --init --recursive" + exit 1 + fi +done + +# --- OpenROAD (delegates to its own //:install) --- +if [[ $BUILD_OPENROAD -eq 1 ]]; then + echo "=== Building OpenROAD with GUI support ===" + (cd "${WORKSPACE}/tools/OpenROAD" && bazelisk run --//:platform=gui //:install) +fi + +# --- Yosys --- +# Uses stamp file for fast no-op: if the yosys submodule commit hasn't +# changed, skip the build entirely. +YOSYS_INSTALL="${INSTALL_DIR}/yosys" +YOSYS_STAMP="${YOSYS_INSTALL}/.yosys_commit" +YOSYS_COMMIT="$(git -C "${WORKSPACE}/tools/yosys" rev-parse HEAD)" + +if [[ -f "${YOSYS_STAMP}" ]] && [[ "$(cat "${YOSYS_STAMP}")" == "${YOSYS_COMMIT}" ]]; then + echo "=== Yosys already up to date (${YOSYS_COMMIT:0:12}) ===" +else + echo "=== Building Yosys ===" + ( + cd "${WORKSPACE}/tools/yosys" + make -j "${NUM_THREADS}" PREFIX="${YOSYS_INSTALL}" ABC_ARCHFLAGS=-Wno-register + make install PREFIX="${YOSYS_INSTALL}" + ) + echo "${YOSYS_COMMIT}" > "${YOSYS_STAMP}" + echo "Yosys installed to ${YOSYS_INSTALL}/bin/yosys" +fi + +# --- yosys-slang --- +SLANG_STAMP="${YOSYS_INSTALL}/.slang_commit" +SLANG_COMMIT="$(git -C "${WORKSPACE}/tools/yosys-slang" rev-parse HEAD)" + +if [[ -f "${SLANG_STAMP}" ]] && [[ "$(cat "${SLANG_STAMP}")" == "${SLANG_COMMIT}" ]]; then + echo "=== yosys-slang already up to date (${SLANG_COMMIT:0:12}) ===" +else + echo "=== Building yosys-slang ===" + ( + cd "${WORKSPACE}/tools/yosys-slang" + cmake -S . -B build \ + -DYOSYS_CONFIG="${YOSYS_INSTALL}/bin/yosys-config" \ + -DCMAKE_BUILD_TYPE=Release \ + -DYOSYS_SLANG_REVISION=unknown \ + -DSLANG_REVISION=unknown + cmake --build build -j "${NUM_THREADS}" + cmake --install build --prefix "${YOSYS_INSTALL}" + ) + echo "${SLANG_COMMIT}" > "${SLANG_STAMP}" + echo "yosys-slang installed to ${YOSYS_INSTALL}/share/yosys/plugins/" +fi + +echo "" +echo "=== Done ===" +echo "cd flow && make" diff --git a/build_openroad.sh b/build_openroad.sh index 74303aa69e..aa19f183a4 100755 --- a/build_openroad.sh +++ b/build_openroad.sh @@ -29,9 +29,11 @@ OPENROAD_APP_ARGS="" DOCKER_OS_NAME="ubuntu22.04" PROC=-1 -VERIFIC_COMPONENTS='database util containers pct hier_tree verilog' WITH_VERIFIC=0 -VERIFIC_DIR="" +VERIFIC_SRC="" +VERIFIC_COMPONENTS='database util containers pct hier_tree verilog' +VERIFIC_ARGS=" VERIFIC_COMPONENTS='${VERIFIC_COMPONENTS}'" +VERIFIC_ARGS+=" ENABLE_VERIFIC=1 ENABLE_VERIFIC_VHDL=0 VERIFIC_DIR=verific" function usage() { cat << EOF @@ -145,20 +147,17 @@ while (( "$#" )); do YOSYS_OVERWRITE_ARGS=1 ;; --yosys-args) - YOSYS_USER_ARGS="$2" + YOSYS_USER_ARGS+="$2" shift ;; --with-verific) - YOSYS_USER_ARGS+=" ENABLE_VERIFIC=1" - YOSYS_USER_ARGS+=" ENABLE_VERIFIC_VHDL=0" - YOSYS_USER_ARGS+=" VERIFIC_COMPONENTS='${VERIFIC_COMPONENTS}'" - VERIFIC_DIR=${2} - if [ ! -d "${VERIFIC_DIR}" ]; then - echo "[ERROR] Verific path '${VERIFIC_DIR}' does not exist." >&2 + WITH_VERIFIC=1 + VERIFIC_SRC=${2} + if [ ! -d "${VERIFIC_SRC}" ]; then + echo "[ERROR] Verific path '${VERIFIC_SRC}' does not exist." >&2 exit 1 fi - YOSYS_USER_ARGS+=" VERIFIC_DIR=${VERIFIC_DIR}" - WITH_VERIFIC=1 + YOSYS_USER_ARGS+="${VERIFIC_ARGS}" shift ;; --openroad-args-overwrite) @@ -238,8 +237,14 @@ __docker_build() cp .dockerignore{,.bak} sed -i '/flow\/platforms/d' .dockerignore fi + options="" + if [ -n "${WITH_VERIFIC}" ]; then + cp -r "${VERIFIC_SRC}" tools/verific + options="-buildArgs=--build-arg verificPath=tools/verific" + fi ./etc/DockerHelper.sh create -target=dev -os="${DOCKER_OS_NAME}" -threads="${PROC}" - ./etc/DockerHelper.sh create -target=builder -os="${DOCKER_OS_NAME}" -threads="${PROC}" + ./etc/DockerHelper.sh create -target=builder -os="${DOCKER_OS_NAME}" -threads="${PROC}" "${options}" + rm -rf tools/verific if [ ! -z "${DOCKER_COPY_PLATFORMS+x}" ]; then mv .dockerignore{.bak,} fi @@ -248,39 +253,56 @@ __docker_build() __local_build() { if [[ "$OSTYPE" == "darwin"* ]]; then - export PATH="$(brew --prefix bison)/bin:$(brew --prefix flex)/bin:$(brew --prefix tcl-tk)/bin:$PATH" - export CMAKE_PREFIX_PATH=$(brew --prefix or-tools) + export PATH="$(brew --prefix bison)/bin:$(brew --prefix flex)/bin:$(brew --prefix tcl-tk)/bin:$PATH" + export CMAKE_PREFIX_PATH=$(brew --prefix or-tools) fi if [[ -f "/opt/rh/rh-python38/enable" ]]; then - set +u - source /opt/rh/rh-python38/enable - set -u + set +u + source /opt/rh/rh-python38/enable + set -u fi if [[ -f "/opt/rh/devtoolset-8/enable" ]]; then - # the scl script has unbound variables - set +u - source /opt/rh/devtoolset-8/enable - set -u + # the scl script has unbound variables + set +u + source /opt/rh/devtoolset-8/enable + set -u fi if [ -z "${SKIP_OPENROAD+x}" ]; then - echo "[INFO FLW-0018] Compiling OpenROAD." - eval ${NICE} ./tools/OpenROAD/etc/Build.sh -dir="$DIR/tools/OpenROAD/build" -threads=${PROC} -cmake=\'${OPENROAD_APP_ARGS}\' - ${NICE} cmake --build tools/OpenROAD/build --target install -j "${PROC}" + echo "[INFO FLW-0018] Compiling OpenROAD." + if [ -f "${DIR}/openroad_deps_prefixes.txt" ]; then + DEPS_PREFIX_ARG="${DIR}/openroad_deps_prefixes.txt" + elif [ -f "${DIR}/tools/OpenROAD/etc/openroad_deps_prefixes.txt" ]; then + DEPS_PREFIX_ARG="${DIR}/tools/OpenROAD/etc/openroad_deps_prefixes.txt" + elif [ -f /etc/openroad_deps_prefixes.txt ]; then + DEPS_PREFIX_ARG="/etc/openroad_deps_prefixes.txt" + else + DEPS_PREFIX_ARG="" + fi + if [[ -n "${DEPS_PREFIX_ARG}" ]]; then + echo "[INFO FLW-0029] Found OpenROAD dependencies prefixes file: '${DEPS_PREFIX_ARG}'." + DEPS_PREFIX_ARG="-deps-prefixes-file=${DEPS_PREFIX_ARG}" + fi + eval ${NICE} ./tools/OpenROAD/etc/Build.sh \ + -dir="$DIR/tools/OpenROAD/build" \ + -threads=${PROC} \ + -cmake=\'${OPENROAD_APP_ARGS}\' \ + ${DEPS_PREFIX_ARG} + ${NICE} cmake --build tools/OpenROAD/build --target install -j "${PROC}" fi YOSYS_ABC_PATH=tools/yosys/abc if [[ -d "${YOSYS_ABC_PATH}/.git" ]]; then - # update indexes to make sure git diff-index uses correct data - git --work-tree=${YOSYS_ABC_PATH} --git-dir=${YOSYS_ABC_PATH}/.git update-index --refresh + # update indexes to make sure git diff-index uses correct data + git --work-tree=${YOSYS_ABC_PATH} --git-dir=${YOSYS_ABC_PATH}/.git update-index --refresh fi if [ ${WITH_VERIFIC} -eq 1 ]; then echo "[INFO FLW-0031] Compiling Verific components." - cp -r "${VERIFIC_DIR}" verific + cp -r "${VERIFIC_SRC}" tools/yosys/verific for c in ${VERIFIC_COMPONENTS}; do - make -j -C "verific/${c}" clean - make -j -C "verific/${c}" + make -j -C "tools/yosys/verific/${c}" clean + make -j -C "tools/yosys/verific/${c}" done fi @@ -305,7 +327,7 @@ __local_build() if [ ${WITH_VERIFIC} -eq 1 ]; then echo "[INFO FLW-0032] Cleaning up Verific components." - rm -rf verific + rm -rf tools/yosys/verific fi } diff --git a/docker/Dockerfile.builder b/docker/Dockerfile.builder index 62419e533c..7b8ff10f7f 100644 --- a/docker/Dockerfile.builder +++ b/docker/Dockerfile.builder @@ -31,9 +31,25 @@ ENV PATH="/usr/local/bin/wrapped-cc:$PATH" COPY --link tools tools ARG numThreads=$(nproc) ARG openroadVersion=NotSet +ARG verificPath="" -RUN echo "" > tools/yosys/abc/.gitcommit && \ - ./build_openroad.sh --no_init --local --threads ${numThreads} --openroad-args -DOPENROAD_VERSION=${openroadVersion} +RUN < tools/yosys/abc/.gitcommit +if [ -n "${verificPath}" ]; then + verificArgs="--with-verific ${verificPath}" +else + verificArgs="" +fi +./build_openroad.sh --no_init \ + --local \ + --threads ${numThreads} \ + --openroad-args -DOPENROAD_VERSION=${openroadVersion} \ + ${verificArgs} +if [ -n "${verificPath}" ]; then + rm -rf "${verificPath}" +fi +EOF FROM orfs-base diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev index a2a822b486..288d4ef709 100644 --- a/docker/Dockerfile.dev +++ b/docker/Dockerfile.dev @@ -28,8 +28,7 @@ RUN mkdir -p /usr/local/bin/wrapped-cc && \ ENV PATH="/usr/local/bin/wrapped-cc:$PATH" -RUN ./DependencyInstaller.sh -base $options $constantBuildDir \ - && ./DependencyInstaller.sh -common $options $constantBuildDir \ +RUN ./DependencyInstaller.sh -all $options $constantBuildDir -save-deps-prefixes=/etc/openroad_deps_prefixes.txt \ && rm -rf /tmp/installer /tmp/* /var/tmp/* /var/lib/apt/lists/* ARG fromImage @@ -37,3 +36,5 @@ ARG fromImage RUN echo "$fromImage" | grep -q "ubuntu" && \ strip --remove-section=.note.ABI-tag /usr/lib/x86_64-linux-gnu/libQt5Core.so || \ echo "Skipping strip command as fromImage does not contain 'ubuntu'" + +WORKDIR /OpenROAD-flow-scripts diff --git a/docs/user/BuildLocally.md b/docs/user/BuildLocally.md index 79a2dd09aa..120b4f943e 100644 --- a/docs/user/BuildLocally.md +++ b/docs/user/BuildLocally.md @@ -12,23 +12,20 @@ cd OpenROAD-flow-scripts sudo ./setup.sh ``` -## Using Bazel to build OpenROAD and run the ORFS flow +## Using Bazel to build OpenROAD and run the ORFS flow (unsupported) -Long story short: OpenROAD will eventually switch to using Bazel for downloading dependencies and building OpenROAD for all the reasons that the DependencyInstaller.sh and cmake are hard to support and brittle across platforms. - -Currently the simplest way to build OpenROAD and run ORFS is to run one test, which will download all OpenROAD dependencies and build OpenROAD in the exec configuration: +For ORFS/OpenROAD developers. Most of `./setup.sh` isn't needed when +building OpenROAD with Bazel — this provides the bare minimum to build +OpenROAD and test ORFS flows. No sudo required. +Install [Bazelisk](https://bazel.build/install/bazelisk) first. ``` shell -cd tools/OpenROAD -bazelisk test src/drt/... -cd ../../flow -make OPENROAD_EXE=$(pwd)/../tools/OpenROAD/bazel-out/k8-opt-exec-ST-*/bin/openroad +git clone --recursive https://github.com/The-OpenROAD-Project/OpenROAD-flow-scripts +cd OpenROAD-flow-scripts +bazelisk run //:install_for_bazel +cd flow && make ``` -Bazel could similarly be used to download and make available pre-built binaries for tools such as Yosys, eqy and KLayout. - -Running some quick tests will cause the desired exec config of OpenROAD to be built. There's no explicit Bazel way to build an exec config of an executable and we want to to use an exec config that is the same binary as is used for a local OpenROAD modify + test Bazel cycle. - ## Build ``` shell diff --git a/docs/user/FlowVariables.md b/docs/user/FlowVariables.md index 0ebd3722ef..b8aa8f65e1 100644 --- a/docs/user/FlowVariables.md +++ b/docs/user/FlowVariables.md @@ -192,7 +192,39 @@ configuration file. | PLATFORM| Specifies process design kit or technology node to be used.| | | PLATFORM_TCL| Specifies a Tcl script with commands to run before loading design.| | | POST_CTS_TCL| Specifies a Tcl script with commands to run after CTS is completed.| | +| POST_DENSITY_FILL_TCL| Specifies a Tcl script with commands to run after density fill.| | +| POST_DETAIL_PLACE_TCL| Specifies a Tcl script with commands to run after detailed placement.| | +| POST_DETAIL_ROUTE_TCL| Specifies a Tcl script with commands to run after detailed route.| | +| POST_FILLCELL_TCL| Specifies a Tcl script with commands to run after fillcell insertion.| | +| POST_FINAL_REPORT_TCL| Specifies a Tcl script with commands to run after final report generation.| | +| POST_FLOORPLAN_TCL| Specifies a Tcl script with commands to run after floorplan is completed.| | +| POST_GLOBAL_PLACE_SKIP_IO_TCL| Specifies a Tcl script with commands to run after global placement (skip IO).| | +| POST_GLOBAL_PLACE_TCL| Specifies a Tcl script with commands to run after global placement.| | +| POST_GLOBAL_ROUTE_TCL| Specifies a Tcl script with commands to run after global route.| | +| POST_IO_PLACEMENT_TCL| Specifies a Tcl script with commands to run after IO placement.| | +| POST_MACRO_PLACE_TCL| Specifies a Tcl script with commands to run after macro placement.| | +| POST_PDN_TCL| Specifies a Tcl script with commands to run after PDN generation.| | +| POST_REPAIR_TIMING_POST_PLACE_TCL| Specifies a Tcl script with commands to run after post-place timing repair.| | +| POST_RESIZE_TCL| Specifies a Tcl script with commands to run after resize.| | +| POST_SYNTH_TCL| Specifies a Tcl script with commands to run after synthesis ODB generation.| | +| POST_TAPCELL_TCL| Specifies a Tcl script with commands to run after tapcell.| | +| PRE_CTS_TCL| Specifies a Tcl script with commands to run before CTS.| | +| PRE_DENSITY_FILL_TCL| Specifies a Tcl script with commands to run before density fill.| | +| PRE_DETAIL_PLACE_TCL| Specifies a Tcl script with commands to run before detailed placement.| | +| PRE_DETAIL_ROUTE_TCL| Specifies a Tcl script with commands to run before detailed route.| | +| PRE_FILLCELL_TCL| Specifies a Tcl script with commands to run before fillcell insertion.| | +| PRE_FINAL_REPORT_TCL| Specifies a Tcl script with commands to run before final report generation.| | +| PRE_FLOORPLAN_TCL| Specifies a Tcl script with commands to run before floorplan.| | +| PRE_GLOBAL_PLACE_SKIP_IO_TCL| Specifies a Tcl script with commands to run before global placement (skip IO).| | +| PRE_GLOBAL_PLACE_TCL| Specifies a Tcl script with commands to run before global placement.| | | PRE_GLOBAL_ROUTE_TCL| Specifies a Tcl script with commands to run before global route.| | +| PRE_IO_PLACEMENT_TCL| Specifies a Tcl script with commands to run before IO placement.| | +| PRE_MACRO_PLACE_TCL| Specifies a Tcl script with commands to run before macro placement.| | +| PRE_PDN_TCL| Specifies a Tcl script with commands to run before PDN generation.| | +| PRE_REPAIR_TIMING_POST_PLACE_TCL| Specifies a Tcl script with commands to run before post-place timing repair.| | +| PRE_RESIZE_TCL| Specifies a Tcl script with commands to run before resize.| | +| PRE_SYNTH_TCL| Specifies a Tcl script with commands to run before synthesis ODB generation.| | +| PRE_TAPCELL_TCL| Specifies a Tcl script with commands to run before tapcell.| | | PROCESS| Technology node or process in use.| | | PWR_NETS_VOLTAGES| Used for IR Drop calculation.| | | RCX_RULES| RC Extraction rules file path.| | @@ -202,7 +234,7 @@ configuration file. | REMOVE_CELLS_FOR_LEC| String patterns directly passed to write_verilog -remove_cells <> for lec checks.| | | REPAIR_PDN_VIA_LAYER| Remove power grid vias which generate DRC violations after detailed routing.| | | REPORT_CLOCK_SKEW| Report clock skew as part of reporting metrics, starting at CTS, before which there is no clock skew. This metric can be quite time-consuming, so it can be useful to disable.| 1| -| ROUTING_LAYER_ADJUSTMENT| Adjusts routing layer capacities to manage congestion and improve detailed routing. High values ease detailed routing but risk excessive detours and long global routing times, while low values reduce global routing failure but can complicate detailed routing. The global routing running time normally reduces dramatically (entirely design specific, but going from hours to minutes has been observed) when the value is low (such as 0.10). Sometimes, global routing will succeed with lower values and fail with higher values. Exploring results with different values can help shed light on the problem. Start with a too low value, such as 0.10, and bisect to value that works by doing multiple global routing runs. As a last resort, `make global_route_issue` and using the tools/OpenROAD/etc/deltaDebug.py can be useful to debug global routing errors. If there is something specific that is impossible to route, such as a clock line over a macro, global routing will terminate with DRC errors routes that could have been routed were it not for the specific impossible routes. deltaDebug.py should weed out the possible routes and leave a minimal failing case that pinpoints the problem.| 0.5| +| ROUTING_LAYER_ADJUSTMENT| Adjusts routing layer capacities to manage congestion and improve detailed routing. High values ease detailed routing but risk excessive detours and long global routing times, while low values reduce global routing failure but can complicate detailed routing. The global routing running time normally reduces dramatically (entirely design specific, but going from hours to minutes has been observed) when the value is low (such as 0.10). Sometimes, global routing will succeed with lower values and fail with higher values. Exploring results with different values can help shed light on the problem. Start with a too low value, such as 0.10, and bisect to value that works by doing multiple global routing runs. As a last resort, `make global_route_issue` and using the tools/OpenROAD/etc/whittle.py can be useful to debug global routing errors. If there is something specific that is impossible to route, such as a clock line over a macro, global routing will terminate with DRC errors routes that could have been routed were it not for the specific impossible routes. whittle.py should weed out the possible routes and leave a minimal failing case that pinpoints the problem.| 0.5| | RTLMP_AREA_WT| Weight for the area of the current floorplan.| 0.1| | RTLMP_ARGS| Overrides all other RTL macro placer arguments.| | | RTLMP_BOUNDARY_WT| Weight for the boundary or how far the hard macro clusters are from boundaries.| 50.0| @@ -273,6 +305,7 @@ configuration file. | TIELO_CELL_AND_PORT| Tie low cells used in Yosys synthesis to replace a logical 0 in the Netlist.| | | TIE_SEPARATION| Distance separating tie high/low instances from the load.| 0| | TNS_END_PERCENT| Default TNS_END_PERCENT value for post CTS timing repair. Try fixing all violating endpoints by default (reduce to 5% for runtime). Specifies how many percent of violating paths to fix [0-100]. Worst path will always be fixed.| 100| +| UNSET_ABC9_BOX_CELLS| List of cells to unset the abc9_box attribute on| | | USE_FILL| Whether to perform metal density filling.| 0| | VERILOG_DEFINES| Preprocessor defines passed to the language frontend. Example: `-D HPDCACHE_ASSERT_OFF`| | | VERILOG_FILES| The path to the design Verilog/SystemVerilog files providing a description of modules.| | @@ -291,6 +324,8 @@ configuration file. - [DFF_MAP_FILE](#DFF_MAP_FILE) - [LATCH_MAP_FILE](#LATCH_MAP_FILE) - [MIN_BUF_CELL_AND_PORTS](#MIN_BUF_CELL_AND_PORTS) +- [POST_SYNTH_TCL](#POST_SYNTH_TCL) +- [PRE_SYNTH_TCL](#PRE_SYNTH_TCL) - [SDC_FILE](#SDC_FILE) - [SDC_GUT](#SDC_GUT) - [SYNTH_ARGS](#SYNTH_ARGS) @@ -315,6 +350,7 @@ configuration file. - [SYNTH_WRAPPED_MULTIPLIERS](#SYNTH_WRAPPED_MULTIPLIERS) - [TIEHI_CELL_AND_PORT](#TIEHI_CELL_AND_PORT) - [TIELO_CELL_AND_PORT](#TIELO_CELL_AND_PORT) +- [UNSET_ABC9_BOX_CELLS](#UNSET_ABC9_BOX_CELLS) - [VERILOG_DEFINES](#VERILOG_DEFINES) - [VERILOG_FILES](#VERILOG_FILES) - [VERILOG_INCLUDE_DIRS](#VERILOG_INCLUDE_DIRS) @@ -349,6 +385,14 @@ configuration file. - [PLACE_DENSITY](#PLACE_DENSITY) - [PLACE_DENSITY_LB_ADDON](#PLACE_DENSITY_LB_ADDON) - [PLACE_SITE](#PLACE_SITE) +- [POST_FLOORPLAN_TCL](#POST_FLOORPLAN_TCL) +- [POST_MACRO_PLACE_TCL](#POST_MACRO_PLACE_TCL) +- [POST_PDN_TCL](#POST_PDN_TCL) +- [POST_TAPCELL_TCL](#POST_TAPCELL_TCL) +- [PRE_FLOORPLAN_TCL](#PRE_FLOORPLAN_TCL) +- [PRE_MACRO_PLACE_TCL](#PRE_MACRO_PLACE_TCL) +- [PRE_PDN_TCL](#PRE_PDN_TCL) +- [PRE_TAPCELL_TCL](#PRE_TAPCELL_TCL) - [REMOVE_ABC_BUFFERS](#REMOVE_ABC_BUFFERS) - [ROUTING_LAYER_ADJUSTMENT](#ROUTING_LAYER_ADJUSTMENT) - [RTLMP_AREA_WT](#RTLMP_AREA_WT) @@ -408,6 +452,18 @@ configuration file. - [PLACE_DENSITY](#PLACE_DENSITY) - [PLACE_DENSITY_LB_ADDON](#PLACE_DENSITY_LB_ADDON) - [PLACE_PINS_ARGS](#PLACE_PINS_ARGS) +- [POST_DETAIL_PLACE_TCL](#POST_DETAIL_PLACE_TCL) +- [POST_GLOBAL_PLACE_SKIP_IO_TCL](#POST_GLOBAL_PLACE_SKIP_IO_TCL) +- [POST_GLOBAL_PLACE_TCL](#POST_GLOBAL_PLACE_TCL) +- [POST_IO_PLACEMENT_TCL](#POST_IO_PLACEMENT_TCL) +- [POST_REPAIR_TIMING_POST_PLACE_TCL](#POST_REPAIR_TIMING_POST_PLACE_TCL) +- [POST_RESIZE_TCL](#POST_RESIZE_TCL) +- [PRE_DETAIL_PLACE_TCL](#PRE_DETAIL_PLACE_TCL) +- [PRE_GLOBAL_PLACE_SKIP_IO_TCL](#PRE_GLOBAL_PLACE_SKIP_IO_TCL) +- [PRE_GLOBAL_PLACE_TCL](#PRE_GLOBAL_PLACE_TCL) +- [PRE_IO_PLACEMENT_TCL](#PRE_IO_PLACEMENT_TCL) +- [PRE_REPAIR_TIMING_POST_PLACE_TCL](#PRE_REPAIR_TIMING_POST_PLACE_TCL) +- [PRE_RESIZE_TCL](#PRE_RESIZE_TCL) - [ROUTING_LAYER_ADJUSTMENT](#ROUTING_LAYER_ADJUSTMENT) - [SKIP_REPORT_METRICS](#SKIP_REPORT_METRICS) - [TNS_END_PERCENT](#TNS_END_PERCENT) @@ -430,6 +486,7 @@ configuration file. - [MATCH_CELL_FOOTPRINT](#MATCH_CELL_FOOTPRINT) - [MAX_REPAIR_TIMING_ITER](#MAX_REPAIR_TIMING_ITER) - [POST_CTS_TCL](#POST_CTS_TCL) +- [PRE_CTS_TCL](#PRE_CTS_TCL) - [REMOVE_CELLS_FOR_EQY](#REMOVE_CELLS_FOR_EQY) - [REPORT_CLOCK_SKEW](#REPORT_CLOCK_SKEW) - [SETUP_REPAIR_SEQUENCE](#SETUP_REPAIR_SEQUENCE) @@ -453,6 +510,7 @@ configuration file. - [MAX_REPAIR_TIMING_ITER](#MAX_REPAIR_TIMING_ITER) - [MAX_ROUTING_LAYER](#MAX_ROUTING_LAYER) - [MIN_ROUTING_LAYER](#MIN_ROUTING_LAYER) +- [POST_GLOBAL_ROUTE_TCL](#POST_GLOBAL_ROUTE_TCL) - [PRE_GLOBAL_ROUTE_TCL](#PRE_GLOBAL_ROUTE_TCL) - [REPORT_CLOCK_SKEW](#REPORT_CLOCK_SKEW) - [ROUTING_LAYER_ADJUSTMENT](#ROUTING_LAYER_ADJUSTMENT) @@ -478,6 +536,10 @@ configuration file. - [MAX_REPAIR_ANTENNAS_ITER_DRT](#MAX_REPAIR_ANTENNAS_ITER_DRT) - [MAX_ROUTING_LAYER](#MAX_ROUTING_LAYER) - [MIN_ROUTING_LAYER](#MIN_ROUTING_LAYER) +- [POST_DETAIL_ROUTE_TCL](#POST_DETAIL_ROUTE_TCL) +- [POST_FILLCELL_TCL](#POST_FILLCELL_TCL) +- [PRE_DETAIL_ROUTE_TCL](#PRE_DETAIL_ROUTE_TCL) +- [PRE_FILLCELL_TCL](#PRE_FILLCELL_TCL) - [REPORT_CLOCK_SKEW](#REPORT_CLOCK_SKEW) - [ROUTING_LAYER_ADJUSTMENT](#ROUTING_LAYER_ADJUSTMENT) - [SKIP_ANTENNA_REPAIR_POST_DRT](#SKIP_ANTENNA_REPAIR_POST_DRT) @@ -491,6 +553,10 @@ configuration file. - [GND_NETS_VOLTAGES](#GND_NETS_VOLTAGES) - [MAX_ROUTING_LAYER](#MAX_ROUTING_LAYER) - [MIN_ROUTING_LAYER](#MIN_ROUTING_LAYER) +- [POST_DENSITY_FILL_TCL](#POST_DENSITY_FILL_TCL) +- [POST_FINAL_REPORT_TCL](#POST_FINAL_REPORT_TCL) +- [PRE_DENSITY_FILL_TCL](#PRE_DENSITY_FILL_TCL) +- [PRE_FINAL_REPORT_TCL](#PRE_FINAL_REPORT_TCL) - [PWR_NETS_VOLTAGES](#PWR_NETS_VOLTAGES) - [REPORT_CLOCK_SKEW](#REPORT_CLOCK_SKEW) - [ROUTING_LAYER_ADJUSTMENT](#ROUTING_LAYER_ADJUSTMENT) diff --git a/etc/DependencyInstaller.sh b/etc/DependencyInstaller.sh index ce71b18133..6ff8d911db 100755 --- a/etc/DependencyInstaller.sh +++ b/etc/DependencyInstaller.sh @@ -10,8 +10,12 @@ else fi # package versions -klayoutVersion=0.30.3 -numThreads=$(nproc) +klayoutVersion=0.30.7 +if [[ "$OSTYPE" == "darwin"* ]]; then + numThreads=$(sysctl -n hw.logicalcpu) +else + numThreads=$(nproc) +fi _versionCompare() { local a b IFS=. ; set -f @@ -40,10 +44,13 @@ _installPipCommon() { fi } +_installPipSystem() { + apt-get -y install python3-pandas python3-numpy python3-click python3-yaml python3-yamlfix +} + # Enterprise Linux 7 cleanup _install_EL7_CleanUp() { yum clean -y all - rm -rf /var/lib/apt/lists/* } # Enterprise Linux 7 package installation (EL7 = RHEL 7 or CentOS 7) @@ -72,7 +79,6 @@ _install_EL7_Packages() { # Enterprise Linux 8/9 cleanup _install_EL8_EL9_CleanUp() { dnf clean -y all - rm -rf /var/lib/apt/lists/* } # Enterprise Linux 8/9 package installation (EL8/EL9 = RHEL, Rocky Linux, AlmaLinux, or CentOS 8 as no CentOS 9 exists) @@ -152,19 +158,25 @@ _installUbuntuPackages() { apt-get -y update apt-get -y install --no-install-recommends \ bison \ + capnproto \ curl \ flex \ help2man \ + libboost-iostreams-dev \ + libcapnp-dev \ libfl-dev \ libfl2 \ libgit2-dev \ libgoogle-perftools-dev \ + libgtest-dev \ libqt5multimediawidgets5 \ libqt5opengl5 \ libqt5svg5-dev \ libqt5xmlpatterns5-dev \ + libtbb-dev \ libz-dev \ perl \ + pkg-config \ python3-pip \ python3-venv \ qtmultimedia5-dev \ @@ -189,8 +201,6 @@ _installUbuntuPackages() { # install KLayout if [[ $1 == "rodete" ]]; then apt-get -y install --no-install-recommends klayout python3-pandas - elif _versionCompare "$1" -ge 23.04; then - apt-get -y install --no-install-recommends klayout python3-pandas else arch=$(uname -m) lastDir="$(pwd)" @@ -211,13 +221,13 @@ _installUbuntuPackages() { fi else if [[ $1 == 20.04 ]]; then - klayoutChecksum=e83be08033f2f69d83ab7bd494a7a858 + klayoutChecksum=e95175a8053d3577375fbd3a7b3d7dbf elif [[ $1 == 22.04 ]]; then - klayoutChecksum=6e431b0a1a34c16eab9958a2c28f88bd + klayoutChecksum=202530d198b0c7b93aa5af0e8e438ccd elif [[ $1 == 24.04 ]]; then - klayoutChecksum=2d186f0225dbac7ae2d790aa8fa57814 + klayoutChecksum=145adaa044101bb41179aa63ec6d7f86 else - echo "Unrecognized version of Ubuntu $1. Please install KLayout manually" + echo "Unsupported Ubuntu version $1. Supported versions: 20.04, 22.04, 24.04. Please upgrade to a supported LTS release or install KLayout ${klayoutVersion} manually from https://www.klayout.org/build.html" exit 1 fi wget https://www.klayout.org/downloads/Ubuntu-${1%.*}/klayout_${klayoutVersion}-1_amd64.deb @@ -274,10 +284,7 @@ _installCI() { coreutils \ curl \ python3 \ - software-properties-common \ - clang pkg-config \ - libboost-dev libfl-dev libtbb-dev capnproto libcapnp-dev \ - libgtest-dev libspdlog-dev libfmt-dev libboost-iostreams-dev zlib1g-dev + software-properties-common } _help() { @@ -363,6 +370,9 @@ while [ "$#" -gt 0 ]; do CI="yes" OR_INSTALLER_ARGS="${OR_INSTALLER_ARGS} -save-deps-prefixes=/etc/openroad_deps_prefixes.txt" ;; + -save-deps-prefixes=*) + OR_INSTALLER_ARGS="${OR_INSTALLER_ARGS} $1" + ;; -yosys-ver=*) YOSYS_VER=${1#*=} ;; @@ -421,7 +431,7 @@ case "${os}" in if [[ ${CI} == "yes" ]]; then echo "WARNING: Installing CI dependencies is only supported on Ubuntu 22.04" >&2 fi - + # Detect EL version to choose appropriate functions if [[ -f /etc/os-release ]]; then elVersion=$(awk -F= '/^VERSION_ID/{print $2}' /etc/os-release | sed 's/"//g' | cut -d. -f1) @@ -429,10 +439,10 @@ case "${os}" in echo "ERROR: Could not detect Enterprise Linux version" >&2 exit 1 fi - + # First install OpenROAD base _installORDependencies - + # Determine between EL7 vs EL8/9, since yum vs dnf should be used, and different Klayout builds exist case "${elVersion}" in "7") @@ -454,7 +464,7 @@ case "${os}" in exit 1 ;; esac - + if [[ "${option}" == "common" || "${option}" == "all" ]]; then _installPipCommon fi @@ -473,14 +483,18 @@ case "${os}" in _installUbuntuPackages "${version}" _installUbuntuCleanUp fi - if [[ "${option}" == "common" || "${option}" == "all" ]]; then - if [[ $version != "rodete" ]]; then + if [[ $version != "rodete" ]]; then + if [[ "${option}" == "common" || "${option}" == "all" ]]; then if _versionCompare ${version} -lt 23.04 ; then _installPipCommon + else + if [[ "${option}" == "base" || "${option}" == "all" ]]; then + _installPipSystem + fi fi - else - echo "Skip common for rodete" fi + else + echo "Skip pip packages for rodete" fi ;; "Darwin" ) diff --git a/etc/DockerHelper.sh b/etc/DockerHelper.sh index 1eb0acca56..1d31edbb69 100755 --- a/etc/DockerHelper.sh +++ b/etc/DockerHelper.sh @@ -35,6 +35,7 @@ usage: $0 [CMD] [OPTIONS] -dry-run Do not push images to the repository -push-latest Push the latest image to the repository -no-constant-build-dir Do not use constant build directory + -buildArgs= Additional build arguments to pass to docker buildx -h -help Show this message and exits EOF @@ -64,7 +65,7 @@ _setup() { "builder" | "master") fromImage="${FROM_IMAGE_OVERRIDE:-"${org}/flow-${os}-dev"}:${imageTag}" context="." - buildArgs="--build-arg numThreads=${numThreads}" + buildArgs+=" --build-arg numThreads=${numThreads}" orVersion=$(git -C tools/OpenROAD describe --tags) echo "OpenROAD version: ${orVersion}" buildArgs+=" --build-arg openroadVersion=${orVersion}" @@ -76,7 +77,7 @@ _setup() { local yosys_ver yosys_ver=v$(grep 'yosys_ver =' tools/yosys/docs/source/conf.py | awk -F'"' '{print $2}') options+=" -yosys-ver=${yosys_ver}" - buildArgs="--build-arg \"options=${options}\" ${noConstantBuildDir}" + buildArgs+=" --build-arg \"options=${options}\" ${noConstantBuildDir}" ;; *) echo "Target ${target} not found" >&2 @@ -84,7 +85,7 @@ _setup() { ;; esac imagePath="${imageName}:${imageTag}" - buildArgs="--build-arg fromImage=${fromImage} ${buildArgs}" + buildArgs+=" ${buildArgs} --build-arg fromImage=${fromImage}" file="docker/Dockerfile.${target}" } @@ -191,7 +192,7 @@ os="ubuntu22.04" target="dev" numThreads="-1" tag="" -options="" +buildArgs="" dryRun=0 pushLatest=0 @@ -201,7 +202,7 @@ while [ "$#" -gt 0 ]; do _help 0 ;; -ci ) - options="-ci" + options+=" -ci" ;; -dry-run ) dryRun=1 @@ -227,6 +228,9 @@ while [ "$#" -gt 0 ]; do -tag=* ) tag="${1#*=}" ;; + -buildArgs=* ) + buildArgs="${1#*=}" + ;; -no-constant-build-dir ) noConstantBuildDir="--build-arg constantBuildDir= " ;; diff --git a/flow/Makefile b/flow/Makefile index f18ca938d7..462d37bb04 100644 --- a/flow/Makefile +++ b/flow/Makefile @@ -88,7 +88,7 @@ DESIGN_CONFIG ?= ./designs/nangate45/gcd/config.mk export DESIGN_CONFIG include $(DESIGN_CONFIG) -export DESIGN_DIR ?= $(dir $(DESIGN_CONFIG)) +export DESIGN_DIR ?= $(patsubst %/,%,$(dir $(DESIGN_CONFIG))) # default value "base" for FLOW_VARIANT and "." for WORK_HOME are duplicated # from variables.yaml and variables.mk because we need it @@ -195,21 +195,25 @@ $(OBJECTS_DIR)/klayout.lyt: $(KLAYOUT_TECH_FILE) $(OBJECTS_DIR)/klayout_tech.lef .PHONY: do-klayout do-klayout: -ifeq ($(KLAYOUT_ENV_VAR_IN_PATH),valid) - SC_LEF_RELATIVE_PATH="$(shell realpath --relative-to=$(RESULTS_DIR) $(SC_LEF))"; \ - OTHER_LEFS_RELATIVE_PATHS=$$(echo "$(foreach file, $(OBJECTS_DIR)/klayout_tech.lef $(ADDITIONAL_LEFS),$$(realpath --relative-to=$(RESULTS_DIR) $(file)))"); \ - sed 's,.*,'"$$SC_LEF_RELATIVE_PATH"''"$$OTHER_LEFS_RELATIVE_PATHS"',g' $(KLAYOUT_TECH_FILE) > $(OBJECTS_DIR)/klayout.lyt -else - sed 's,.*,$(foreach file, $(OBJECTS_DIR)/klayout_tech.lef $(SC_LEF) $(ADDITIONAL_LEFS),$(shell realpath --relative-to=$(RESULTS_DIR) $(file))),g' $(KLAYOUT_TECH_FILE) > $(OBJECTS_DIR)/klayout.lyt -endif - sed -i 's,.*,$(foreach file, $(FLOW_HOME)/platforms/$(PLATFORM)/*map,$(shell realpath $(file))),g' $(OBJECTS_DIR)/klayout.lyt + @mkdir -p $(dir $(OBJECTS_DIR)/klayout.lyt) + $(PYTHON_EXE) $(UTILS_DIR)/generate_klayout_tech.py \ + --template $(KLAYOUT_TECH_FILE) \ + --output $(OBJECTS_DIR)/klayout.lyt \ + --lef-files $(OBJECTS_DIR)/klayout_tech.lef $(SC_LEF) $(ADDITIONAL_LEFS) \ + --reference-dir $(RESULTS_DIR) \ + --map-files $(wildcard $(FLOW_HOME)/platforms/$(PLATFORM)/*map) $(OBJECTS_DIR)/klayout_wrap.lyt: $(KLAYOUT_TECH_FILE) $(OBJECTS_DIR)/klayout_tech.lef $(UNSET_AND_MAKE) do-klayout_wrap .PHONY: do-klayout_wrap do-klayout_wrap: - sed 's,.*,$(foreach file, $(OBJECTS_DIR)/klayout_tech.lef $(WRAP_LEFS),$(shell realpath --relative-to=$(OBJECTS_DIR)/def $(file))),g' $(KLAYOUT_TECH_FILE) > $(OBJECTS_DIR)/klayout_wrap.lyt + @mkdir -p $(dir $(OBJECTS_DIR)/klayout_wrap.lyt) + $(PYTHON_EXE) $(UTILS_DIR)/generate_klayout_tech.py \ + --template $(KLAYOUT_TECH_FILE) \ + --output $(OBJECTS_DIR)/klayout_wrap.lyt \ + --lef-files $(OBJECTS_DIR)/klayout_tech.lef $(WRAP_LEFS) \ + --reference-dir $(OBJECTS_DIR)/def $(WRAPPED_LEFS): mkdir -p $(OBJECTS_DIR)/lef $(OBJECTS_DIR)/def @@ -627,7 +631,7 @@ final: finish .PHONY: do-finish do-finish: - $(UNSET_AND_MAKE) do-6_1_fill do-6_1_fill.sdc do-6_final.sdc do-6_report do-gds elapsed + $(UNSET_AND_MAKE) do-6_1_fill do-6_1_fill.sdc do-6_final.sdc do-6_report elapsed .PHONY: generate_abstract generate_abstract: $(RESULTS_DIR)/6_final.gds $(RESULTS_DIR)/6_final.def $(RESULTS_DIR)/6_final.v $(RESULTS_DIR)/6_final.sdc @@ -643,6 +647,17 @@ do-generate_abstract: clean_abstract: rm -f $(RESULTS_DIR)/$(DESIGN_NAME).lib $(RESULTS_DIR)/$(DESIGN_NAME).lef +.PHONY: check-klayout +check-klayout: + @if [ -z "$(KLAYOUT_CMD)" ]; then \ + echo "Error: KLayout not found. Install KLayout or set KLAYOUT_CMD."; \ + echo "Hint: KLayout is needed for GDS/DRC/LVS targets."; \ + exit 1; \ + fi + +.PHONY: gds +gds: $(GDS_FINAL_FILE) + # Merge wrapped macros using Klayout #------------------------------------------------------------------------------- $(WRAPPED_GDSOAS): $(OBJECTS_DIR)/klayout_wrap.lyt $(WRAPPED_LEFS) @@ -658,7 +673,7 @@ $(WRAPPED_GDSOAS): $(OBJECTS_DIR)/klayout_wrap.lyt $(WRAPPED_LEFS) # Merge GDS using Klayout #------------------------------------------------------------------------------- -$(GDS_MERGED_FILE): $(RESULTS_DIR)/6_final.def $(OBJECTS_DIR)/klayout.lyt $(GDSOAS_FILES) $(WRAPPED_GDSOAS) $(SEAL_GDSOAS) +$(GDS_MERGED_FILE): check-klayout $(RESULTS_DIR)/6_final.def $(OBJECTS_DIR)/klayout.lyt $(GDSOAS_FILES) $(WRAPPED_GDSOAS) $(SEAL_GDSOAS) $(UNSET_AND_MAKE) do-gds-merged .PHONY: do-gds-merged @@ -768,7 +783,7 @@ nuke: clean_test clean_issues # DEF/GDS/OAS viewer shortcuts #------------------------------------------------------------------------------- .PHONY: $(foreach file,$(RESULTS_DEF) $(RESULTS_GDS) $(RESULTS_OAS),klayout_$(file)) -$(foreach file,$(RESULTS_DEF) $(RESULTS_GDS) $(RESULTS_OAS),klayout_$(file)): klayout_%: $(OBJECTS_DIR)/klayout.lyt +$(foreach file,$(RESULTS_DEF) $(RESULTS_GDS) $(RESULTS_OAS),klayout_$(file)): klayout_%: check-klayout $(OBJECTS_DIR)/klayout.lyt $(SCRIPTS_DIR)/klayout.sh -nn $(OBJECTS_DIR)/klayout.lyt $(RESULTS_DIR)/$* $(eval $(call OPEN_GUI_SHORTCUT,synth,1_synth.odb)) diff --git a/flow/designs/asap7/aes-block/rules-base.json b/flow/designs/asap7/aes-block/rules-base.json index 3276e206cf..0d454b5e23 100644 --- a/flow/designs/asap7/aes-block/rules-base.json +++ b/flow/designs/asap7/aes-block/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -106.0, + "value": -78.0, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -3710.0, + "value": -2890.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -40,7 +40,7 @@ "compare": ">=" }, "cts__timing__hold__tns": { - "value": -5770.0, + "value": -5670.0, "compare": ">=" }, "globalroute__antenna_diodes_count": { @@ -48,23 +48,23 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -117.0, + "value": -77.7, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -3650.0, + "value": -3020.0, "compare": ">=" }, "globalroute__timing__hold__ws": { - "value": -22.5, + "value": -25.9, "compare": ">=" }, "globalroute__timing__hold__tns": { - "value": -508.0, + "value": -1080.0, "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 52736, + "value": 51873, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -66.7, + "value": -58.1, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -1290.0, + "value": -897.0, "compare": ">=" }, "finish__timing__hold__ws": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 7206, + "value": 7205, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/asap7/aes-mbff/rules-base.json b/flow/designs/asap7/aes-mbff/rules-base.json index 198be13ec2..08c173c711 100644 --- a/flow/designs/asap7/aes-mbff/rules-base.json +++ b/flow/designs/asap7/aes-mbff/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 1928.39, + "value": 1900.0, "compare": "<=" }, "constraints__clocks__count": { @@ -8,7 +8,7 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 2156, + "value": 2103, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -38.2, + "value": -28.8, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -1130.0, + "value": -164.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -49.6, + "value": -41.3, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -2370.0, + "value": -1010.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -41.6, + "value": -31.8, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -857.0, + "value": -235.0, "compare": ">=" }, "finish__timing__hold__ws": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 2254, + "value": 2206, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/asap7/aes/BUILD.bazel b/flow/designs/asap7/aes/BUILD.bazel deleted file mode 100644 index 2ff325bb42..0000000000 --- a/flow/designs/asap7/aes/BUILD.bazel +++ /dev/null @@ -1,47 +0,0 @@ -load("@bazel-orfs//:openroad.bzl", "orfs_flow", "orfs_synth") - -BLACKBOXES = [ - "aes_sbox", - "aes_key_expand_128", - "aes_cipher_top", -] - -[orfs_synth( - name = "{name}_netlist_synth".format(name = name), - arguments = { - "SDC_FILE": "$(location :constraint.sdc)", - "SYNTH_BLACKBOXES": " ".join([b for b in BLACKBOXES if b != name]), - }, - data = [":constraint.sdc"], - module_top = name, - variant = "netlist", - verilog_files = ["//flow/designs/src/aes:verilog"], -) for name in BLACKBOXES] - -[filegroup( - name = "{name}_netlist".format(name = name), - srcs = ["{name}_netlist_synth".format(name = name)], - output_group = "1_synth.v", -) for name in BLACKBOXES] - -filegroup( - name = "netlists", - srcs = [":{}_netlist".format(name) for name in BLACKBOXES], -) - -orfs_flow( - name = "aes_cipher_top", - arguments = { - "ABC_AREA": "1", - "CORE_UTILIZATION": "40", - "CORE_ASPECT_RATIO": "1", - "CORE_MARGIN": "2", - "PLACE_DENSITY": "0.65", - "TNS_END_PERCENT": "100", - }, - sources = { - "SDC_FILE": [":constraint.sdc"], - "SYNTH_NETLIST_FILES": [":netlists"], - }, - top = "aes_cipher_top", -) diff --git a/flow/designs/asap7/aes/config.mk b/flow/designs/asap7/aes/config.mk index 9dc285d86c..0d310cc6b8 100644 --- a/flow/designs/asap7/aes/config.mk +++ b/flow/designs/asap7/aes/config.mk @@ -8,7 +8,7 @@ export SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint. export ABC_AREA = 1 -export CORE_UTILIZATION = 40 +export CORE_UTILIZATION = 70 export CORE_ASPECT_RATIO = 1 export CORE_MARGIN = 2 export PLACE_DENSITY = 0.65 diff --git a/flow/designs/asap7/aes/rules-base.json b/flow/designs/asap7/aes/rules-base.json index aee5cc07ed..5d37adb92a 100644 --- a/flow/designs/asap7/aes/rules-base.json +++ b/flow/designs/asap7/aes/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 1928.39, + "value": 1900.0, "compare": "<=" }, "constraints__clocks__count": { @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 2162, + "value": 2032, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 19594, + "value": 19153, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,19 +20,19 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 1704, + "value": 1666, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 1704, + "value": 1666, "compare": "<=" }, "cts__timing__setup__ws": { - "value": -34.8, + "value": -28.8, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -1100.0, + "value": -164.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -47.4, + "value": -37.6, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -2170.0, + "value": -846.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 72539, + "value": 66246, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -42.2, + "value": -39.9, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -825.0, + "value": -384.0, "compare": ">=" }, "finish__timing__hold__ws": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 2269, + "value": 2108, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/asap7/aes_lvt/rules-base.json b/flow/designs/asap7/aes_lvt/rules-base.json index e5039648ab..2fb6b362f8 100644 --- a/flow/designs/asap7/aes_lvt/rules-base.json +++ b/flow/designs/asap7/aes_lvt/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 1920.63, + "value": 1910.0, "compare": "<=" }, "constraints__clocks__count": { @@ -8,7 +8,7 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 1978, + "value": 1954, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 2017, + "value": 1992, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/asap7/cva6/config.mk b/flow/designs/asap7/cva6/config.mk index 3882ee9347..355dba03aa 100644 --- a/flow/designs/asap7/cva6/config.mk +++ b/flow/designs/asap7/cva6/config.mk @@ -109,3 +109,5 @@ export CTS_LIB_NAME = asap7sc7p5t_INVBUF_SLVT_FF_nldm_211120 # Remove rvfi_probes_o interface export SYNTH_CANONICALIZE_TCL = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NAME)/canonicalize.tcl +export SWAP_ARITH_OPERATORS = 1 +export OPENROAD_HIERARCHICAL = 1 diff --git a/flow/designs/asap7/ethmac/rules-base.json b/flow/designs/asap7/ethmac/rules-base.json index 0f81ddda44..7db97e6cd6 100644 --- a/flow/designs/asap7/ethmac/rules-base.json +++ b/flow/designs/asap7/ethmac/rules-base.json @@ -12,7 +12,7 @@ "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 69423, + "value": 68920, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,19 +20,19 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 6037, + "value": 5993, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 6037, + "value": 5993, "compare": "<=" }, "cts__timing__setup__ws": { - "value": -114.0, + "value": -90.2, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -1710.0, + "value": -1360.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -128.0, + "value": -107.0, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -2160.0, + "value": -2140.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 243645, + "value": 241787, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -117.0, + "value": -102.0, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -1800.0, + "value": -1630.0, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/asap7/ethmac_lvt/BUILD.bazel b/flow/designs/asap7/ethmac_lvt/BUILD.bazel deleted file mode 100644 index 6bc3354348..0000000000 --- a/flow/designs/asap7/ethmac_lvt/BUILD.bazel +++ /dev/null @@ -1,24 +0,0 @@ -load("@bazel-orfs//:openroad.bzl", "orfs_flow") - -orfs_flow( - name = "ethmac_lvt", - arguments = { - # Faster builds - "SKIP_INCREMENTAL_REPAIR": "1", - "GPL_TIMING_DRIVEN": "0", - # Various - "SDC_FILE": "$(location :constraint.sdc)", - "ABC_AREA": "1", - "CORE_UTILIZATION": "40", - "CORE_ASPECT_RATIO": "1", - "CORE_MARGIN": "2", - "PLACE_DENSITY": "0.60", - "ASAP7_USE_VT": "LVT", - "RECOVER_POWER": "1", - }, - sources = { - "SDC_FILE": [":constraint.sdc"], - }, - top = "ethmac", - verilog_files = ["//flow/designs/src/ethmac_lvt:verilog"], -) diff --git a/flow/designs/asap7/ethmac_lvt/rules-base.json b/flow/designs/asap7/ethmac_lvt/rules-base.json index 1e3ce0a680..3f6b71c8b5 100644 --- a/flow/designs/asap7/ethmac_lvt/rules-base.json +++ b/flow/designs/asap7/ethmac_lvt/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -62.7, + "value": -21.7, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -907.0, + "value": -113.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -70.3, + "value": -28.9, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -1130.0, + "value": -263.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -56.5, + "value": -19.6, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -904.0, + "value": -94.2, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/asap7/gcd-ccs/rules-base.json b/flow/designs/asap7/gcd-ccs/rules-base.json index 102e04c4e8..990e39d816 100644 --- a/flow/designs/asap7/gcd-ccs/rules-base.json +++ b/flow/designs/asap7/gcd-ccs/rules-base.json @@ -12,7 +12,7 @@ "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 520, + "value": 489, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,19 +20,19 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 45, + "value": 42, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 44, + "value": 42, "compare": "<=" }, "cts__timing__setup__ws": { - "value": -33.8, + "value": -21.3, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -103.0, + "value": -67.8, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -33.8, + "value": -15.5, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -102.0, + "value": -62.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 1358, + "value": 925, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -56.6, + "value": -37.9, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -324.0, + "value": -180.0, "compare": ">=" }, "finish__timing__hold__ws": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 54, + "value": 53, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/asap7/gcd/asap7_gcd_sweep.yaml b/flow/designs/asap7/gcd/asap7_gcd_sweep.yaml new file mode 100644 index 0000000000..8ee0d4c056 --- /dev/null +++ b/flow/designs/asap7/gcd/asap7_gcd_sweep.yaml @@ -0,0 +1,18 @@ +run_config: + design: gcd + experiment: freq + flow_home: /OpenROAD-flow-scripts/flow + jobs: 3 + mode: sweep + platform: asap7 + ray_outputs_dir: /work + orfs_outputs_dir: /work +search_space: + _SDC_FILE_PATH: + type: constant + value: /OpenROAD-flow-scripts/flow/designs/asap7/gcd/constraint.sdc + _SDC_CLK_PERIOD: + type: range_int + min: 200 + max: 500 + step: 50 diff --git a/flow/designs/asap7/gcd/asap7_gcd_tune.yaml b/flow/designs/asap7/gcd/asap7_gcd_tune.yaml new file mode 100644 index 0000000000..63e3b864d1 --- /dev/null +++ b/flow/designs/asap7/gcd/asap7_gcd_tune.yaml @@ -0,0 +1,13 @@ +run_config: + design: gcd + experiment: basic + flow_home: /OpenROAD-flow-scripts/flow + jobs: 3 + mode: tune + platform: asap7 + ray_outputs_dir: /work + orfs_outputs_dir: /work + samples: 10 + timeout: 1.0 +search_space: + file: designs/asap7/gcd/autotuner_new.json diff --git a/flow/designs/asap7/gcd/autotuner_new.json b/flow/designs/asap7/gcd/autotuner_new.json new file mode 100644 index 0000000000..25df4e73e4 --- /dev/null +++ b/flow/designs/asap7/gcd/autotuner_new.json @@ -0,0 +1,46 @@ +{ + "_SDC_FILE_PATH": "constraint.sdc", + "_SDC_CLK_PERIOD": { + "type": "range_float", + "min": 200, + "max": 500, + "step": 0 + }, + "CELL_PAD_IN_SITES_GLOBAL_PLACEMENT": { + "type": "range_int", + "min": 0, + "max": 3, + "step": 1 + }, + "CELL_PAD_IN_SITES_DETAIL_PLACEMENT": { + "type": "range_int", + "min": 0, + "max": 3, + "step": 1 + }, + "_FR_LAYER_ADJUST": { + "type": "range_float", + "min": 0.1, + "max": 0.3, + "step": 0 + }, + "PLACE_DENSITY_LB_ADDON": { + "type": "range_float", + "min": 0.0, + "max": 0.2, + "step": 0 + }, + "CTS_CLUSTER_SIZE": { + "type": "range_int", + "min": 10, + "max": 200, + "step": 1 + }, + "CTS_CLUSTER_DIAMETER": { + "type": "range_int", + "min": 20, + "max": 400, + "step": 1 + }, + "_FR_FILE_PATH": "fastroute.tcl" +} \ No newline at end of file diff --git a/flow/designs/asap7/gcd/config.mk b/flow/designs/asap7/gcd/config.mk index 8bfb86c8e2..c98498e7a8 100644 --- a/flow/designs/asap7/gcd/config.mk +++ b/flow/designs/asap7/gcd/config.mk @@ -5,8 +5,9 @@ export DESIGN_NAME = gcd export VERILOG_FILES = $(sort $(wildcard $(DESIGN_HOME)/src/$(DESIGN_NAME)/*.v)) export SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NAME)/constraint.sdc -export DIE_AREA = 0 0 16.2 16.2 -export CORE_AREA = 1.08 1.08 15.12 15.12 +export CORE_UTILIZATION = 65 +export CORE_ASPECT_RATIO = 1 +export CORE_MARGIN = 0.5 # The goal of this design is to have a smoketest that builds quickly, # that said, this design will go through grt with a 0.99 placement density. export PLACE_DENSITY = 0.35 diff --git a/flow/designs/asap7/gcd/rules-base.json b/flow/designs/asap7/gcd/rules-base.json index 5b577397e3..b8a5a4a404 100644 --- a/flow/designs/asap7/gcd/rules-base.json +++ b/flow/designs/asap7/gcd/rules-base.json @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 52, + "value": 50, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 531, + "value": 473, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,19 +20,19 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 47, + "value": 41, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 46, + "value": 41, "compare": "<=" }, "cts__timing__setup__ws": { - "value": -53.6, + "value": -29.6, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -281.0, + "value": -119.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -64.0, + "value": -39.7, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -439.0, + "value": -225.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 1352, + "value": 1006, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -48.6, + "value": -32.2, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -270.0, + "value": -141.0, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/asap7/ibex/asap7_ibex_sweep.yaml b/flow/designs/asap7/ibex/asap7_ibex_sweep.yaml new file mode 100644 index 0000000000..05108af5e5 --- /dev/null +++ b/flow/designs/asap7/ibex/asap7_ibex_sweep.yaml @@ -0,0 +1,19 @@ +run_config: + design: ibex + experiment: freq + flow_home: /OpenROAD-flow-scripts/flow + jobs: 2 + mode: sweep + platform: asap7 + ray_outputs_dir: /work + orfs_outputs_dir: /work +search_space: + _SDC_FILE_PATH: + type: constant + value: /OpenROAD-flow-scripts/flow/designs/asap7/ibex/constraint.sdc + _SDC_CLK_PERIOD: + type: range_int + min: 950 + max: 1050 + step: 10 + diff --git a/flow/designs/asap7/ibex/asap7_ibex_tune.yaml b/flow/designs/asap7/ibex/asap7_ibex_tune.yaml new file mode 100644 index 0000000000..104dc32385 --- /dev/null +++ b/flow/designs/asap7/ibex/asap7_ibex_tune.yaml @@ -0,0 +1,12 @@ +run_config: + design: ibex + experiment: basic + flow_home: /OpenROAD-flow-scripts/flow + jobs: 2 + mode: tune + samples: 5 + platform: asap7 + ray_outputs_dir: /work + orfs_outputs_dir: /work +search_space: + file: designs/asap7/ibex/autotuner_new.json diff --git a/flow/designs/asap7/ibex/autotuner_new.json b/flow/designs/asap7/ibex/autotuner_new.json new file mode 100644 index 0000000000..1921e7598b --- /dev/null +++ b/flow/designs/asap7/ibex/autotuner_new.json @@ -0,0 +1,58 @@ +{ + "_SDC_FILE_PATH": "designs/asap7/ibex/constraint.sdc", + "_SDC_CLK_PERIOD": { + "type": "range_int", + "step": 0, + "min": 1200, + "max": 2000 + }, + "CORE_UTILIZATION": { + "type": "range_int", + "step": 1, + "min": 5, + "max": 10 + }, + "CORE_ASPECT_RATIO": { + "type": "range_float", + "step": 0, + "min": 0.9, + "max": 1.1 + }, + "CELL_PAD_IN_SITES_GLOBAL_PLACEMENT": { + "type": "range_int", + "step": 1, + "min": 0, + "max": 3 + }, + "CELL_PAD_IN_SITES_DETAIL_PLACEMENT": { + "type": "range_int", + "step": 1, + "min": 0, + "max": 3 + }, + "_FR_LAYER_ADJUST": { + "type": "range_float", + "step": 0, + "min": 0.0, + "max": 0.1 + }, + "PLACE_DENSITY_LB_ADDON": { + "type": "range_float", + "step": 0, + "min": 0.0, + "max": 0.2 + }, + "CTS_CLUSTER_SIZE": { + "type": "range_int", + "step": 1, + "min": 10, + "max": 200 + }, + "CTS_CLUSTER_DIAMETER": { + "type": "range_int", + "step": 1, + "min": 20, + "max": 400 + }, + "_FR_FILE_PATH": "" +} diff --git a/flow/designs/asap7/ibex/config.mk b/flow/designs/asap7/ibex/config.mk index a6a0b94a2e..419c77f8c3 100644 --- a/flow/designs/asap7/ibex/config.mk +++ b/flow/designs/asap7/ibex/config.mk @@ -31,5 +31,3 @@ export TNS_END_PERCENT = 100 export SWAP_ARITH_OPERATORS = 1 export OPENROAD_HIERARCHICAL = 1 -export LEC_CHECK = 0 - diff --git a/flow/designs/asap7/ibex/rules-base.json b/flow/designs/asap7/ibex/rules-base.json index 4ea1cb0ccc..fb2ed8ed93 100644 --- a/flow/designs/asap7/ibex/rules-base.json +++ b/flow/designs/asap7/ibex/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -139.0, + "value": -79.4, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -48300.0, + "value": -442.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -151.0, + "value": -87.4, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -82000.0, + "value": -592.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -125.0, + "value": -69.1, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -46500.0, + "value": -286.0, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/asap7/jpeg/config.mk b/flow/designs/asap7/jpeg/config.mk index 7a229fa0cf..e7bd41a42f 100644 --- a/flow/designs/asap7/jpeg/config.mk +++ b/flow/designs/asap7/jpeg/config.mk @@ -17,6 +17,4 @@ export TNS_END_PERCENT = 100 export EQUIVALENCE_CHECK ?= 1 export REMOVE_CELLS_FOR_EQY = TAPCELL* -export LEC_CHECK = 0 - diff --git a/flow/designs/asap7/mock-alu/config.mk b/flow/designs/asap7/mock-alu/config.mk index 455da4d370..c8054db41e 100644 --- a/flow/designs/asap7/mock-alu/config.mk +++ b/flow/designs/asap7/mock-alu/config.mk @@ -11,5 +11,3 @@ export ROUTING_LAYER_ADJUSTMENT = 0.45 export SWAP_ARITH_OPERATORS = 1 export OPENROAD_HIERARCHICAL = 1 -export LEC_CHECK = 0 - diff --git a/flow/designs/asap7/mock-alu/rules-base.json b/flow/designs/asap7/mock-alu/rules-base.json index 6de35a7d79..41d7e8aa44 100644 --- a/flow/designs/asap7/mock-alu/rules-base.json +++ b/flow/designs/asap7/mock-alu/rules-base.json @@ -8,7 +8,7 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 1808, + "value": 1790, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { @@ -32,7 +32,7 @@ "compare": ">=" }, "cts__timing__setup__tns": { - "value": -18100.0, + "value": -13200.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -52,7 +52,7 @@ "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -21700.0, + "value": -15100.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -84,7 +84,7 @@ "compare": ">=" }, "finish__timing__setup__tns": { - "value": -18600.0, + "value": -13000.0, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/asap7/mock-cpu/constraint.sdc b/flow/designs/asap7/mock-cpu/constraint.sdc index 4648916e35..a7f3b609e2 100644 --- a/flow/designs/asap7/mock-cpu/constraint.sdc +++ b/flow/designs/asap7/mock-cpu/constraint.sdc @@ -2,7 +2,7 @@ # # This fifo is from http://www.sunburst-design.com/papers/CummingsSNUG2002SJ_FIFO1.pdf -source designs/src/mock-array/util.tcl +source $::env(DESIGN_HOME)/src/mock-array/util.tcl set sdc_version 2.0 diff --git a/flow/designs/asap7/mock-cpu/rules-base.json b/flow/designs/asap7/mock-cpu/rules-base.json index fa1aefe3a0..008068335e 100644 --- a/flow/designs/asap7/mock-cpu/rules-base.json +++ b/flow/designs/asap7/mock-cpu/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -103.0, + "value": -89.5, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -2070.0, + "value": -1430.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -104.0, + "value": -90.9, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -2350.0, + "value": -1780.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -97.7, + "value": -84.6, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -2230.0, + "value": -1670.0, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/asap7/riscv32i-mock-sram/rules-base.json b/flow/designs/asap7/riscv32i-mock-sram/rules-base.json index fe47b8735d..fe4797062a 100644 --- a/flow/designs/asap7/riscv32i-mock-sram/rules-base.json +++ b/flow/designs/asap7/riscv32i-mock-sram/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 1640.0, + "value": 1570.0, "compare": "<=" }, "constraints__clocks__count": { @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -50.0, + "value": -47.5, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -693.0, + "value": -190.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -95.7, + "value": -56.5, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -1700.0, + "value": -209.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 72999, + "value": 65578, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -106.0, + "value": -66.8, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -12300.0, + "value": -363.0, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/asap7/riscv32i/config.mk b/flow/designs/asap7/riscv32i/config.mk index d148ad51c9..6b4175b16a 100644 --- a/flow/designs/asap7/riscv32i/config.mk +++ b/flow/designs/asap7/riscv32i/config.mk @@ -10,8 +10,8 @@ export VERILOG_FILES = $(sort $(wildcard $(DESIGN_HOME)/src/riscv32i/*.v)) export SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/riscv32i/constraint.sdc ifeq ($(BLOCKS),) - export ADDITIONAL_LEFS = ./platforms/$(PLATFORM)/lef/fakeram7_256x32.lef - export ADDITIONAL_LIBS = $(LIB_DIR)/fakeram7_256x32.lib + export ADDITIONAL_LEFS = $(PLATFORM_DIR)/lef/fakeram7_256x32.lef + export ADDITIONAL_LIBS = $(PLATFORM_DIR)/lib/NLDM/fakeram7_256x32.lib endif export CORE_UTILIZATION = 62 diff --git a/flow/designs/asap7/riscv32i/rules-base.json b/flow/designs/asap7/riscv32i/rules-base.json index e71b73a916..763594330b 100644 --- a/flow/designs/asap7/riscv32i/rules-base.json +++ b/flow/designs/asap7/riscv32i/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -117.0, + "value": -51.1, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -23200.0, + "value": -220.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -100.0, + "value": -60.9, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -19800.0, + "value": -1010.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 70494, + "value": 67276, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -84,7 +84,7 @@ "compare": ">=" }, "finish__timing__setup__tns": { - "value": -4450.0, + "value": -261.0, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/asap7/swerv_wrapper/BUILD.bazel b/flow/designs/asap7/swerv_wrapper/BUILD.bazel deleted file mode 100644 index e97eee723b..0000000000 --- a/flow/designs/asap7/swerv_wrapper/BUILD.bazel +++ /dev/null @@ -1,118 +0,0 @@ -load("@bazel-orfs//:openroad.bzl", "orfs_flow", "orfs_macro", "orfs_synth") - -FAKERAMS = [ - "fakeram7_64x21", - "fakeram7_256x34", - "fakeram7_2048x39", -] - -# BLACKBOXES are those listed in SYNTH_HIERARCHICAL=1 -# -# 33.1. IC_DATA_ICACHE_TAG_HIGH12_ICACHE_TAG_LOW6_ICACHE_IC_DEPTH8' to `/input.blif'.. - -BLACKBOXES = [ - "IC_TAG_ICACHE_TAG_HIGH12_ICACHE_TAG_LOW6_ICACHE_TAG_DEPTH64", - "dbg", - "dec_decode_ctl", - "dec_gpr_ctl_GPR_BANKS1_GPR_BANKS_LOG21", - "dec_ib_ctl", - "dec_tlu_ctl", - "dec_trigger", - "dma_ctrl", - "exu_alu_ctl", - "ifu_aln_ctl", - "ifu_bp_ctl", - "ifu_ifc_ctl", - "ifu_mem_ctl", - "lsu_bus_intf", - "lsu_dccm_ctl", - "lsu_ecc", - "lsu_lsc_ctl", - "lsu_stbuf", - "lsu_trigger", - "pic_ctrl", - "ram_256x34", - # When run with SYNTH_HIERARCHICAL=1, which should not be used here, - # the error below is produced. - # - # ERROR: Missing cost information on instanced blackbox lsu_dccm_mem - "lsu_dccm_mem", - "exu_div_ctl", - "lsu_bus_buffer", - "ram_2048x39", - "exu", - "swerv_wrapper", -] - -[orfs_synth( - name = "{name}_netlist_synth".format(name = name), - arguments = { - "SDC_FILE": "$(location :constraint.sdc)", - "SYNTH_BLACKBOXES": " ".join([b for b in BLACKBOXES if b != name]), - "SYNTH_HIERARCHICAL": "0", - }, - data = [":constraint.sdc"], - module_top = name, - variant = "netlist", - verilog_files = [ - "macros.v", - "//flow/designs/src/swerv:verilog", - ], - deps = FAKERAMS, -) for name in BLACKBOXES] - -[filegroup( - name = "{name}_netlist".format(name = name), - srcs = ["{name}_netlist_synth".format(name = name)], - output_group = "1_synth.v", -) for name in BLACKBOXES] - -# ca. 540 seconds for sequential synthesis, vs 90 seconds for netlist synthesis. -filegroup( - name = "netlists", - srcs = [":{}_netlist".format(name) for name in BLACKBOXES], -) - -# Canonicalize the netlists to avoid rebuilds unecessarily. -# -# This is more a demonstration than a practical solution. -# -# Other things could be done here, like get a netlist from git lfs, -# process the netlist in some other way, with Naja, etc. -genrule( - name = "netlists_canonicalized", - srcs = [":netlists"], - outs = ["netlists_canonicalized.v"], - cmd = """ - cat $(locations :netlists) | grep -v -E '\\(\\* src = "|Generated by Yosys' > $@ - """, -) - -[orfs_macro( - name = top, - lef = "lef/{}.lef".format(top), - lib = "lib/{}.lib".format(top), - module_top = top, -) for top in FAKERAMS] - -orfs_flow( - name = "swerv_wrapper", - arguments = { - "LIB_MODEL": "CCS", - "SYNTH_HIERARCHICAL": "1", - "DIE_AREA": "0 0 550 600", - "CORE_AREA": "5 5 545 595", - "PLACE_PINS_ARGS": "-exclude left:* -exclude right:*", - "PLACE_DENSITY_LB_ADDON": "0.20", - "TNS_END_PERCENT": "100", - "PWR_NETS_VOLTAGEsS": "", - "GND_NETS_VOLTAGES": "", - }, - macros = FAKERAMS, - sources = { - "SDC_FILE": [":constraint.sdc"], - "SYNTH_NETLIST_FILES": [":netlists_canonicalized"], - }, - tags = ["manual"], - verilog_files = [], -) diff --git a/flow/designs/asap7/swerv_wrapper/config.mk b/flow/designs/asap7/swerv_wrapper/config.mk index 7316e10210..97410ab479 100644 --- a/flow/designs/asap7/swerv_wrapper/config.mk +++ b/flow/designs/asap7/swerv_wrapper/config.mk @@ -51,8 +51,7 @@ export SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/swerv_wrapper/constraint.sdc export ADDITIONAL_LEFS = $(sort $(wildcard $(DESIGN_HOME)/$(PLATFORM)/swerv_wrapper/lef/*.lef)) export ADDITIONAL_LIBS = $(sort $(wildcard $(DESIGN_HOME)/$(PLATFORM)/swerv_wrapper/lib/*.lib)) -export DIE_AREA = 0 0 550 600 -export CORE_AREA = 5 5 545 595 +export CORE_UTILIZATION = 30 export IO_CONSTRAINTS = $(DESIGN_HOME)/$(PLATFORM)/swerv_wrapper/io.tcl export PLACE_DENSITY_LB_ADDON = 0.20 @@ -62,5 +61,3 @@ export ROUTING_LAYER_ADJUSTMENT = 0.2 export SWAP_ARITH_OPERATORS = 1 export OPENROAD_HIERARCHICAL = 1 -export LEC_CHECK = 0 - diff --git a/flow/designs/asap7/swerv_wrapper/rules-base.json b/flow/designs/asap7/swerv_wrapper/rules-base.json index 87721c47d8..6a509049e7 100644 --- a/flow/designs/asap7/swerv_wrapper/rules-base.json +++ b/flow/designs/asap7/swerv_wrapper/rules-base.json @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 55786, + "value": 55101, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 167763, + "value": 156615, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,11 +20,11 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 14588, + "value": 13619, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 14588, + "value": 13619, "compare": "<=" }, "cts__timing__setup__ws": { @@ -44,7 +44,7 @@ "compare": ">=" }, "globalroute__antenna_diodes_count": { - "value": 118, + "value": 117, "compare": "<=" }, "globalroute__timing__setup__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 1711340, + "value": 1483815, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -76,27 +76,27 @@ "compare": "<=" }, "detailedroute__antenna_diodes_count": { - "value": 118, + "value": 117, "compare": "<=" }, "finish__timing__setup__ws": { - "value": -160.0, + "value": -276.0, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -7230.0, + "value": -11700.0, "compare": ">=" }, "finish__timing__hold__ws": { - "value": -200.0, + "value": -134.0, "compare": ">=" }, "finish__timing__hold__tns": { - "value": -125000.0, + "value": -11000.0, "compare": ">=" }, "finish__design__instance__area": { - "value": 56249, + "value": 55530, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/asap7/uart/rules-base.json b/flow/designs/asap7/uart/rules-base.json index 41a1e745d0..fff05ed184 100644 --- a/flow/designs/asap7/uart/rules-base.json +++ b/flow/designs/asap7/uart/rules-base.json @@ -32,7 +32,7 @@ "compare": ">=" }, "cts__timing__setup__tns": { - "value": -927.0, + "value": -756.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -52,7 +52,7 @@ "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -1640.0, + "value": -1360.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 2030, + "value": 1673, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -84,7 +84,7 @@ "compare": ">=" }, "finish__timing__setup__tns": { - "value": -1030.0, + "value": -690.0, "compare": ">=" }, "finish__timing__hold__ws": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 119, + "value": 109, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/gf12/ariane/config.mk b/flow/designs/gf12/ariane/config.mk index fe50cb930c..4a8e331a21 100644 --- a/flow/designs/gf12/ariane/config.mk +++ b/flow/designs/gf12/ariane/config.mk @@ -37,5 +37,3 @@ export REMOVE_ABC_BUFFERS = 1 export SWAP_ARITH_OPERATORS = 1 export OPENROAD_HIERARCHICAL = 1 - -export LEC_CHECK = 0 diff --git a/flow/designs/gf12/ariane/rules-base.json b/flow/designs/gf12/ariane/rules-base.json index 25ac24d9df..30f8f24b2b 100644 --- a/flow/designs/gf12/ariane/rules-base.json +++ b/flow/designs/gf12/ariane/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -211.0, + "value": -208.0, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -38800.0, + "value": -716.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 3427852, + "value": 3948737, "compare": "<=" }, "detailedroute__route__drc_errors": { diff --git a/flow/designs/gf12/bp_dual/config.mk b/flow/designs/gf12/bp_dual/config.mk index 013ffea5d2..3f3e20af00 100644 --- a/flow/designs/gf12/bp_dual/config.mk +++ b/flow/designs/gf12/bp_dual/config.mk @@ -66,5 +66,3 @@ export MACRO_WRAPPERS = $(PLATFORM_DIR)/bp/wrappers/wrappers.tcl export PDN_TCL = $(PLATFORM_DIR)/cfg/pdn_grid_strategy_13m_9T.top.tcl export MACRO_PLACE_HALO = 7 7 - -export LEC_CHECK = 0 diff --git a/flow/designs/gf12/bp_quad/config.mk b/flow/designs/gf12/bp_quad/config.mk index b76df07a43..5846c209b3 100644 --- a/flow/designs/gf12/bp_quad/config.mk +++ b/flow/designs/gf12/bp_quad/config.mk @@ -68,5 +68,3 @@ export MACRO_WRAPPERS = $(PLATFORM_DIR)/bp/wrappers/wrappers.tcl export PDN_TCL = $(PLATFORM_DIR)/cfg/pdn_grid_strategy_13m_9T.top.tcl export MACRO_PLACE_HALO = 7 7 - -export LEC_CHECK = 0 diff --git a/flow/designs/gf12/bp_quad/rules-base.json b/flow/designs/gf12/bp_quad/rules-base.json index 9f06523d88..424a10a695 100644 --- a/flow/designs/gf12/bp_quad/rules-base.json +++ b/flow/designs/gf12/bp_quad/rules-base.json @@ -4,11 +4,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 1496173, + "value": 1503890, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 1442363, + "value": 1472164, "compare": "<=" }, "detailedplace__design__violations": { @@ -16,19 +16,19 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 125423, + "value": 128014, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 125423, + "value": 128014, "compare": "<=" }, "cts__timing__setup__ws": { - "value": -572.0, + "value": -375.0, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -659000.0, + "value": -393000.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -40,27 +40,27 @@ "compare": ">=" }, "globalroute__antenna_diodes_count": { - "value": 0, + "value": 1125, "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -117.0, + "value": -223.0, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -448.0, + "value": -4160.0, "compare": ">=" }, "globalroute__timing__hold__ws": { - "value": -100.0, + "value": -117.0, "compare": ">=" }, "globalroute__timing__hold__tns": { - "value": -400.0, + "value": -519.0, "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 24629256, + "value": 26222976, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -72,15 +72,15 @@ "compare": "<=" }, "detailedroute__antenna_diodes_count": { - "value": 5, + "value": 1131, "compare": "<=" }, "finish__timing__setup__ws": { - "value": -201.0, + "value": -225.0, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -1330.0, + "value": -1730.0, "compare": ">=" }, "finish__timing__hold__ws": { @@ -92,7 +92,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 1523750, + "value": 1534801, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/gf12/bp_single/config.mk b/flow/designs/gf12/bp_single/config.mk index 0455d8ff07..cf55a2e69e 100644 --- a/flow/designs/gf12/bp_single/config.mk +++ b/flow/designs/gf12/bp_single/config.mk @@ -71,5 +71,3 @@ export SETUP_SLACK_MARGIN ?= 100 export SWAP_ARITH_OPERATORS = 1 export OPENROAD_HIERARCHICAL = 1 - -export LEC_CHECK = 0 diff --git a/flow/designs/gf12/bp_single/rules-base.json b/flow/designs/gf12/bp_single/rules-base.json index 8a2cc25598..e3585846e5 100644 --- a/flow/designs/gf12/bp_single/rules-base.json +++ b/flow/designs/gf12/bp_single/rules-base.json @@ -36,11 +36,11 @@ "compare": ">=" }, "cts__timing__hold__ws": { - "value": -303.0, + "value": -385.0, "compare": ">=" }, "cts__timing__hold__tns": { - "value": -5060.0, + "value": -4460.0, "compare": ">=" }, "globalroute__antenna_diodes_count": { @@ -56,7 +56,7 @@ "compare": ">=" }, "globalroute__timing__hold__ws": { - "value": -255.0, + "value": -382.0, "compare": ">=" }, "globalroute__timing__hold__tns": { @@ -88,7 +88,7 @@ "compare": ">=" }, "finish__timing__hold__ws": { - "value": -100.0, + "value": -208.0, "compare": ">=" }, "finish__timing__hold__tns": { diff --git a/flow/designs/gf12/ca53/config.mk b/flow/designs/gf12/ca53/config.mk index d86d931093..b788b1fbea 100644 --- a/flow/designs/gf12/ca53/config.mk +++ b/flow/designs/gf12/ca53/config.mk @@ -69,5 +69,3 @@ endif #export SKIP_PIN_SWAP = 1 export SKIP_INCREMENTAL_REPAIR = 1 export TNS_END_PERCENT = 5 - -export LEC_CHECK = 0 diff --git a/flow/designs/gf12/ca53/rules-base.json b/flow/designs/gf12/ca53/rules-base.json index 92a7084c78..a2d1eb0a25 100644 --- a/flow/designs/gf12/ca53/rules-base.json +++ b/flow/designs/gf12/ca53/rules-base.json @@ -88,7 +88,7 @@ "compare": ">=" }, "finish__timing__hold__tns": { - "value": -2390.0, + "value": -3000.0, "compare": ">=" }, "finish__design__instance__area": { diff --git a/flow/designs/gf12/ibex/rules-base.json b/flow/designs/gf12/ibex/rules-base.json index 3b63acb1a4..bd5e360b32 100644 --- a/flow/designs/gf12/ibex/rules-base.json +++ b/flow/designs/gf12/ibex/rules-base.json @@ -24,7 +24,7 @@ "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 1570, + "value": 1752, "compare": "<=" }, "cts__timing__setup__ws": { diff --git a/flow/designs/gf12/swerv_wrapper/rules-base.json b/flow/designs/gf12/swerv_wrapper/rules-base.json index e504c37e34..be48a57243 100644 --- a/flow/designs/gf12/swerv_wrapper/rules-base.json +++ b/flow/designs/gf12/swerv_wrapper/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -84.0, + "value": -75.0, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -374.0, + "value": -300.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 2369199, + "value": 2737551, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -88,7 +88,7 @@ "compare": ">=" }, "finish__timing__hold__ws": { - "value": -84.1, + "value": -83.4, "compare": ">=" }, "finish__timing__hold__tns": { diff --git a/flow/designs/gf12/tinyRocket/config.mk b/flow/designs/gf12/tinyRocket/config.mk index ff0e7be0ce..08e3a88942 100644 --- a/flow/designs/gf12/tinyRocket/config.mk +++ b/flow/designs/gf12/tinyRocket/config.mk @@ -41,5 +41,3 @@ endif export SWAP_ARITH_OPERATORS = 1 export OPENROAD_HIERARCHICAL = 1 - -export LEC_CHECK = 0 diff --git a/flow/designs/gf180/aes-hybrid/rules-base.json b/flow/designs/gf180/aes-hybrid/rules-base.json index 8c1d4ef4c6..42ece06169 100644 --- a/flow/designs/gf180/aes-hybrid/rules-base.json +++ b/flow/designs/gf180/aes-hybrid/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -1.16, + "value": -1.14, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -155.0, + "value": -137.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -1.29, + "value": -1.27, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -170.0, + "value": -154.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -84,7 +84,7 @@ "compare": ">=" }, "finish__timing__setup__tns": { - "value": -166.0, + "value": -148.0, "compare": ">=" }, "finish__timing__hold__ws": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 762911, + "value": 752796, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/gf180/aes/rules-base.json b/flow/designs/gf180/aes/rules-base.json index 58ca477974..864fdbe9fb 100644 --- a/flow/designs/gf180/aes/rules-base.json +++ b/flow/designs/gf180/aes/rules-base.json @@ -32,7 +32,7 @@ "compare": ">=" }, "cts__timing__setup__tns": { - "value": -101.0, + "value": -98.7, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -1.06, + "value": -1.04, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -119.0, + "value": -118.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 1368635, + "value": 1359688, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -84,7 +84,7 @@ "compare": ">=" }, "finish__timing__setup__tns": { - "value": -114.0, + "value": -112.0, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/gf180/ibex/config.mk b/flow/designs/gf180/ibex/config.mk index d7e80346ae..036ce5145e 100644 --- a/flow/designs/gf180/ibex/config.mk +++ b/flow/designs/gf180/ibex/config.mk @@ -18,5 +18,3 @@ export PLACE_DENSITY_LB_ADDON = 0.1 export SWAP_ARITH_OPERATORS = 1 export OPENROAD_HIERARCHICAL = 1 -export LEC_CHECK = 0 - diff --git a/flow/designs/gf180/ibex/rules-base.json b/flow/designs/gf180/ibex/rules-base.json index 5d6d354b54..18835caee7 100644 --- a/flow/designs/gf180/ibex/rules-base.json +++ b/flow/designs/gf180/ibex/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.518, + "value": -0.507, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -2.04, + "value": -2.01, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.683, + "value": -0.59, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -8.66, + "value": -2.32, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -0.628, + "value": -0.601, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -2.6, + "value": -2.22, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/gf180/jpeg/rules-base.json b/flow/designs/gf180/jpeg/rules-base.json index 9da8363f53..67e5147e29 100644 --- a/flow/designs/gf180/jpeg/rules-base.json +++ b/flow/designs/gf180/jpeg/rules-base.json @@ -12,7 +12,7 @@ "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 51347, + "value": 51218, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,11 +20,11 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 4465, + "value": 4454, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 4465, + "value": 4454, "compare": "<=" }, "cts__timing__setup__ws": { diff --git a/flow/designs/gf180/riscv32i/rules-base.json b/flow/designs/gf180/riscv32i/rules-base.json index c9c7102342..fe9c6ee742 100644 --- a/flow/designs/gf180/riscv32i/rules-base.json +++ b/flow/designs/gf180/riscv32i/rules-base.json @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.5, + "value": -0.471, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -2.0, + "value": -1.86, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -0.5, + "value": -0.453, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -1.87, + "value": -1.8, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/gf180/uart-blocks/config.mk b/flow/designs/gf180/uart-blocks/config.mk index 15f496a5e6..b34c398b32 100644 --- a/flow/designs/gf180/uart-blocks/config.mk +++ b/flow/designs/gf180/uart-blocks/config.mk @@ -23,5 +23,3 @@ export TAPCELL_TCL ?= $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/tapcell.tcl export MACRO_ROWS_HALO_X = 14 export MACRO_ROWS_HALO_Y = 14 -export LEC_CHECK = 0 - diff --git a/flow/designs/gf180/uart-blocks/rules-base.json b/flow/designs/gf180/uart-blocks/rules-base.json index 40b0e2f6c8..de20a48fd8 100644 --- a/flow/designs/gf180/uart-blocks/rules-base.json +++ b/flow/designs/gf180/uart-blocks/rules-base.json @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 17036, + "value": 21354, "compare": "<=" }, "detailedroute__route__drc_errors": { diff --git a/flow/designs/ihp-sg13g2/aes/rules-base.json b/flow/designs/ihp-sg13g2/aes/rules-base.json index bd5fa98563..d20b95319c 100644 --- a/flow/designs/ihp-sg13g2/aes/rules-base.json +++ b/flow/designs/ihp-sg13g2/aes/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 214000.0, + "value": 208000.0, "compare": "<=" }, "constraints__clocks__count": { @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 200905, + "value": 197224, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 18614, + "value": 18253, "compare": "<=" }, "detailedplace__design__violations": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 204761, + "value": 201215, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/ihp-sg13g2/gcd/rules-base.json b/flow/designs/ihp-sg13g2/gcd/rules-base.json index 8c7b58a53a..a74bfae7db 100644 --- a/flow/designs/ihp-sg13g2/gcd/rules-base.json +++ b/flow/designs/ihp-sg13g2/gcd/rules-base.json @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 6197, + "value": 6153, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 508, + "value": 443, "compare": "<=" }, "detailedplace__design__violations": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 11161, + "value": 11091, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 6473, + "value": 6429, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/ihp-sg13g2/i2c-gpio-expander/I2cDeviceCtrl/config.mk b/flow/designs/ihp-sg13g2/i2c-gpio-expander/I2cDeviceCtrl/config.mk index ec737999b9..4af4286850 100644 --- a/flow/designs/ihp-sg13g2/i2c-gpio-expander/I2cDeviceCtrl/config.mk +++ b/flow/designs/ihp-sg13g2/i2c-gpio-expander/I2cDeviceCtrl/config.mk @@ -19,5 +19,3 @@ export CORNERS = slow typ fast export PDN_TCL = $(DESIGN_HOME)/$(PLATFORM)/$(TOP_DESIGN_NICKNAME)/${DESIGN_NAME}/pdn.tcl -export LEC_CHECK = 0 - diff --git a/flow/designs/ihp-sg13g2/i2c-gpio-expander/I2cDeviceCtrl/pdn.tcl b/flow/designs/ihp-sg13g2/i2c-gpio-expander/I2cDeviceCtrl/pdn.tcl index 11a54c43c5..e6c2311a3a 100644 --- a/flow/designs/ihp-sg13g2/i2c-gpio-expander/I2cDeviceCtrl/pdn.tcl +++ b/flow/designs/ihp-sg13g2/i2c-gpio-expander/I2cDeviceCtrl/pdn.tcl @@ -11,14 +11,6 @@ add_global_connection -net {VSS} -inst_pattern {.*} -pin_pattern {VSS!} -ground add_global_connection -net {VDD} -inst_pattern {.*} -pin_pattern {^VDD$} -power add_global_connection -net {VSS} -inst_pattern {.*} -pin_pattern {^VSS$} -ground -# padframe core power pins -add_global_connection -net {VDD} -pin_pattern {^vdd$} -power -add_global_connection -net {VSS} -pin_pattern {^vss$} -ground - -# padframe io power pins -add_global_connection -net {IOVDD} -pin_pattern {^iovdd$} -power -add_global_connection -net {IOVSS} -pin_pattern {^iovss$} -ground - global_connect # core voltage domain @@ -29,10 +21,10 @@ define_pdn_grid -name {grid} -voltage_domains {CORE} -pins {Metal4 Metal5} add_pdn_stripe -grid {grid} -layer {Metal1} -width {0.44} -pitch {7.56} -offset {0} \ -followpins add_pdn_ring -grid {grid} -layers {Metal4 Metal5} -widths {3.0} -spacings {2.0} \ - -core_offsets {4.5} -connect_to_pads -add_pdn_stripe -grid {grid} -layer {Metal4} -width {1.840} -pitch {75.6} -offset {13.6} \ + -core_offsets {4.5} +add_pdn_stripe -grid {grid} -layer {Metal4} -width {2.0} -pitch {40.0} -offset {10.0} \ -extend_to_core_ring -add_pdn_stripe -grid {grid} -layer {Metal5} -width {1.840} -pitch {75.6} -offset {13.6} \ +add_pdn_stripe -grid {grid} -layer {Metal5} -width {2.0} -pitch {40.0} -offset {10.0} \ -extend_to_core_ring add_pdn_connect -grid {grid} -layers {Metal1 Metal4} add_pdn_connect -grid {grid} -layers {Metal4 Metal5} diff --git a/flow/designs/ihp-sg13g2/i2c-gpio-expander/config.mk b/flow/designs/ihp-sg13g2/i2c-gpio-expander/config.mk index 2e85545f27..70ae7c201e 100644 --- a/flow/designs/ihp-sg13g2/i2c-gpio-expander/config.mk +++ b/flow/designs/ihp-sg13g2/i2c-gpio-expander/config.mk @@ -40,6 +40,8 @@ sg13g2_IOPadIOVss_inst \ sg13g2_IOPadIOVdd_inst export FOOTPRINT_TCL = $(PLATFORM_DIR)/pad.tcl +export MACRO_PLACEMENT_TCL = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/macros.tcl + export PDN_TCL = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/pdn.tcl export BLOCKS = I2cDeviceCtrl diff --git a/flow/designs/ihp-sg13g2/i2c-gpio-expander/macros.tcl b/flow/designs/ihp-sg13g2/i2c-gpio-expander/macros.tcl new file mode 100644 index 0000000000..da053f450f --- /dev/null +++ b/flow/designs/ihp-sg13g2/i2c-gpio-expander/macros.tcl @@ -0,0 +1 @@ +place_macro -macro_name system_expander.i2cCtrl -location {375.54 372} -orientation R0 -exact diff --git a/flow/designs/ihp-sg13g2/i2c-gpio-expander/pdn.tcl b/flow/designs/ihp-sg13g2/i2c-gpio-expander/pdn.tcl index 6006bf8471..aa317e8153 100644 --- a/flow/designs/ihp-sg13g2/i2c-gpio-expander/pdn.tcl +++ b/flow/designs/ihp-sg13g2/i2c-gpio-expander/pdn.tcl @@ -20,13 +20,15 @@ set_voltage_domain -name {CORE} -power {VDD} -ground {VSS} define_pdn_grid -name {grid} -voltage_domains {CORE} -pins {TopMetal1 TopMetal2} add_pdn_stripe -grid {grid} -layer {Metal1} -width {0.44} -pitch {7.56} -offset {0} \ -followpins -extend_to_core_ring -add_pdn_ring -grid {grid} -layers {TopMetal1 TopMetal2} -widths {8.0} -spacings {5.0} \ +add_pdn_ring -grid {grid} -layers {Metal5 TopMetal1} -widths {8.0} -spacings {5.0} \ -core_offsets {4.5} -connect_to_pads -add_pdn_stripe -grid {grid} -layer {TopMetal1} -width {2.200} -pitch {75.6} -offset {13.6} \ +add_pdn_stripe -grid {grid} -layer {TopMetal1} -width {4.0} -pitch {60.0} -offset {10.0} \ -extend_to_core_ring -add_pdn_stripe -grid {grid} -layer {TopMetal2} -width {2.200} -pitch {75.6} -offset {13.6} \ +add_pdn_stripe -grid {grid} -layer {TopMetal2} -width {4.0} -pitch {60.0} -offset {10.0} \ -extend_to_core_ring add_pdn_connect -grid {grid} -layers {Metal1 TopMetal1} +add_pdn_connect -grid {grid} -layers {Metal5 TopMetal1} +add_pdn_connect -grid {grid} -layers {Metal5 TopMetal2} add_pdn_connect -grid {grid} -layers {TopMetal1 TopMetal2} define_pdn_grid \ diff --git a/flow/designs/ihp-sg13g2/i2c-gpio-expander/rules-base.json b/flow/designs/ihp-sg13g2/i2c-gpio-expander/rules-base.json index a2aaf4d634..9a579e936f 100644 --- a/flow/designs/ihp-sg13g2/i2c-gpio-expander/rules-base.json +++ b/flow/designs/ihp-sg13g2/i2c-gpio-expander/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 311335.1878, + "value": 358000.0, "compare": "<=" }, "constraints__clocks__count": { diff --git a/flow/designs/ihp-sg13g2/ibex/config.mk b/flow/designs/ihp-sg13g2/ibex/config.mk index 94aaf9c727..7f3e9f4fc7 100644 --- a/flow/designs/ihp-sg13g2/ibex/config.mk +++ b/flow/designs/ihp-sg13g2/ibex/config.mk @@ -23,5 +23,3 @@ export CTS_BUF_DISTANCE = 60 export SWAP_ARITH_OPERATORS = 1 export OPENROAD_HIERARCHICAL = 1 -export LEC_CHECK = 0 - diff --git a/flow/designs/ihp-sg13g2/jpeg/rules-base.json b/flow/designs/ihp-sg13g2/jpeg/rules-base.json index ce42b4ed9f..3e35a44c1a 100644 --- a/flow/designs/ihp-sg13g2/jpeg/rules-base.json +++ b/flow/designs/ihp-sg13g2/jpeg/rules-base.json @@ -76,7 +76,7 @@ "compare": "<=" }, "detailedroute__antenna_diodes_count": { - "value": 135, + "value": 142, "compare": "<=" }, "finish__timing__setup__ws": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 1053077, + "value": 1041769, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/ihp-sg13g2/spi/rules-base.json b/flow/designs/ihp-sg13g2/spi/rules-base.json index 5c7cfd223e..8a15a24775 100644 --- a/flow/designs/ihp-sg13g2/spi/rules-base.json +++ b/flow/designs/ihp-sg13g2/spi/rules-base.json @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 3441, + "value": 3972, "compare": "<=" }, "detailedroute__route__drc_errors": { diff --git a/flow/designs/nangate45/aes/rules-base.json b/flow/designs/nangate45/aes/rules-base.json index c06b130a4f..0259ea49ed 100644 --- a/flow/designs/nangate45/aes/rules-base.json +++ b/flow/designs/nangate45/aes/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 19700.0, + "value": 19000.0, "compare": "<=" }, "constraints__clocks__count": { @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 23356, + "value": 22666, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 18239, + "value": 18129, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,11 +20,11 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 1586, + "value": 1576, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 1586, + "value": 1576, "compare": "<=" }, "cts__timing__setup__ws": { @@ -80,7 +80,7 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -0.0439, + "value": -0.0432, "compare": ">=" }, "finish__timing__setup__tns": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 23597, + "value": 22909, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/nangate45/ariane133/rules-base.json b/flow/designs/nangate45/ariane133/rules-base.json index 16ee72a7ef..932d873880 100644 --- a/flow/designs/nangate45/ariane133/rules-base.json +++ b/flow/designs/nangate45/ariane133/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 825864.85, + "value": 825000.0, "compare": "<=" }, "constraints__clocks__count": { @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.509, + "value": -0.694, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -650.0, + "value": -1190.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.482, + "value": -0.699, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -583.0, + "value": -1260.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -0.516, + "value": -0.716, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -649.0, + "value": -1510.0, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/nangate45/ariane136/rules-base.json b/flow/designs/nangate45/ariane136/rules-base.json index 97be8f8aa5..e48b97d4ae 100644 --- a/flow/designs/nangate45/ariane136/rules-base.json +++ b/flow/designs/nangate45/ariane136/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 845982.06, + "value": 845000.0, "compare": "<=" }, "constraints__clocks__count": { @@ -8,7 +8,7 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 853182, + "value": 847520, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { @@ -36,15 +36,15 @@ "compare": ">=" }, "cts__timing__hold__ws": { - "value": -0.693, + "value": -0.678, "compare": ">=" }, "cts__timing__hold__tns": { - "value": -4.16, + "value": -8.05, "compare": ">=" }, "globalroute__antenna_diodes_count": { - "value": 202, + "value": 200, "compare": "<=" }, "globalroute__timing__setup__ws": { @@ -76,7 +76,7 @@ "compare": "<=" }, "detailedroute__antenna_diodes_count": { - "value": 202, + "value": 201, "compare": "<=" }, "finish__timing__setup__ws": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 864432, + "value": 858672, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/nangate45/black_parrot/rules-base.json b/flow/designs/nangate45/black_parrot/rules-base.json index fc21694bef..0bc0df18eb 100644 --- a/flow/designs/nangate45/black_parrot/rules-base.json +++ b/flow/designs/nangate45/black_parrot/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 777000.0, + "value": 776000.0, "compare": "<=" }, "constraints__clocks__count": { @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 774157, + "value": 724309, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 280905, + "value": 242399, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,15 +20,15 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 24426, + "value": 21078, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 24426, + "value": 21078, "compare": "<=" }, "cts__timing__setup__ws": { - "value": -2.88, + "value": -2.8, "compare": ">=" }, "cts__timing__setup__tns": { @@ -48,7 +48,7 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -3.04, + "value": -2.97, "compare": ">=" }, "globalroute__timing__setup__tns": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 6985506, + "value": 6759084, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -80,7 +80,7 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -2.85, + "value": -2.78, "compare": ">=" }, "finish__timing__setup__tns": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 788072, + "value": 737075, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/nangate45/bp_be_top/config.mk b/flow/designs/nangate45/bp_be_top/config.mk index bf2de62487..7f88c0f4c3 100644 --- a/flow/designs/nangate45/bp_be_top/config.mk +++ b/flow/designs/nangate45/bp_be_top/config.mk @@ -30,5 +30,3 @@ export CTS_CLUSTER_DIAMETER = 50 export SYNTH_MINIMUM_KEEP_SIZE = 3000 export FASTROUTE_TCL = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NAME)/fastroute.tcl - -export LEC_CHECK = 0 diff --git a/flow/designs/nangate45/bp_be_top/rules-base.json b/flow/designs/nangate45/bp_be_top/rules-base.json index b579bb1766..2140525de9 100644 --- a/flow/designs/nangate45/bp_be_top/rules-base.json +++ b/flow/designs/nangate45/bp_be_top/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.423, + "value": -0.411, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -32.1, + "value": -24.3, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.431, + "value": -0.427, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -35.9, + "value": -29.9, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -0.43, + "value": -0.418, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -35.5, + "value": -28.5, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/nangate45/bp_fe_top/rules-base.json b/flow/designs/nangate45/bp_fe_top/rules-base.json index f153c05337..6f22269795 100644 --- a/flow/designs/nangate45/bp_fe_top/rules-base.json +++ b/flow/designs/nangate45/bp_fe_top/rules-base.json @@ -52,7 +52,7 @@ "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -1.23, + "value": -0.411, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 1912200, + "value": 1673870, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -80,19 +80,19 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -0.222, + "value": -0.206, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -13.8, + "value": -9.95, "compare": ">=" }, "finish__timing__hold__ws": { - "value": 0.0, + "value": -0.002, "compare": ">=" }, "finish__timing__hold__tns": { - "value": 0.0, + "value": -0.003, "compare": ">=" }, "finish__design__instance__area": { diff --git a/flow/designs/nangate45/bp_multi_top/config.mk b/flow/designs/nangate45/bp_multi_top/config.mk index f7cb5e4e0f..60edf46ef3 100644 --- a/flow/designs/nangate45/bp_multi_top/config.mk +++ b/flow/designs/nangate45/bp_multi_top/config.mk @@ -36,5 +36,3 @@ export SKIP_GATE_CLONING = 1 export SWAP_ARITH_OPERATORS = 1 export OPENROAD_HIERARCHICAL = 1 -export LEC_CHECK = 0 - diff --git a/flow/designs/nangate45/bp_multi_top/rules-base.json b/flow/designs/nangate45/bp_multi_top/rules-base.json index 79678ddd70..15e50bdcba 100644 --- a/flow/designs/nangate45/bp_multi_top/rules-base.json +++ b/flow/designs/nangate45/bp_multi_top/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 570000.0, + "value": 568000.0, "compare": "<=" }, "constraints__clocks__count": { @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 580304, + "value": 574894, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 110096, + "value": 108887, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,11 +20,11 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 9574, + "value": 9468, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 9574, + "value": 9468, "compare": "<=" }, "cts__timing__setup__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 3700293, + "value": 3920880, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -4.92, + "value": -0.24, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -262.0, + "value": -0.96, "compare": ">=" }, "finish__timing__hold__ws": { @@ -92,11 +92,11 @@ "compare": ">=" }, "finish__timing__hold__tns": { - "value": -0.96, + "value": -1.32, "compare": ">=" }, "finish__design__instance__area": { - "value": 587157, + "value": 581449, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/nangate45/dynamic_node/rules-base.json b/flow/designs/nangate45/dynamic_node/rules-base.json index bdac02bcce..9cf3eed023 100644 --- a/flow/designs/nangate45/dynamic_node/rules-base.json +++ b/flow/designs/nangate45/dynamic_node/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.423, + "value": -0.362, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -1.51, + "value": -1.45, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.434, + "value": -0.38, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -1.63, + "value": -1.49, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 219107, + "value": 208117, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -0.408, + "value": -0.344, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -1.45, + "value": -1.32, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/nangate45/gcd/rules-base.json b/flow/designs/nangate45/gcd/rules-base.json index 90428cccbc..40ceae99f8 100644 --- a/flow/designs/nangate45/gcd/rules-base.json +++ b/flow/designs/nangate45/gcd/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 725.6, + "value": 723.0, "compare": "<=" }, "constraints__clocks__count": { @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.0696, + "value": -0.0599, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -0.812, + "value": -0.448, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.0841, + "value": -0.0751, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -1.47, + "value": -1.06, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 4515, + "value": 5236, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -0.0744, + "value": -0.0688, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -1.05, + "value": -0.821, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/nangate45/ibex/rules-base.json b/flow/designs/nangate45/ibex/rules-base.json index cb35d317ef..57b78f4f4e 100644 --- a/flow/designs/nangate45/ibex/rules-base.json +++ b/flow/designs/nangate45/ibex/rules-base.json @@ -52,7 +52,7 @@ "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -0.546, + "value": -0.626, "compare": ">=" }, "globalroute__timing__hold__ws": { diff --git a/flow/designs/nangate45/jpeg/rules-base.json b/flow/designs/nangate45/jpeg/rules-base.json index 564a07b43e..b9828daea8 100644 --- a/flow/designs/nangate45/jpeg/rules-base.json +++ b/flow/designs/nangate45/jpeg/rules-base.json @@ -32,7 +32,7 @@ "compare": ">=" }, "cts__timing__setup__tns": { - "value": -39.2, + "value": -54.6, "compare": ">=" }, "cts__timing__hold__ws": { @@ -52,7 +52,7 @@ "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -49.5, + "value": -66.5, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -84,7 +84,7 @@ "compare": ">=" }, "finish__timing__setup__tns": { - "value": -36.9, + "value": -53.3, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/nangate45/mempool_group/rules-base.json b/flow/designs/nangate45/mempool_group/rules-base.json index 48e089a5f2..68c3af717b 100644 --- a/flow/designs/nangate45/mempool_group/rules-base.json +++ b/flow/designs/nangate45/mempool_group/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 271098.37, + "value": 424000.0, "compare": "<=" }, "constraints__clocks__count": { @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 295108, + "value": 444176, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 163160, + "value": 194613, "compare": "<=" }, "detailedplace__design__violations": { @@ -32,7 +32,7 @@ "compare": ">=" }, "cts__timing__setup__tns": { - "value": -10300.0, + "value": -13300.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -52,7 +52,7 @@ "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -11100.0, + "value": -11200.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 4029078, + "value": 5508759, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -84,7 +84,7 @@ "compare": ">=" }, "finish__timing__setup__tns": { - "value": -12100.0, + "value": -11000.0, "compare": ">=" }, "finish__timing__hold__ws": { @@ -92,11 +92,11 @@ "compare": ">=" }, "finish__timing__hold__tns": { - "value": -0.6, + "value": -1.77, "compare": ">=" }, "finish__design__instance__area": { - "value": 303227, + "value": 453719, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/nangate45/swerv/config.mk b/flow/designs/nangate45/swerv/config.mk index 31319f817f..2a76357c5a 100644 --- a/flow/designs/nangate45/swerv/config.mk +++ b/flow/designs/nangate45/swerv/config.mk @@ -11,3 +11,5 @@ export CORE_MARGIN = 5 export PLACE_DENSITY_LB_ADDON = 0.25 export TNS_END_PERCENT = 100 +export SWAP_ARITH_OPERATORS = 1 +export OPENROAD_HIERARCHICAL = 1 diff --git a/flow/designs/nangate45/swerv/rules-base.json b/flow/designs/nangate45/swerv/rules-base.json index 1b0037aabe..0693282dcc 100644 --- a/flow/designs/nangate45/swerv/rules-base.json +++ b/flow/designs/nangate45/swerv/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.387, + "value": -0.518, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -310.0, + "value": -338.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.416, + "value": -0.533, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -249.0, + "value": -329.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -0.398, + "value": -0.524, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -233.0, + "value": -311.0, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/nangate45/swerv_wrapper/rules-base.json b/flow/designs/nangate45/swerv_wrapper/rules-base.json index 099e50863b..e823e2c4c5 100644 --- a/flow/designs/nangate45/swerv_wrapper/rules-base.json +++ b/flow/designs/nangate45/swerv_wrapper/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.101, + "value": -0.197, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -0.402, + "value": -89.7, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.111, + "value": -0.237, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -0.534, + "value": -68.7, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 3639180, + "value": 5077847, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -80,19 +80,19 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -0.138, + "value": -0.256, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -0.924, + "value": -70.8, "compare": ">=" }, "finish__timing__hold__ws": { - "value": -0.107, + "value": -0.1, "compare": ">=" }, "finish__timing__hold__tns": { - "value": -0.407, + "value": -0.4, "compare": ">=" }, "finish__design__instance__area": { diff --git a/flow/designs/nangate45/tinyRocket/rules-base.json b/flow/designs/nangate45/tinyRocket/rules-base.json index b43b2952ec..f546d8c309 100644 --- a/flow/designs/nangate45/tinyRocket/rules-base.json +++ b/flow/designs/nangate45/tinyRocket/rules-base.json @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 60645, + "value": 60308, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 32140, + "value": 31653, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,11 +20,11 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 2795, + "value": 2752, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 2795, + "value": 2752, "compare": "<=" }, "cts__timing__setup__ws": { @@ -32,7 +32,7 @@ "compare": ">=" }, "cts__timing__setup__tns": { - "value": -17.1, + "value": -30.3, "compare": ">=" }, "cts__timing__hold__ws": { @@ -52,7 +52,7 @@ "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -30.0, + "value": -44.3, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 539547, + "value": 538070, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -84,7 +84,7 @@ "compare": ">=" }, "finish__timing__setup__tns": { - "value": -28.5, + "value": -38.1, "compare": ">=" }, "finish__timing__hold__ws": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 62486, + "value": 62067, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/rapidus2hp/cva6/config.mk b/flow/designs/rapidus2hp/cva6/config.mk index 4a6682267d..da52a1ca62 100644 --- a/flow/designs/rapidus2hp/cva6/config.mk +++ b/flow/designs/rapidus2hp/cva6/config.mk @@ -94,31 +94,31 @@ export ADDITIONAL_LIBS += $(PLATFORM_DIR)/ram/lib/sacrls0g0d1p64x128m2b1w0c1p0d0 $(PLATFORM_DIR)/ram/lib/sacrls0g0d1p64x25m2b1w0c1p0d0i0s0cr0rr0rm4rw00ms0.lib -DEFAULT_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint.sdc -_0P2A_6T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.2a_6T.sdc -_0P2A_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.2a_8T.sdc -_0P15_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.15_8T.sdc -_0P3_6T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.3_6T.sdc -_0P3_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.3_8T.sdc +.DEFAULT_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint.sdc +._0P2A_6T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.2a_6T.sdc +._0P2A_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.2a_8T.sdc +._0P15_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.15_8T.sdc +._0P3S_6T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.3s_6T.sdc +._0P3S_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.3s_8T.sdc # Use $(if) to defer conditional eval until all makefiles are read export SDC_FILE = $(strip \ $(if $(filter 0.2a,$(RAPIDUS_PDK_VERSION)), \ $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ - $(_0P2A_6T_SDC_FILE), \ - $(_0P2A_8T_SDC_FILE) \ + $(._0P2A_6T_SDC_FILE), \ + $(._0P2A_8T_SDC_FILE) \ ), \ $(if $(filter 0.15,$(RAPIDUS_PDK_VERSION)), \ $(if $(filter ra02h184_HST_45CPP,$(PLACE_SITE)), \ - $(_0P15_8T_SDC_FILE), \ - $(DEFAULT_SDC_FILE) \ + $(._0P15_8T_SDC_FILE), \ + $(.DEFAULT_SDC_FILE) \ ), \ - $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ + $(if $(filter 0.3s,$(RAPIDUS_PDK_VERSION)), \ $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ - $(_0P3_6T_SDC_FILE), \ - $(_0P3_8T_SDC_FILE) \ + $(._0P3S_6T_SDC_FILE), \ + $(._0P3S_8T_SDC_FILE) \ ), \ - $(DEFAULT_SDC_FILE) \ + $(.DEFAULT_SDC_FILE) \ ) \ ) \ )) @@ -148,6 +148,3 @@ export SYNTH_CANONICALIZE_TCL = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NAME)/canoni export SWAP_ARITH_OPERATORS = 1 export OPENROAD_HIERARCHICAL = 1 - -# Until the verilog writer fix is merged -export LEC_CHECK = 0 diff --git a/flow/designs/rapidus2hp/cva6/constraint_0.3_6T.sdc b/flow/designs/rapidus2hp/cva6/constraint_0.3s_6T.sdc similarity index 100% rename from flow/designs/rapidus2hp/cva6/constraint_0.3_6T.sdc rename to flow/designs/rapidus2hp/cva6/constraint_0.3s_6T.sdc diff --git a/flow/designs/rapidus2hp/cva6/constraint_0.3_8T.sdc b/flow/designs/rapidus2hp/cva6/constraint_0.3s_8T.sdc similarity index 100% rename from flow/designs/rapidus2hp/cva6/constraint_0.3_8T.sdc rename to flow/designs/rapidus2hp/cva6/constraint_0.3s_8T.sdc diff --git a/flow/designs/rapidus2hp/cva6/rules-base.json b/flow/designs/rapidus2hp/cva6/rules-base.json index eeecec3aa3..b080ef4497 100644 --- a/flow/designs/rapidus2hp/cva6/rules-base.json +++ b/flow/designs/rapidus2hp/cva6/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 17000.0, + "value": 16800.0, "compare": "<=" }, "constraints__clocks__count": { @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 14040, + "value": 13856, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 167948, + "value": 142196, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,19 +20,19 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 14604, + "value": 12365, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 14604, + "value": 12365, "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.138, + "value": -0.04, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -287.0, + "value": -0.16, "compare": ">=" }, "cts__timing__hold__ws": { @@ -44,15 +44,15 @@ "compare": ">=" }, "globalroute__antenna_diodes_count": { - "value": 143, + "value": 118, "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.255, + "value": -0.0412, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -575.0, + "value": -0.164, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -60,15 +60,15 @@ "compare": ">=" }, "globalroute__timing__hold__tns": { - "value": -0.108, + "value": -0.1, "compare": ">=" }, "finish__timing__setup__ws": { - "value": -0.255, + "value": -0.0412, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -575.0, + "value": -0.164, "compare": ">=" }, "finish__timing__hold__ws": { @@ -76,11 +76,11 @@ "compare": ">=" }, "finish__timing__hold__tns": { - "value": -0.108, + "value": -0.1, "compare": ">=" }, "finish__design__instance__area": { - "value": 14360, + "value": 14305, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/rapidus2hp/cva6/rules-verific.json b/flow/designs/rapidus2hp/cva6/rules-verific.json index 10726859ca..61b8668d9c 100644 --- a/flow/designs/rapidus2hp/cva6/rules-verific.json +++ b/flow/designs/rapidus2hp/cva6/rules-verific.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 17200.0, + "value": 17000.0, "compare": "<=" }, "constraints__clocks__count": { @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 14318, + "value": 14025, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 173997, + "value": 145376, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,19 +20,19 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 15130, + "value": 12641, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 15130, + "value": 12641, "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.157, + "value": -0.04, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -518.0, + "value": -0.16, "compare": ">=" }, "cts__timing__hold__ws": { @@ -44,15 +44,15 @@ "compare": ">=" }, "globalroute__antenna_diodes_count": { - "value": 148, + "value": 121, "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.358, + "value": -0.04, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -650.0, + "value": -0.16, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,11 +64,11 @@ "compare": ">=" }, "finish__timing__setup__ws": { - "value": -0.358, + "value": -0.04, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -650.0, + "value": -0.16, "compare": ">=" }, "finish__timing__hold__ws": { @@ -80,7 +80,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 14642, + "value": 14478, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/rapidus2hp/cva6/test/test_params.py b/flow/designs/rapidus2hp/cva6/test/test_params.py index 74639da262..5320deb206 100755 --- a/flow/designs/rapidus2hp/cva6/test/test_params.py +++ b/flow/designs/rapidus2hp/cva6/test/test_params.py @@ -24,9 +24,7 @@ def setUp(self): def get_exp_sdc(self, place_site, pdk_version): """Returns the expected SDC file path""" - if pdk_version in ["", "0.2a", "0.3"]: - if pdk_version == "": - pdk_version = "0.3" + if pdk_version in ["0.2a", "0.3s"]: if place_site == "ra02h138_DST_45CPP": return os.path.join( self._design_full_dir, f"constraint_{pdk_version}_6T.sdc" @@ -109,6 +107,23 @@ def test_pdk_0p15(self): front_end=front_end, ) + def test_pdk_0p3s(self): + """ + Tests PDK 0.3s + """ + + pdk_version = "0.3s" + for front_end in self._front_end_list: + for place_site in self._synopsys_site_list: + exp_sdc = self.get_exp_sdc(place_site, pdk_version) + self.execute_cmd( + "SDC_FILE", + exp_sdc, + place_site=place_site, + pdk_version=pdk_version, + front_end=front_end, + ) + def test_pdk_0p3(self): """ Tests PDK 0.3 diff --git a/flow/designs/rapidus2hp/ethmac/config.mk b/flow/designs/rapidus2hp/ethmac/config.mk index a0491869dc..f49bdc5577 100644 --- a/flow/designs/rapidus2hp/ethmac/config.mk +++ b/flow/designs/rapidus2hp/ethmac/config.mk @@ -17,9 +17,13 @@ export CORE_UTILIZATION = $(strip \ $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ 63, \ 65), \ - $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ + $(if $(filter 0.3s,$(RAPIDUS_PDK_VERSION)), \ 65, \ - 70) \ + $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ + 63, \ + 70 \ + ) \ + ) \ )) export CORE_ASPECT_RATIO = 1 diff --git a/flow/designs/rapidus2hp/ethmac/rules-base.json b/flow/designs/rapidus2hp/ethmac/rules-base.json index 8a34279dbc..07fe69c1df 100644 --- a/flow/designs/rapidus2hp/ethmac/rules-base.json +++ b/flow/designs/rapidus2hp/ethmac/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.0283, + "value": -0.0347, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -0.363, + "value": -0.658, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.0419, + "value": -0.0519, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -1.24, + "value": -1.58, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,11 +64,11 @@ "compare": ">=" }, "finish__timing__setup__ws": { - "value": -0.0419, + "value": -0.0519, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -1.24, + "value": -1.58, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/rapidus2hp/ethmac/rules-verific.json b/flow/designs/rapidus2hp/ethmac/rules-verific.json index 20792283ab..19259f96c6 100644 --- a/flow/designs/rapidus2hp/ethmac/rules-verific.json +++ b/flow/designs/rapidus2hp/ethmac/rules-verific.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 3290.0, + "value": 3780.0, "compare": "<=" }, "constraints__clocks__count": { @@ -12,7 +12,7 @@ "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 86788, + "value": 86754, "compare": "<=" }, "detailedplace__design__violations": { @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.0287, + "value": -0.0353, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -0.435, + "value": -0.698, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.0445, + "value": -0.0601, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -0.948, + "value": -1.63, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,11 +64,11 @@ "compare": ">=" }, "finish__timing__setup__ws": { - "value": -0.0445, + "value": -0.0601, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -0.948, + "value": -1.63, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/rapidus2hp/ethmac/test/test_params.py b/flow/designs/rapidus2hp/ethmac/test/test_params.py index 2c3ed37ef2..b7d78ae3f3 100755 --- a/flow/designs/rapidus2hp/ethmac/test/test_params.py +++ b/flow/designs/rapidus2hp/ethmac/test/test_params.py @@ -28,8 +28,10 @@ def get_exp_util(self, place_site, pdk_version): if place_site == "ra02h138_DST_45CPP": return 63 return 65 - if pdk_version in ["", "0.3"]: + if pdk_version == "0.3s": return 65 + if pdk_version in ["", "0.3"]: + return 63 return 70 def test_pdk_0p3_default(self): @@ -92,6 +94,21 @@ def test_pdk_0p15(self): front_end=front_end, ) + def test_pdk_0p3s(self): + """Tests PDK 0.3s Utilization""" + + pdk_version = "0.3s" + for front_end in self._front_end_list: + for place_site in self._synopsys_site_list: + exp_util = self.get_exp_util(place_site, pdk_version) + self.execute_cmd( + "CORE_UTILIZATION", + exp_util, + place_site=place_site, + pdk_version=pdk_version, + front_end=front_end, + ) + def test_pdk_0p3(self): """Tests PDK 0.3 Utilization""" diff --git a/flow/designs/rapidus2hp/gcd/config.mk b/flow/designs/rapidus2hp/gcd/config.mk index 8f8d39ddfa..77d042acb7 100644 --- a/flow/designs/rapidus2hp/gcd/config.mk +++ b/flow/designs/rapidus2hp/gcd/config.mk @@ -10,22 +10,20 @@ export VERILOG_FILES = $(DESIGN_HOME)/src/$(DESIGN_NAME)/gcd.v export SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NAME)/constraint.sdc # Use $(if) to defer conditional eval until all makefiles are read -# -# | PDK | Place Site | Utilization | -# | ---- | ---------- | ----------- | -# | 0.2 | 6T | 43 | -# | 0.2 | 8T | 45 | -# | 0.2a | 6T | 43 | -# | 0.2a | 8T | 45 | -# | 0.15 | 6T | 38 | -# | 0.15 | 8T | 40 | -# -export CORE_UTILIZATION = $(strip $(if $(filter 0.15,$(RAPIDUS_PDK_VERSION)), \ - $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ - 36, \ - 40), \ - $(if $(filter ra02h138_DST_45CPP SC6T,$(PLACE_SITE)), \ - 43, \ - 45))) +export CORE_UTILIZATION = $(strip \ + $(if $(filter 0.15,$(RAPIDUS_PDK_VERSION)), \ + $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ + 36, \ + 40), \ + $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ + $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ + 36, \ + 42), \ + $(if $(filter ra02h138_DST_45CPP SC6T,$(PLACE_SITE)), \ + 43, \ + 45 \ + ) \ + ) \ + )) export CORE_MARGIN = .5 diff --git a/flow/designs/rapidus2hp/gcd/rules-base.json b/flow/designs/rapidus2hp/gcd/rules-base.json index f4110338d8..d3d9ef6cdd 100644 --- a/flow/designs/rapidus2hp/gcd/rules-base.json +++ b/flow/designs/rapidus2hp/gcd/rules-base.json @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 29, + "value": 36, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 682, + "value": 692, "compare": "<=" }, "detailedplace__design__violations": { @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.0193, + "value": -0.0286, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -0.586, + "value": -0.308, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.0297, + "value": -0.0382, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -0.768, + "value": -0.704, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,11 +64,11 @@ "compare": ">=" }, "finish__timing__setup__ws": { - "value": -0.0297, + "value": -0.0382, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -0.768, + "value": -0.704, "compare": ">=" }, "finish__timing__hold__ws": { @@ -80,7 +80,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 32, + "value": 40, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/rapidus2hp/gcd/rules-verific.json b/flow/designs/rapidus2hp/gcd/rules-verific.json index 4fc7cf9b46..59b3c84e32 100644 --- a/flow/designs/rapidus2hp/gcd/rules-verific.json +++ b/flow/designs/rapidus2hp/gcd/rules-verific.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 22.2, + "value": 20.2, "compare": "<=" }, "constraints__clocks__count": { @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 29, + "value": 37, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 690, + "value": 688, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,11 +20,11 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 60, + "value": 58, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 60, + "value": 58, "compare": "<=" }, "cts__timing__setup__ws": { @@ -32,7 +32,7 @@ "compare": ">=" }, "cts__timing__setup__tns": { - "value": -0.206, + "value": -0.475, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.0339, + "value": -0.0302, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -0.363, + "value": -0.753, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,11 +64,11 @@ "compare": ">=" }, "finish__timing__setup__ws": { - "value": -0.0339, + "value": -0.0302, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -0.363, + "value": -0.753, "compare": ">=" }, "finish__timing__hold__ws": { @@ -80,7 +80,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 31, + "value": 41, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/rapidus2hp/gcd/test/test_params.py b/flow/designs/rapidus2hp/gcd/test/test_params.py index dfe28307b0..22a0d9e9ee 100755 --- a/flow/designs/rapidus2hp/gcd/test/test_params.py +++ b/flow/designs/rapidus2hp/gcd/test/test_params.py @@ -28,6 +28,10 @@ def get_exp_util(self, place_site, pdk_version): if place_site == "ra02h138_DST_45CPP": return 36 return 40 + if pdk_version in ["", "0.3"]: + if place_site == "ra02h138_DST_45CPP": + return 36 + return 42 if place_site in ["SC6T", "ra02h138_DST_45CPP"]: return 43 return 45 @@ -100,6 +104,23 @@ def test_pdk_0p15(self): front_end=front_end, ) + def test_pdk_0p3s(self): + """ + Tests PDK 0.3s utilization + """ + + pdk_version = "0.3s" + for front_end in self._front_end_list: + for place_site in self._synopsys_site_list: + exp_util = self.get_exp_util(place_site, pdk_version) + self.execute_cmd( + "CORE_UTILIZATION", + exp_util, + place_site=place_site, + pdk_version=pdk_version, + front_end=front_end, + ) + def test_pdk_0p3(self): """ Tests PDK 0.3 utilization diff --git a/flow/designs/rapidus2hp/hercules_idecode/config.mk b/flow/designs/rapidus2hp/hercules_idecode/config.mk index b03b6c6cc4..9b6d3c88b1 100644 --- a/flow/designs/rapidus2hp/hercules_idecode/config.mk +++ b/flow/designs/rapidus2hp/hercules_idecode/config.mk @@ -15,23 +15,51 @@ export VERILOG_INCLUDE_DIRS = $(SRC_HOME)/hercules_idecode/verilog \ $(SRC_HOME)/shared/verilog \ $(SRC_HOME)/models/cells/generic -export SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NAME)/prects.sdc +.DEFAULT_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/prects.sdc +._0P3_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/prects_0.3.sdc +export SDC_FILE = $(strip \ + $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ + $(._0P3_SDC_FILE), \ + $(.DEFAULT_SDC_FILE) \ + )) export SYNTH_HDL_FRONTEND ?= slang + # Use $(if) to defer conditional eval until all makefiles are read export CORE_UTILIZATION = $(strip \ - $(if $(filter slang,$(SYNTH_HDL_FRONTEND)), \ - $(if $(filter ra02h138_DST_45CPP SC6T,$(PLACE_SITE)), \ - $(if $(filter 0.15,$(RAPIDUS_PDK_VERSION)), \ - 42, \ - 44 \ + $(if $(filter 0.15,$(RAPIDUS_PDK_VERSION)), \ + $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ + $(if $(filter slang,$(SYNTH_HDL_FRONTEND)), \ + 42, \ + 43 \ ), \ - 50 \ + $(if $(filter slang,$(SYNTH_HDL_FRONTEND)), \ + 50, \ + 48 \ + ) \ ), \ - $(if $(filter ra02h138_DST_45CPP SC6T,$(PLACE_SITE)), \ - 43, \ - 48 \ + $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ + $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ + $(if $(filter slang,$(SYNTH_HDL_FRONTEND)), \ + 47, \ + 48 \ + ), \ + $(if $(filter slang,$(SYNTH_HDL_FRONTEND)), \ + 62, \ + 58 \ + ) \ + ), \ + $(if $(filter ra02h138_DST_45CPP SC6T,$(PLACE_SITE)), \ + $(if $(filter slang,$(SYNTH_HDL_FRONTEND)), \ + 44, \ + 43 \ + ), \ + $(if $(filter slang,$(SYNTH_HDL_FRONTEND)), \ + 50, \ + 48 \ + ) \ + ) \ ) \ )) diff --git a/flow/designs/rapidus2hp/hercules_idecode/prects_0.3.sdc b/flow/designs/rapidus2hp/hercules_idecode/prects_0.3.sdc new file mode 100644 index 0000000000..cfd7563a21 --- /dev/null +++ b/flow/designs/rapidus2hp/hercules_idecode/prects_0.3.sdc @@ -0,0 +1,16 @@ +source $::env(PLATFORM_DIR)/util.tcl + +#set sdc_version 2.1 +set sdc_version 1.4 +current_design hercules_idecode + +set clk_period 370 + +convert_time_value clk_period + +set_max_fanout 32 [current_design] +set_load [convert_cap_value 10] [all_outputs] +set_max_capacitance [convert_cap_value 10] [all_inputs] + +create_clock -name "clk" -add -period $clk_period \ + -waveform [list 0.0 [expr 0.5*$clk_period]] [get_ports clk] diff --git a/flow/designs/rapidus2hp/hercules_idecode/rules-base.json b/flow/designs/rapidus2hp/hercules_idecode/rules-base.json index c65a3a3682..b40328635d 100644 --- a/flow/designs/rapidus2hp/hercules_idecode/rules-base.json +++ b/flow/designs/rapidus2hp/hercules_idecode/rules-base.json @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 11599, + "value": 10320, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 296166, + "value": 230511, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,19 +20,19 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 25754, + "value": 20044, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 25754, + "value": 20044, "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.0252, + "value": -0.0185, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -26.4, + "value": -0.074, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.0644, + "value": -0.0383, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -203.0, + "value": -0.473, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,11 +64,11 @@ "compare": ">=" }, "finish__timing__setup__ws": { - "value": -0.0644, + "value": -0.0383, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -203.0, + "value": -0.473, "compare": ">=" }, "finish__timing__hold__ws": { @@ -80,7 +80,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 11865, + "value": 10628, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/rapidus2hp/hercules_idecode/rules-verific.json b/flow/designs/rapidus2hp/hercules_idecode/rules-verific.json index af3f451f7f..06eec91af7 100644 --- a/flow/designs/rapidus2hp/hercules_idecode/rules-verific.json +++ b/flow/designs/rapidus2hp/hercules_idecode/rules-verific.json @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 11625, + "value": 10358, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 298282, + "value": 232846, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,19 +20,19 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 25938, + "value": 20248, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 25938, + "value": 20248, "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.0226, + "value": -0.0185, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -7.13, + "value": -0.074, "compare": ">=" }, "cts__timing__hold__ws": { @@ -44,15 +44,15 @@ "compare": ">=" }, "globalroute__antenna_diodes_count": { - "value": 259, + "value": 202, "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.0668, + "value": -0.0225, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -189.0, + "value": -0.0993, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,11 +64,11 @@ "compare": ">=" }, "finish__timing__setup__ws": { - "value": -0.0668, + "value": -0.0225, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -189.0, + "value": -0.0993, "compare": ">=" }, "finish__timing__hold__ws": { @@ -80,7 +80,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 11884, + "value": 10645, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/rapidus2hp/hercules_idecode/test/test_params.py b/flow/designs/rapidus2hp/hercules_idecode/test/test_params.py index 6df51087ca..07b1fb4a34 100755 --- a/flow/designs/rapidus2hp/hercules_idecode/test/test_params.py +++ b/flow/designs/rapidus2hp/hercules_idecode/test/test_params.py @@ -24,16 +24,29 @@ def setUp(self): def get_exp_util(self, place_site, pdk_version, front_end): """Returns the expected value""" - if front_end == "verific": - if place_site in ["SC6T", "ra02h138_DST_45CPP"]: + if pdk_version == "0.15": + if place_site == "ra02h138_DST_45CPP": + if front_end in ["", "slang"]: + return 42 return 43 + if front_end in ["", "slang"]: + return 50 return 48 - else: - if place_site in ["SC6T", "ra02h138_DST_45CPP"]: - if pdk_version == "0.15": - return 42 + if pdk_version in ["", "0.3"]: + if place_site == "ra02h138_DST_45CPP": + if front_end in ["", "slang"]: + return 47 + return 48 + if front_end in ["", "slang"]: + return 62 + return 58 + if place_site in ["SC6T", "ra02h138_DST_45CPP"]: + if front_end in ["", "slang"]: return 44 + return 43 + if front_end in ["", "slang"]: return 50 + return 48 def test_pdk_0p3_default(self): """ @@ -103,6 +116,23 @@ def test_pdk_0p15(self): front_end=front_end, ) + def test_pdk_0p3s(self): + """ + Tests PDK 0.3s utilization + """ + + pdk_version = "0.3s" + for front_end in self._front_end_list: + for place_site in self._synopsys_site_list: + exp_util = self.get_exp_util(place_site, pdk_version, front_end) + self.execute_cmd( + "CORE_UTILIZATION", + exp_util, + place_site=place_site, + pdk_version=pdk_version, + front_end=front_end, + ) + def test_pdk_0p3(self): """ Tests PDK 0.3 utilization diff --git a/flow/designs/rapidus2hp/hercules_is_int/config.mk b/flow/designs/rapidus2hp/hercules_is_int/config.mk index 4e207a8168..0ebf5d65b3 100644 --- a/flow/designs/rapidus2hp/hercules_is_int/config.mk +++ b/flow/designs/rapidus2hp/hercules_is_int/config.mk @@ -20,7 +20,13 @@ export VERILOG_INCLUDE_DIRS = $(SRC_HOME)/hercules_issue/verilog \ $(SRC_HOME)/shared/verilog \ $(SRC_HOME)/models/cells/generic -export SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NAME)/prects.sdc +.DEFAULT_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/prects.sdc +._0P3_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/prects_0.3.sdc +export SDC_FILE = $(strip \ + $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ + $(._0P3_SDC_FILE), \ + $(.DEFAULT_SDC_FILE) \ + )) # Must be defined before the ifeq's export SYNTH_HDL_FRONTEND ?= slang @@ -28,7 +34,7 @@ export SYNTH_HIERARCHICAL ?= 0 # Use $(if) to defer conditional eval until all makefiles are read export CORE_UTILIZATION = $(strip \ - $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ + $(if $(filter 0.3s,$(RAPIDUS_PDK_VERSION)), \ $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ $(if $(filter slang,$(SYNTH_HDL_FRONTEND)), \ $(if $(filter 14LM,$(LAYER_STACK_OPTION)), \ @@ -50,14 +56,23 @@ export CORE_UTILIZATION = $(strip \ 30, \ 52 \ ), \ - $(if $(filter slang,$(SYNTH_HDL_FRONTEND)), \ + $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ $(if $(filter ra02h138_DST_45CPP SC6T,$(PLACE_SITE)), \ - 30, \ - 52 \ - ), \ - $(if $(filter ra02h138_DST_45CPP SC6T,$(PLACE_SITE)), \ - 30, \ - 54 \ + 52, \ + $(if $(filter slang,$(SYNTH_HDL_FRONTEND)), \ + 65, \ + 63 \ + ) \ + ), \ + $(if $(filter slang,$(SYNTH_HDL_FRONTEND)), \ + $(if $(filter ra02h138_DST_45CPP SC6T,$(PLACE_SITE)), \ + 30, \ + 52 \ + ), \ + $(if $(filter ra02h138_DST_45CPP SC6T,$(PLACE_SITE)), \ + 30, \ + 54 \ + ) \ ) \ ) \ ) \ diff --git a/flow/designs/rapidus2hp/hercules_is_int/prects_0.3.sdc b/flow/designs/rapidus2hp/hercules_is_int/prects_0.3.sdc new file mode 100644 index 0000000000..0d562a402c --- /dev/null +++ b/flow/designs/rapidus2hp/hercules_is_int/prects_0.3.sdc @@ -0,0 +1,16 @@ +source $::env(PLATFORM_DIR)/util.tcl + +#set sdc_version 2.1 +set sdc_version 1.4 +current_design hercules_is_int + +set clk_period 370 + +convert_time_value clk_period + +set_max_fanout 32 [current_design] +set_load [convert_cap_value 10] [all_outputs] +set_max_capacitance [convert_cap_value 10] [all_inputs] + +create_clock -name "clk" -add -period $clk_period \ + -waveform [list 0.0 [expr { 0.5 * $clk_period }]] [get_ports clk] diff --git a/flow/designs/rapidus2hp/hercules_is_int/rules-base.json b/flow/designs/rapidus2hp/hercules_is_int/rules-base.json index 86002e8f20..504e3f1dbe 100644 --- a/flow/designs/rapidus2hp/hercules_is_int/rules-base.json +++ b/flow/designs/rapidus2hp/hercules_is_int/rules-base.json @@ -12,7 +12,7 @@ "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 658787, + "value": 647733, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,19 +20,19 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 57286, + "value": 56325, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 57286, + "value": 56325, "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.0467, + "value": -0.0185, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -132.0, + "value": -0.074, "compare": ">=" }, "cts__timing__hold__ws": { @@ -44,15 +44,15 @@ "compare": ">=" }, "globalroute__antenna_diodes_count": { - "value": 579, + "value": 567, "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.105, + "value": -0.0815, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -907.0, + "value": -47.3, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,11 +64,11 @@ "compare": ">=" }, "finish__timing__setup__ws": { - "value": -0.105, + "value": -0.0815, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -907.0, + "value": -47.4, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/rapidus2hp/hercules_is_int/rules-verific.json b/flow/designs/rapidus2hp/hercules_is_int/rules-verific.json index 7bada738bb..24a7dcca8c 100644 --- a/flow/designs/rapidus2hp/hercules_is_int/rules-verific.json +++ b/flow/designs/rapidus2hp/hercules_is_int/rules-verific.json @@ -12,7 +12,7 @@ "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 659181, + "value": 646997, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,19 +20,19 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 57320, + "value": 56261, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 57320, + "value": 56261, "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.0505, + "value": -0.0185, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -158.0, + "value": -0.074, "compare": ">=" }, "cts__timing__hold__ws": { @@ -44,15 +44,15 @@ "compare": ">=" }, "globalroute__antenna_diodes_count": { - "value": 579, + "value": 567, "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.106, + "value": -0.111, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -1160.0, + "value": -107.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,11 +64,11 @@ "compare": ">=" }, "finish__timing__setup__ws": { - "value": -0.106, + "value": -0.111, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -1160.0, + "value": -107.0, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/rapidus2hp/hercules_is_int/test/test_params.py b/flow/designs/rapidus2hp/hercules_is_int/test/test_params.py index 54422f0940..3830917581 100755 --- a/flow/designs/rapidus2hp/hercules_is_int/test/test_params.py +++ b/flow/designs/rapidus2hp/hercules_is_int/test/test_params.py @@ -24,7 +24,11 @@ def setUp(self): def get_exp_util(self, place_site, front_end, pdk_version, layer_stack): """Returns the expected value""" - if pdk_version in ["", "0.3"]: + if pdk_version == "0.15": + if place_site == "ra02h138_DST_45CPP": + return 30 + return 52 + if pdk_version == "0.3s": if place_site == "ra02h138_DST_45CPP": if front_end in ["", "slang"]: if layer_stack == "14LM": @@ -35,10 +39,12 @@ def get_exp_util(self, place_site, front_end, pdk_version, layer_stack): if layer_stack == "14LM": return 50 return 56 - if pdk_version in "0.15": + if pdk_version in ["", "0.3"]: if place_site == "ra02h138_DST_45CPP": - return 30 - return 52 + return 52 + if front_end in ["", "slang"]: + return 65 + return 63 if front_end == "verific": if place_site in ["SC6T", "ra02h138_DST_45CPP"]: return 30 @@ -48,6 +54,15 @@ def get_exp_util(self, place_site, front_end, pdk_version, layer_stack): return 30 return 52 + def get_exp_sdc(self, place_site, pdk_version): + """Returns the expected SDC file path""" + + if pdk_version in ["", "0.3"]: + if pdk_version == "": + pdk_version = "0.3" + return os.path.join(self._design_full_dir, f"prects_{pdk_version}.sdc") + return os.path.join(self._design_full_dir, "prects.sdc") + def test_pdk_0p3_default(self): """ Tests PDK 0.3 utilization @@ -131,6 +146,27 @@ def test_pdk_0p15(self): layer_stack=layer_stack, ) + def test_pdk_0p3s(self): + """ + Tests PDK 0.3s utilization + """ + + pdk_version = "0.3s" + for front_end in self._front_end_list: + for place_site in self._synopsys_site_list: + for layer_stack in self._layer_stack_list: + exp_util = self.get_exp_util( + place_site, front_end, pdk_version, layer_stack + ) + self.execute_cmd( + "CORE_UTILIZATION", + exp_util, + place_site=place_site, + pdk_version=pdk_version, + front_end=front_end, + layer_stack=layer_stack, + ) + def test_pdk_0p3(self): """ Tests PDK 0.3 utilization diff --git a/flow/designs/rapidus2hp/ibex/config.mk b/flow/designs/rapidus2hp/ibex/config.mk index 3a1b18e49e..9e6c5907d6 100644 --- a/flow/designs/rapidus2hp/ibex/config.mk +++ b/flow/designs/rapidus2hp/ibex/config.mk @@ -23,28 +23,35 @@ export SYNTH_HDL_FRONTEND ?= slang ifeq ($(FLOW_VARIANT),pos_slack) export SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_pos_slack.sdc else - DEFAULT_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint.sdc - _0P2A_6T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.2a_6T.sdc - _0P2A_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.2a_8T.sdc - _0P15_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.15.sdc - _0P3_6T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.3_6T.sdc - _0P3_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.3_8T.sdc + .DEFAULT_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint.sdc + ._0P2A_6T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.2a_6T.sdc + ._0P2A_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.2a_8T.sdc + ._0P15_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.15.sdc + ._0P3S_6T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.3s_6T.sdc + ._0P3S_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.3s_8T.sdc + ._0P3_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint_0.3_8T.sdc # Use $(if) to defer conditional eval until all makefiles are read export SDC_FILE = $(strip \ $(if $(filter 0.2a,$(RAPIDUS_PDK_VERSION)), \ $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ - $(_0P2A_6T_SDC_FILE), \ - $(_0P2A_8T_SDC_FILE) \ + $(._0P2A_6T_SDC_FILE), \ + $(._0P2A_8T_SDC_FILE) \ ), \ $(if $(filter 0.15,$(RAPIDUS_PDK_VERSION)), \ - $(_0P15_SDC_FILE), \ - $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ + $(._0P15_SDC_FILE), \ + $(if $(filter 0.3s,$(RAPIDUS_PDK_VERSION)), \ $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ - $(_0P3_6T_SDC_FILE), \ - $(_0P3_8T_SDC_FILE) \ + $(._0P3S_6T_SDC_FILE), \ + $(._0P3S_8T_SDC_FILE) \ ), \ - $(DEFAULT_SDC_FILE) \ + $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ + $(if $(filter ra02h184_HST_45CPP,$(PLACE_SITE)), \ + $(._0P3_8T_SDC_FILE), \ + $(.DEFAULT_SDC_FILE) \ + ), \ + $(.DEFAULT_SDC_FILE) \ + ) \ ) \ ) \ )) @@ -56,12 +63,18 @@ export CORE_UTILIZATION = $(strip \ 52, \ 65 \ ), \ - $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ + $(if $(filter 0.3s,$(RAPIDUS_PDK_VERSION)), \ $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ 60, \ 65 \ ), \ - 70 \ + $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ + $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ + 55, \ + 70 \ + ), \ + 70 \ + ) \ ) \ )) diff --git a/flow/designs/rapidus2hp/ibex/constraint_0.3_6T.sdc b/flow/designs/rapidus2hp/ibex/constraint_0.3s_6T.sdc similarity index 100% rename from flow/designs/rapidus2hp/ibex/constraint_0.3_6T.sdc rename to flow/designs/rapidus2hp/ibex/constraint_0.3s_6T.sdc diff --git a/flow/designs/rapidus2hp/ibex/constraint_0.3s_8T.sdc b/flow/designs/rapidus2hp/ibex/constraint_0.3s_8T.sdc new file mode 100644 index 0000000000..f539d55b82 --- /dev/null +++ b/flow/designs/rapidus2hp/ibex/constraint_0.3s_8T.sdc @@ -0,0 +1,19 @@ +source $::env(PLATFORM_DIR)/util.tcl + +set clk_name core_clock +set clk_port_name clk_i +set clk_period 450 +set clk_io_pct 0.2 + +set clk_port [get_ports $clk_port_name] + +convert_time_value clk_period + +create_clock -name $clk_name -period $clk_period $clk_port + +set non_clock_inputs [lsearch -inline -all -not -exact [all_inputs] $clk_port] + +set_input_delay [expr { $clk_period * $clk_io_pct }] -clock $clk_name \ + $non_clock_inputs +set_output_delay [expr { $clk_period * $clk_io_pct }] -clock $clk_name \ + [all_outputs] diff --git a/flow/designs/rapidus2hp/ibex/rules-base.json b/flow/designs/rapidus2hp/ibex/rules-base.json index 3c226224e5..f68093141f 100644 --- a/flow/designs/rapidus2hp/ibex/rules-base.json +++ b/flow/designs/rapidus2hp/ibex/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 1020.0, + "value": 1010.0, "compare": "<=" }, "constraints__clocks__count": { @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 1049, + "value": 1216, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 22939, + "value": 20942, "compare": "<=" }, "detailedplace__design__violations": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.048, + "value": -0.0344, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -12.8, + "value": -0.938, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,11 +64,11 @@ "compare": ">=" }, "finish__timing__setup__ws": { - "value": -0.048, + "value": -0.0344, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -12.8, + "value": -0.938, "compare": ">=" }, "finish__timing__hold__ws": { @@ -80,7 +80,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 1088, + "value": 1266, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/rapidus2hp/ibex/rules-verific.json b/flow/designs/rapidus2hp/ibex/rules-verific.json index 476841c423..14cad94e09 100644 --- a/flow/designs/rapidus2hp/ibex/rules-verific.json +++ b/flow/designs/rapidus2hp/ibex/rules-verific.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 1030.0, + "value": 1020.0, "compare": "<=" }, "constraints__clocks__count": { @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 1060, + "value": 1221, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 23391, + "value": 21890, "compare": "<=" }, "detailedplace__design__violations": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.0239, + "value": -0.0353, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -0.0951, + "value": -0.152, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,11 +64,11 @@ "compare": ">=" }, "finish__timing__setup__ws": { - "value": -0.0239, + "value": -0.0353, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -0.0951, + "value": -0.152, "compare": ">=" }, "finish__timing__hold__ws": { @@ -80,7 +80,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 1103, + "value": 1274, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/rapidus2hp/ibex/test/test_params.py b/flow/designs/rapidus2hp/ibex/test/test_params.py index 9953c62ccd..3c2f74814e 100755 --- a/flow/designs/rapidus2hp/ibex/test/test_params.py +++ b/flow/designs/rapidus2hp/ibex/test/test_params.py @@ -24,14 +24,18 @@ def setUp(self): def get_exp_util(self, place_site, pdk_version): """Returns the expected utilization""" - if pdk_version in ["", "0.3"]: - if place_site == "ra02h138_DST_45CPP": - return 60 - return 65 if pdk_version == "0.15": if place_site == "ra02h138_DST_45CPP": return 52 return 65 + if pdk_version == "0.3s": + if place_site == "ra02h138_DST_45CPP": + return 60 + return 65 + if pdk_version in ["", "0.3"]: + if place_site == "ra02h138_DST_45CPP": + return 55 + return 70 return 70 def get_exp_sdc(self, place_site, pdk_version): @@ -47,9 +51,7 @@ def get_exp_sdc(self, place_site, pdk_version): ) if pdk_version == "0.15": return os.path.join(self._design_full_dir, f"constraint_{pdk_version}.sdc") - if pdk_version in ["", "0.3"]: - if pdk_version == "": - pdk_version = "0.3" + if pdk_version == "0.3s": if place_site == "ra02h138_DST_45CPP": return os.path.join( self._design_full_dir, f"constraint_{pdk_version}_6T.sdc" @@ -58,6 +60,13 @@ def get_exp_sdc(self, place_site, pdk_version): self._design_full_dir, f"constraint_{pdk_version}_8T.sdc" ) + if pdk_version in ["", "0.3"]: + if place_site in ["", "ra02h184_HST_45CPP"]: + if pdk_version == "": + pdk_version = "0.3" + return os.path.join( + self._design_full_dir, f"constraint_{pdk_version}_8T.sdc" + ) return os.path.join(self._design_full_dir, "constraint.sdc") def test_pdk_0p3_default(self): @@ -160,6 +169,32 @@ def test_pdk_0p15(self): front_end=front_end, ) + def test_pdk_0p3s(self): + """ + Tests PDK 0.3s utilization + """ + + front_end = "" + pdk_version = "0.3s" + for front_end in self._front_end_list: + for place_site in self._synopsys_site_list: + exp_util = self.get_exp_util(place_site, pdk_version) + exp_sdc = self.get_exp_sdc(place_site, pdk_version) + self.execute_cmd( + "CORE_UTILIZATION", + exp_util, + place_site=place_site, + pdk_version=pdk_version, + front_end=front_end, + ) + self.execute_cmd( + "SDC_FILE", + exp_sdc, + place_site=place_site, + pdk_version=pdk_version, + front_end=front_end, + ) + def test_pdk_0p3(self): """ Tests PDK 0.3 utilization diff --git a/flow/designs/rapidus2hp/jpeg/config.mk b/flow/designs/rapidus2hp/jpeg/config.mk index a41d2bcecc..c157e1942b 100644 --- a/flow/designs/rapidus2hp/jpeg/config.mk +++ b/flow/designs/rapidus2hp/jpeg/config.mk @@ -10,31 +10,44 @@ endif export VERILOG_FILES = $(sort $(wildcard $(DESIGN_HOME)/src/$(DESIGN_NICKNAME)/*.v)) export VERILOG_INCLUDE_DIRS = $(DESIGN_HOME)/src/$(DESIGN_NICKNAME)/include -DEFAULT_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/jpeg_encoder15_7nm.sdc -_0P2A_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/jpeg_encoder15_0.2a_8T.sdc -_0P15_6T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/jpeg_encoder15_0.15_6T.sdc -_0P15_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/jpeg_encoder15_0.15_8T.sdc -_0P3_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/jpeg_encoder15_0.3.sdc +.DEFAULT_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/jpeg_encoder15_7nm.sdc +._0P2A_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/jpeg_encoder15_0.2a_8T.sdc +._0P15_6T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/jpeg_encoder15_0.15_6T.sdc +._0P15_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/jpeg_encoder15_0.15_8T.sdc +._0P3S_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/jpeg_encoder15_0.3s.sdc +._0P3_6T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/jpeg_encoder15_0.3_6T.sdc +._0P3_8T_SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/jpeg_encoder15_0.3_8T.sdc # Use $(if) to defer conditional eval until all makefiles are read export SDC_FILE = $(strip \ $(if $(and $(filter 0.2a,$(RAPIDUS_PDK_VERSION)),$(filter ra02h184_HST_45CPP,$(PLACE_SITE))), \ - $(_0P2A_8T_SDC_FILE), \ + $(._0P2A_8T_SDC_FILE), \ $(if $(filter 0.15,$(RAPIDUS_PDK_VERSION)), \ $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ - $(_0P15_6T_SDC_FILE), \ - $(_0P15_8T_SDC_FILE) \ + $(._0P15_6T_SDC_FILE), \ + $(._0P15_8T_SDC_FILE) \ ), \ - $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ - $(_0P3_SDC_FILE), \ - $(DEFAULT_SDC_FILE) \ + $(if $(filter 0.3s,$(RAPIDUS_PDK_VERSION)), \ + $(._0P3S_SDC_FILE), \ + $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ + $(if $(filter ra02h138_DST_45CPP,$(PLACE_SITE)), \ + $(._0P3_6T_SDC_FILE), \ + $(._0P3_8T_SDC_FILE) \ + ), \ + $(.DEFAULT_SDC_FILE) \ + ) \ ) \ ) \ )) export ABC_AREA = 1 -export CORE_UTILIZATION = 60 +export CORE_UTILIZATION = $(strip \ + $(if $(filter 0.3,$(RAPIDUS_PDK_VERSION)), \ + 62, \ + 60 \ + )) + export CORE_ASPECT_RATIO = 1 export CORE_MARGIN = 0.75 diff --git a/flow/designs/rapidus2hp/jpeg/jpeg_encoder15_0.3_6T.sdc b/flow/designs/rapidus2hp/jpeg/jpeg_encoder15_0.3_6T.sdc new file mode 100644 index 0000000000..48533567a1 --- /dev/null +++ b/flow/designs/rapidus2hp/jpeg/jpeg_encoder15_0.3_6T.sdc @@ -0,0 +1,21 @@ +source $::env(PLATFORM_DIR)/util.tcl + +current_design jpeg_encoder + +set clk_name clk +set clk_port_name clk +set clk_period 290 +set clk_io_pct 0.2 + +convert_time_value clk_period + +set clk_port [get_ports $clk_port_name] + +create_clock -name $clk_name -period $clk_period $clk_port + +set non_clock_inputs [lsearch -inline -all -not -exact [all_inputs] $clk_port] + +set_input_delay [expr { $clk_period * $clk_io_pct }] -clock $clk_name \ + $non_clock_inputs +set_output_delay [expr { $clk_period * $clk_io_pct }] -clock $clk_name \ + [all_outputs] diff --git a/flow/designs/rapidus2hp/jpeg/jpeg_encoder15_0.3_8T.sdc b/flow/designs/rapidus2hp/jpeg/jpeg_encoder15_0.3_8T.sdc new file mode 100644 index 0000000000..4f489bb009 --- /dev/null +++ b/flow/designs/rapidus2hp/jpeg/jpeg_encoder15_0.3_8T.sdc @@ -0,0 +1,21 @@ +source $::env(PLATFORM_DIR)/util.tcl + +current_design jpeg_encoder + +set clk_name clk +set clk_port_name clk +set clk_period 225 +set clk_io_pct 0.2 + +convert_time_value clk_period + +set clk_port [get_ports $clk_port_name] + +create_clock -name $clk_name -period $clk_period $clk_port + +set non_clock_inputs [lsearch -inline -all -not -exact [all_inputs] $clk_port] + +set_input_delay [expr { $clk_period * $clk_io_pct }] -clock $clk_name \ + $non_clock_inputs +set_output_delay [expr { $clk_period * $clk_io_pct }] -clock $clk_name \ + [all_outputs] diff --git a/flow/designs/rapidus2hp/jpeg/jpeg_encoder15_0.3.sdc b/flow/designs/rapidus2hp/jpeg/jpeg_encoder15_0.3s.sdc similarity index 100% rename from flow/designs/rapidus2hp/jpeg/jpeg_encoder15_0.3.sdc rename to flow/designs/rapidus2hp/jpeg/jpeg_encoder15_0.3s.sdc diff --git a/flow/designs/rapidus2hp/jpeg/rules-base.json b/flow/designs/rapidus2hp/jpeg/rules-base.json index a8328c9bca..84e4a2f460 100644 --- a/flow/designs/rapidus2hp/jpeg/rules-base.json +++ b/flow/designs/rapidus2hp/jpeg/rules-base.json @@ -12,7 +12,7 @@ "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 116278, + "value": 109773, "compare": "<=" }, "detailedplace__design__violations": { @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.0541, + "value": -0.0112, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -37.8, + "value": -0.045, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.106, + "value": -0.0358, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -106.0, + "value": -6.39, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,11 +64,11 @@ "compare": ">=" }, "finish__timing__setup__ws": { - "value": -0.106, + "value": -0.0358, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -106.0, + "value": -6.39, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/rapidus2hp/jpeg/rules-verific.json b/flow/designs/rapidus2hp/jpeg/rules-verific.json index 09e284c6b6..6b369ce4b8 100644 --- a/flow/designs/rapidus2hp/jpeg/rules-verific.json +++ b/flow/designs/rapidus2hp/jpeg/rules-verific.json @@ -12,7 +12,7 @@ "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 117602, + "value": 115045, "compare": "<=" }, "detailedplace__design__violations": { @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.0522, + "value": -0.0112, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -43.9, + "value": -0.045, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.0956, + "value": -0.0629, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -120.0, + "value": -13.8, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,11 +64,11 @@ "compare": ">=" }, "finish__timing__setup__ws": { - "value": -0.0956, + "value": -0.0629, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -120.0, + "value": -13.8, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/rapidus2hp/jpeg/test/test_params.py b/flow/designs/rapidus2hp/jpeg/test/test_params.py index b04eed5eab..d2b7432a58 100755 --- a/flow/designs/rapidus2hp/jpeg/test/test_params.py +++ b/flow/designs/rapidus2hp/jpeg/test/test_params.py @@ -21,6 +21,12 @@ def setUp(self): ParamTestBase.setUp(self, "jpeg") + def get_exp_util(self, place_site, pdk_version): + """Returns the expected utilization""" + if pdk_version in ["", "0.3"]: + return 62 + return 60 + def get_exp_sdc(self, place_site, pdk_version): """Returns the expected SDC file path""" @@ -29,7 +35,9 @@ def get_exp_sdc(self, place_site, pdk_version): return os.path.join( self._design_full_dir, f"jpeg_encoder15_{pdk_version}_8T.sdc" ) - if pdk_version == "0.15": + if pdk_version in ["", "0.3", "0.15"]: + if pdk_version == "": + pdk_version = "0.3" if place_site in ["", "ra02h184_HST_45CPP"]: return os.path.join( self._design_full_dir, f"jpeg_encoder15_{pdk_version}_8T.sdc" @@ -37,9 +45,7 @@ def get_exp_sdc(self, place_site, pdk_version): return os.path.join( self._design_full_dir, f"jpeg_encoder15_{pdk_version}_6T.sdc" ) - if pdk_version in ["", "0.3"]: - if pdk_version == "": - pdk_version = "0.3" + if pdk_version == "0.3s": return os.path.join( self._design_full_dir, f"jpeg_encoder15_{pdk_version}.sdc" ) @@ -53,7 +59,15 @@ def test_pdk_0p3_default(self): pdk_version = "" for front_end in self._front_end_list: for place_site in self._synopsys_site_list: + exp_util = self.get_exp_util(place_site, pdk_version) exp_sdc = self.get_exp_sdc(place_site, pdk_version) + self.execute_cmd( + "CORE_UTILIZATION", + exp_util, + place_site=place_site, + pdk_version=pdk_version, + front_end=front_end, + ) self.execute_cmd( "SDC_FILE", exp_sdc, @@ -70,7 +84,15 @@ def test_pdk_0p2(self): pdk_version = "0.2" for front_end in self._front_end_list: for place_site in self._ibm_site_list: + exp_util = self.get_exp_util(place_site, pdk_version) exp_sdc = self.get_exp_sdc(place_site, pdk_version) + self.execute_cmd( + "CORE_UTILIZATION", + exp_util, + place_site=place_site, + pdk_version=pdk_version, + front_end=front_end, + ) self.execute_cmd( "SDC_FILE", exp_sdc, @@ -87,7 +109,15 @@ def test_pdk_0p2a(self): pdk_version = "0.2a" for front_end in self._front_end_list: for place_site in self._synopsys_site_list: + exp_util = self.get_exp_util(place_site, pdk_version) exp_sdc = self.get_exp_sdc(place_site, pdk_version) + self.execute_cmd( + "CORE_UTILIZATION", + exp_util, + place_site=place_site, + pdk_version=pdk_version, + front_end=front_end, + ) self.execute_cmd( "SDC_FILE", exp_sdc, @@ -104,7 +134,40 @@ def test_pdk_0p15(self): pdk_version = "0.15" for front_end in self._front_end_list: for place_site in self._synopsys_site_list: + exp_util = self.get_exp_util(place_site, pdk_version) exp_sdc = self.get_exp_sdc(place_site, pdk_version) + self.execute_cmd( + "CORE_UTILIZATION", + exp_util, + place_site=place_site, + pdk_version=pdk_version, + front_end=front_end, + ) + self.execute_cmd( + "SDC_FILE", + exp_sdc, + place_site=place_site, + pdk_version=pdk_version, + front_end=front_end, + ) + + def test_pdk_0p3s(self): + """ + Tests PDK 0.3s utilization + """ + + pdk_version = "0.3s" + for front_end in self._front_end_list: + for place_site in self._synopsys_site_list: + exp_util = self.get_exp_util(place_site, pdk_version) + exp_sdc = self.get_exp_sdc(place_site, pdk_version) + self.execute_cmd( + "CORE_UTILIZATION", + exp_util, + place_site=place_site, + pdk_version=pdk_version, + front_end=front_end, + ) self.execute_cmd( "SDC_FILE", exp_sdc, @@ -121,7 +184,15 @@ def test_pdk_0p3(self): pdk_version = "0.3" for front_end in self._front_end_list: for place_site in self._synopsys_site_list: + exp_util = self.get_exp_util(place_site, pdk_version) exp_sdc = self.get_exp_sdc(place_site, pdk_version) + self.execute_cmd( + "CORE_UTILIZATION", + exp_util, + place_site=place_site, + pdk_version=pdk_version, + front_end=front_end, + ) self.execute_cmd( "SDC_FILE", exp_sdc, diff --git a/flow/designs/sky130hd/aes/rules-base.json b/flow/designs/sky130hd/aes/rules-base.json index 35d8773839..2721f12272 100644 --- a/flow/designs/sky130hd/aes/rules-base.json +++ b/flow/designs/sky130hd/aes/rules-base.json @@ -12,7 +12,7 @@ "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 20599, + "value": 20235, "compare": "<=" }, "detailedplace__design__violations": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -1.24, + "value": -0.854, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -20.3, + "value": -14.4, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -1.03, + "value": -0.767, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -8.65, + "value": -7.56, "compare": ">=" }, "finish__timing__hold__ws": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 155682, + "value": 146144, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/sky130hd/chameleon/config.mk b/flow/designs/sky130hd/chameleon/config.mk index d02447831b..2048ec0f03 100644 --- a/flow/designs/sky130hd/chameleon/config.mk +++ b/flow/designs/sky130hd/chameleon/config.mk @@ -33,23 +33,20 @@ export CORE_UTILIZATION = 70 export CORE_ASPECT_RATIO = 1.3 export CORE_MARGIN = 2 -export chameleon_DIR = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME) +export LEC_AUX_VERILOG_FILES = $(DESIGN_DIR)/lec_blackbox_stubs.v -export ADDITIONAL_GDS = $(chameleon_DIR)/gds/apb_sys_0.gds.gz \ - $(chameleon_DIR)/gds/DMC_32x16HC.gds.gz \ - $(chameleon_DIR)/gds/DFFRAM_4K.gds.gz \ - $(chameleon_DIR)/gds/ibex_wrapper.gds.gz +export ADDITIONAL_GDS = $(DESIGN_DIR)/gds/apb_sys_0.gds.gz \ + $(DESIGN_DIR)/gds/DMC_32x16HC.gds.gz \ + $(DESIGN_DIR)/gds/DFFRAM_4K.gds.gz \ + $(DESIGN_DIR)/gds/ibex_wrapper.gds.gz -export ADDITIONAL_LEFS = $(chameleon_DIR)/lef/apb_sys_0.lef \ - $(chameleon_DIR)/lef/DFFRAM_4K.lef \ - $(chameleon_DIR)/lef/DMC_32x16HC.lef \ - $(chameleon_DIR)/lef/ibex_wrapper.lef +export ADDITIONAL_LEFS = $(DESIGN_DIR)/lef/apb_sys_0.lef \ + $(DESIGN_DIR)/lef/DFFRAM_4K.lef \ + $(DESIGN_DIR)/lef/DMC_32x16HC.lef \ + $(DESIGN_DIR)/lef/ibex_wrapper.lef -#export MACRO_PLACEMENT_TCL = $(chameleon_DIR)/macro_placement.tcl +#export MACRO_PLACEMENT_TCL = $(DESIGN_DIR)/macro_placement.tcl export FP_PDN_RAIL_WIDTH = 0.48 export FP_PDN_RAIL_OFFSET = 0 export TNS_END_PERCENT = 100 - -export LEC_CHECK = 0 - diff --git a/flow/designs/sky130hd/chameleon/lec_blackbox_stubs.v b/flow/designs/sky130hd/chameleon/lec_blackbox_stubs.v new file mode 100644 index 0000000000..8375c8dd33 --- /dev/null +++ b/flow/designs/sky130hd/chameleon/lec_blackbox_stubs.v @@ -0,0 +1,143 @@ +module DFFRAM_4K ( + CLK, + WE, + EN, + Di, + Do, + A +); + input CLK; + input [3:0] WE; + input EN; + input [31:0] Di; + output [31:0] Do; + input [9:0] A; +endmodule + +module DMC_32x16HC ( + clk, + rst_n, + A, + A_h, + Do, + hit, + line, + wr +); + input clk; + input rst_n; + input [23:0] A; + input [23:0] A_h; + output [31:0] Do; + output hit; + input [127:0] line; + input wr; +endmodule + +module ibex_wrapper ( + HCLK, + HRESETn, + HADDR, + HSIZE, + HTRANS, + HWDATA, + HWRITE, + HRDATA, + HREADY, + NMI, + EXT_IRQ, + IRQ, + SYSTICKCLKDIV +); + input HCLK; + input HRESETn; + output [31:0] HADDR; + output [2:0] HSIZE; + output [1:0] HTRANS; + output [31:0] HWDATA; + output HWRITE; + input [31:0] HRDATA; + input HREADY; + input NMI; + input EXT_IRQ; + input [14:0] IRQ; + input [23:0] SYSTICKCLKDIV; +endmodule + +module apb_sys_0 ( + HCLK, + HRESETn, + HADDR, + HTRANS, + HWRITE, + HWDATA, + HSEL, + HREADY, + HRDATA, + HREADYOUT, + RsRx_S0, + RsTx_S0, + RsRx_S1, + RsTx_S1, + MSI_S2, + MSO_S2, + SSn_S2, + SCLK_S2, + MSI_S3, + MSO_S3, + SSn_S3, + SCLK_S3, + scl_i_S4, + scl_o_S4, + scl_oen_o_S4, + sda_i_S4, + sda_o_S4, + sda_oen_o_S4, + scl_i_S5, + scl_o_S5, + scl_oen_o_S5, + sda_i_S5, + sda_o_S5, + sda_oen_o_S5, + pwm_S6, + pwm_S7, + IRQ +); + input HCLK; + input HRESETn; + input [31:0] HADDR; + input [1:0] HTRANS; + input HWRITE; + input [31:0] HWDATA; + input HSEL; + input HREADY; + output [31:0] HRDATA; + output HREADYOUT; + input [0:0] RsRx_S0; + output [0:0] RsTx_S0; + input [0:0] RsRx_S1; + output [0:0] RsTx_S1; + input [0:0] MSI_S2; + output [0:0] MSO_S2; + output [0:0] SSn_S2; + output [0:0] SCLK_S2; + input [0:0] MSI_S3; + output [0:0] MSO_S3; + output [0:0] SSn_S3; + output [0:0] SCLK_S3; + input [0:0] scl_i_S4; + output [0:0] scl_o_S4; + output [0:0] scl_oen_o_S4; + input [0:0] sda_i_S4; + output [0:0] sda_o_S4; + output [0:0] sda_oen_o_S4; + input [0:0] scl_i_S5; + output [0:0] scl_o_S5; + output [0:0] scl_oen_o_S5; + input [0:0] sda_i_S5; + output [0:0] sda_o_S5; + output [0:0] sda_oen_o_S5; + output [0:0] pwm_S6; + output [0:0] pwm_S7; + output [15:0] IRQ; +endmodule diff --git a/flow/designs/sky130hd/chameleon/rules-base.json b/flow/designs/sky130hd/chameleon/rules-base.json index 79dae8637f..96373615bf 100644 --- a/flow/designs/sky130hd/chameleon/rules-base.json +++ b/flow/designs/sky130hd/chameleon/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -4.65, + "value": -3.88, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -205.0, + "value": -125.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -44,15 +44,15 @@ "compare": ">=" }, "globalroute__antenna_diodes_count": { - "value": 188, + "value": 122, "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -4.17, + "value": -3.77, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -200.0, + "value": -86.7, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 680445, + "value": 788362, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -72,19 +72,19 @@ "compare": "<=" }, "detailedroute__antenna__violating__nets": { - "value": 4, + "value": 0, "compare": "<=" }, "detailedroute__antenna_diodes_count": { - "value": 218, + "value": 159, "compare": "<=" }, "finish__timing__setup__ws": { - "value": -3.79, + "value": -3.59, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -183.0, + "value": -79.8, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/sky130hd/gcd/config.mk b/flow/designs/sky130hd/gcd/config.mk index 9b725dcf0b..66f35db996 100644 --- a/flow/designs/sky130hd/gcd/config.mk +++ b/flow/designs/sky130hd/gcd/config.mk @@ -11,3 +11,6 @@ export CORE_UTILIZATION = 40 export TNS_END_PERCENT = 100 export EQUIVALENCE_CHECK ?= 1 export REMOVE_CELLS_FOR_EQY = sky130_fd_sc_hd__tapvpwrvgnd* + +export SWAP_ARITH_OPERATORS = 1 +export OPENROAD_HIERARCHICAL = 1 diff --git a/flow/designs/sky130hd/gcd/rules-base.json b/flow/designs/sky130hd/gcd/rules-base.json index 197be97c8d..0b617790b3 100644 --- a/flow/designs/sky130hd/gcd/rules-base.json +++ b/flow/designs/sky130hd/gcd/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -2.27, + "value": -1.82, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -95.5, + "value": -77.3, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -2.42, + "value": -1.91, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -99.7, + "value": -85.4, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 8194, + "value": 14932, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -2.28, + "value": -1.8, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -92.8, + "value": -80.8, "compare": ">=" }, "finish__timing__hold__ws": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 4986, + "value": 5797, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/sky130hd/ibex/BUILD.bazel b/flow/designs/sky130hd/ibex/BUILD.bazel deleted file mode 100644 index 08f7adc3e6..0000000000 --- a/flow/designs/sky130hd/ibex/BUILD.bazel +++ /dev/null @@ -1,23 +0,0 @@ -load("@bazel-orfs//:openroad.bzl", "orfs_flow") - -orfs_flow( - name = "ibex", - arguments = { - "ADDER_MAP_FILE": "", - "CORE_UTILIZATION": "45", - "PLACE_DENSITY_LB_ADDON": "0.25", - "TNS_END_PERCENT": "100", - "REMOVE_ABC_BUFFERS": "1", - "SYNTH_HDL_FRONTEND": "slang", - "VERILOG_INCLUDE_DIRS": "flow/designs/src/ibex_sv/vendor/lowrisc_ip/prim/rtl", - "CTS_CLUSTER_SIZE": "20", - "CTS_CLUSTER_DIAMETER": "50", - }, - pdk = "@docker_orfs//:sky130hd", - sources = { - "SDC_FILE": [":constraint.sdc"], - "FASTROUTE_TCL": ["fastroute.tcl"], - }, - top = "ibex_core", - verilog_files = ["//flow/designs/src/ibex_sv:verilog"], -) diff --git a/flow/designs/sky130hd/ibex/config.mk b/flow/designs/sky130hd/ibex/config.mk index 8e4c3764b5..028ddd21cd 100644 --- a/flow/designs/sky130hd/ibex/config.mk +++ b/flow/designs/sky130hd/ibex/config.mk @@ -15,7 +15,7 @@ export SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint. # Adders degrade ibex setup repair export ADDER_MAP_FILE := -export CORE_UTILIZATION = 45 +export CORE_UTILIZATION = 50 export PLACE_DENSITY_LB_ADDON = 0.25 export TNS_END_PERCENT = 100 @@ -29,5 +29,3 @@ export CTS_CLUSTER_DIAMETER = 50 export SWAP_ARITH_OPERATORS = 1 export OPENROAD_HIERARCHICAL = 1 - -export LEC_CHECK = 0 diff --git a/flow/designs/sky130hd/ibex/rules-base.json b/flow/designs/sky130hd/ibex/rules-base.json index 4be669d3f9..429672309c 100644 --- a/flow/designs/sky130hd/ibex/rules-base.json +++ b/flow/designs/sky130hd/ibex/rules-base.json @@ -8,7 +8,7 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 169126, + "value": 167557, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.533, + "value": -0.505, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -2.05, + "value": -2.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -52,7 +52,7 @@ "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -2.37, + "value": -2.82, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 749863, + "value": 728653, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 180708, + "value": 179425, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/sky130hd/jpeg/fastroute.tcl b/flow/designs/sky130hd/jpeg/fastroute.tcl index e795f5e820..76f9321967 100644 --- a/flow/designs/sky130hd/jpeg/fastroute.tcl +++ b/flow/designs/sky130hd/jpeg/fastroute.tcl @@ -1,4 +1,4 @@ -set_global_routing_layer_adjustment $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER) 0.3 +set_global_routing_layer_adjustment $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER) 0.2 set_routing_layers -clock $::env(MIN_CLK_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER) set_routing_layers -signal $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER) diff --git a/flow/designs/sky130hd/jpeg/rules-base.json b/flow/designs/sky130hd/jpeg/rules-base.json index ed2cd5869b..b44db29b9e 100644 --- a/flow/designs/sky130hd/jpeg/rules-base.json +++ b/flow/designs/sky130hd/jpeg/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 463729.45, + "value": 463000.0, "compare": "<=" }, "constraints__clocks__count": { @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.605, + "value": -0.781, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -55.8, + "value": -110.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -44,7 +44,7 @@ "compare": ">=" }, "globalroute__antenna_diodes_count": { - "value": 122, + "value": 100, "compare": "<=" }, "globalroute__timing__setup__ws": { @@ -52,7 +52,7 @@ "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -153.0, + "value": -185.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -76,7 +76,7 @@ "compare": "<=" }, "detailedroute__antenna_diodes_count": { - "value": 100, + "value": 118, "compare": "<=" }, "finish__timing__setup__ws": { @@ -84,7 +84,7 @@ "compare": ">=" }, "finish__timing__setup__tns": { - "value": -60.6, + "value": -90.0, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/sky130hd/microwatt/config.mk b/flow/designs/sky130hd/microwatt/config.mk index 56ba3efb8d..e6cc7dfe74 100644 --- a/flow/designs/sky130hd/microwatt/config.mk +++ b/flow/designs/sky130hd/microwatt/config.mk @@ -11,13 +11,11 @@ export SDC_FILE = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME)/constraint. export DIE_AREA = 0 0 3020 3610 export CORE_AREA = 10 10 3010 3600 -export microwatt_DIR = $(DESIGN_HOME)/$(PLATFORM)/$(DESIGN_NICKNAME) +export ADDITIONAL_GDS = $(wildcard $(DESIGN_DIR)/gds/*.gds.gz) -export ADDITIONAL_GDS = $(wildcard $(microwatt_DIR)/gds/*.gds.gz) +export ADDITIONAL_LEFS = $(wildcard $(DESIGN_DIR)/lef/*.lef) -export ADDITIONAL_LEFS = $(wildcard $(microwatt_DIR)/lef/*.lef) - -export ADDITIONAL_LIBS = $(wildcard $(microwatt_DIR)/lib/*.lib) +export ADDITIONAL_LIBS = $(wildcard $(DESIGN_DIR)/lib/*.lib) export SYNTH_HIERARCHICAL = 1 @@ -51,5 +49,3 @@ endif export SWAP_ARITH_OPERATORS = 1 export OPENROAD_HIERARCHICAL = 1 - -export LEC_CHECK = 0 diff --git a/flow/designs/sky130hd/microwatt/rules-base.json b/flow/designs/sky130hd/microwatt/rules-base.json index 466cd2ae65..15d7239d50 100644 --- a/flow/designs/sky130hd/microwatt/rules-base.json +++ b/flow/designs/sky130hd/microwatt/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -2.6, + "value": -2.1, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -300.0, + "value": -211.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -44,15 +44,15 @@ "compare": ">=" }, "globalroute__antenna_diodes_count": { - "value": 2531, + "value": 2635, "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -2.59, + "value": -2.2, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -304.0, + "value": -220.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -76,23 +76,23 @@ "compare": "<=" }, "detailedroute__antenna_diodes_count": { - "value": 2095, + "value": 1724, "compare": "<=" }, "finish__timing__setup__ws": { - "value": -2.22, + "value": -1.34, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -183.0, + "value": -61.5, "compare": ">=" }, "finish__timing__hold__ws": { - "value": -1.68, + "value": -1.6, "compare": ">=" }, "finish__timing__hold__tns": { - "value": -46.5, + "value": -22.1, "compare": ">=" }, "finish__design__instance__area": { diff --git a/flow/designs/sky130hd/riscv32i/rules-base.json b/flow/designs/sky130hd/riscv32i/rules-base.json index f44a048e24..7fcf2c4ece 100644 --- a/flow/designs/sky130hd/riscv32i/rules-base.json +++ b/flow/designs/sky130hd/riscv32i/rules-base.json @@ -12,7 +12,7 @@ "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 8498, + "value": 8393, "compare": "<=" }, "detailedplace__design__violations": { @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -1.66, + "value": -1.07, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -55.4, + "value": -15.4, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -1.77, + "value": -1.19, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -140.0, + "value": -16.2, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -1.71, + "value": -1.06, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -69.3, + "value": -11.6, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/sky130hs/aes/rules-base.json b/flow/designs/sky130hs/aes/rules-base.json index 3c5c70764f..3c79d79eef 100644 --- a/flow/designs/sky130hs/aes/rules-base.json +++ b/flow/designs/sky130hs/aes/rules-base.json @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -0.244, + "value": -0.224, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -2.99, + "value": -1.92, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -0.241, + "value": -0.15, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -0.826, + "value": -0.57, "compare": ">=" }, "finish__timing__hold__ws": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 177126, + "value": 176489, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/sky130hs/gcd/rules-base.json b/flow/designs/sky130hs/gcd/rules-base.json index 37d58a53e7..5fb40f5dfc 100644 --- a/flow/designs/sky130hs/gcd/rules-base.json +++ b/flow/designs/sky130hs/gcd/rules-base.json @@ -1,6 +1,6 @@ { "synth__design__instance__area__stdcell": { - "value": 4532.91, + "value": 4470.0, "compare": "<=" }, "constraints__clocks__count": { @@ -8,11 +8,11 @@ "compare": "==" }, "placeopt__design__instance__area": { - "value": 6389, + "value": 6112, "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 721, + "value": 715, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,7 +20,7 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 63, + "value": 62, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { @@ -32,7 +32,7 @@ "compare": ">=" }, "cts__timing__setup__tns": { - "value": -10.8, + "value": -11.4, "compare": ">=" }, "cts__timing__hold__ws": { @@ -52,7 +52,7 @@ "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -18.3, + "value": -19.2, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -84,7 +84,7 @@ "compare": ">=" }, "finish__timing__setup__tns": { - "value": -14.6, + "value": -15.8, "compare": ">=" }, "finish__timing__hold__ws": { @@ -96,7 +96,7 @@ "compare": ">=" }, "finish__design__instance__area": { - "value": 7546, + "value": 7136, "compare": "<=" } } \ No newline at end of file diff --git a/flow/designs/sky130hs/ibex/rules-base.json b/flow/designs/sky130hs/ibex/rules-base.json index 48fc308608..40be0a8a5f 100644 --- a/flow/designs/sky130hs/ibex/rules-base.json +++ b/flow/designs/sky130hs/ibex/rules-base.json @@ -52,7 +52,7 @@ "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -41.0, + "value": -114.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -84,7 +84,7 @@ "compare": ">=" }, "finish__timing__setup__tns": { - "value": -1.4, + "value": -19.8, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/sky130hs/jpeg/rules-base.json b/flow/designs/sky130hs/jpeg/rules-base.json index b02ae82360..e3dc5ecd4b 100644 --- a/flow/designs/sky130hs/jpeg/rules-base.json +++ b/flow/designs/sky130hs/jpeg/rules-base.json @@ -12,7 +12,7 @@ "compare": "<=" }, "placeopt__design__instance__count__stdcell": { - "value": 56059, + "value": 56019, "compare": "<=" }, "detailedplace__design__violations": { @@ -20,11 +20,11 @@ "compare": "==" }, "cts__design__instance__count__setup_buffer": { - "value": 4875, + "value": 4871, "compare": "<=" }, "cts__design__instance__count__hold_buffer": { - "value": 4875, + "value": 4871, "compare": "<=" }, "cts__timing__setup__ws": { @@ -44,7 +44,7 @@ "compare": ">=" }, "globalroute__antenna_diodes_count": { - "value": 193, + "value": 100, "compare": "<=" }, "globalroute__timing__setup__ws": { diff --git a/flow/designs/sky130hs/riscv32i/fastroute.tcl b/flow/designs/sky130hs/riscv32i/fastroute.tcl index 8b8e48cc4b..d125e6f179 100644 --- a/flow/designs/sky130hs/riscv32i/fastroute.tcl +++ b/flow/designs/sky130hs/riscv32i/fastroute.tcl @@ -1,3 +1,3 @@ -set_global_routing_layer_adjustment $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER) 0.30 +set_global_routing_layer_adjustment $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER) 0.20 set_routing_layers -signal $::env(MIN_ROUTING_LAYER)-$::env(MAX_ROUTING_LAYER) diff --git a/flow/designs/sky130hs/riscv32i/rules-base.json b/flow/designs/sky130hs/riscv32i/rules-base.json index d56e3d7fa5..e7141d363c 100644 --- a/flow/designs/sky130hs/riscv32i/rules-base.json +++ b/flow/designs/sky130hs/riscv32i/rules-base.json @@ -28,11 +28,11 @@ "compare": "<=" }, "cts__timing__setup__ws": { - "value": -0.854, + "value": -0.786, "compare": ">=" }, "cts__timing__setup__tns": { - "value": -293.0, + "value": -183.0, "compare": ">=" }, "cts__timing__hold__ws": { @@ -48,11 +48,11 @@ "compare": "<=" }, "globalroute__timing__setup__ws": { - "value": -1.19, + "value": -1.15, "compare": ">=" }, "globalroute__timing__setup__tns": { - "value": -832.0, + "value": -406.0, "compare": ">=" }, "globalroute__timing__hold__ws": { @@ -64,7 +64,7 @@ "compare": ">=" }, "detailedroute__route__wirelength": { - "value": 352098, + "value": 351774, "compare": "<=" }, "detailedroute__route__drc_errors": { @@ -80,11 +80,11 @@ "compare": "<=" }, "finish__timing__setup__ws": { - "value": -1.01, + "value": -0.876, "compare": ">=" }, "finish__timing__setup__tns": { - "value": -514.0, + "value": -207.0, "compare": ">=" }, "finish__timing__hold__ws": { diff --git a/flow/designs/src/aes/BUILD.bazel b/flow/designs/src/aes/BUILD.bazel deleted file mode 100644 index 1639cf0a3b..0000000000 --- a/flow/designs/src/aes/BUILD.bazel +++ /dev/null @@ -1,5 +0,0 @@ -filegroup( - name = "verilog", - srcs = glob(include = ["*.v"]), - visibility = ["//visibility:public"], -) diff --git a/flow/designs/src/chameleon/IPs/APB_UART.v b/flow/designs/src/chameleon/IPs/APB_UART.v index daddc6e182..2ac3a22935 100644 --- a/flow/designs/src/chameleon/IPs/APB_UART.v +++ b/flow/designs/src/chameleon/IPs/APB_UART.v @@ -142,7 +142,7 @@ module APB_UART( 32'hDEADDEAD; wire tx_less_threshold = (tx_level < TXFIFOTR); - wire rx_more_threshold = (rx_level > TXFIFOTR); + wire rx_more_threshold = (rx_level > RXFIFOTR); assign uart_irq = IMASK[0] & ( (~rx_empty & IMASK[2]) | diff --git a/flow/designs/src/cva6/core/cache_subsystem/cva6_hpdcache_if_adapter.sv b/flow/designs/src/cva6/core/cache_subsystem/cva6_hpdcache_if_adapter.sv index d9e9f23316..5d3144b894 100644 --- a/flow/designs/src/cva6/core/cache_subsystem/cva6_hpdcache_if_adapter.sv +++ b/flow/designs/src/cva6/core/cache_subsystem/cva6_hpdcache_if_adapter.sv @@ -114,6 +114,9 @@ module cva6_hpdcache_if_adapter assign cva6_req_o.data_rdata = hpdcache_rsp_i.rdata; assign cva6_req_o.data_rid = hpdcache_rsp_i.tid; assign cva6_req_o.data_gnt = hpdcache_req_ready_i; + assign cva6_req_o.data_ruser = '0; + assign cva6_amo_resp_o = '0; + assign cva6_dcache_flush_ack_o = 1'b0; // Assertions // {{{ @@ -317,6 +320,7 @@ module cva6_hpdcache_if_adapter assign cva6_req_o.data_rdata = hpdcache_rsp_i.rdata; assign cva6_req_o.data_rid = hpdcache_rsp_i.tid; assign cva6_req_o.data_gnt = hpdcache_req_ready_i; + assign cva6_req_o.data_ruser = '0; assign cva6_amo_resp_o.ack = hpdcache_rsp_valid_i && (hpdcache_rsp_i.tid == '1); assign cva6_amo_resp_o.result = amo_is_word ? {{32{amo_resp_word[31]}}, amo_resp_word} diff --git a/flow/designs/src/cva6/core/cache_subsystem/cva6_hpdcache_wrapper.sv b/flow/designs/src/cva6/core/cache_subsystem/cva6_hpdcache_wrapper.sv index 7727dc703d..424024afbd 100644 --- a/flow/designs/src/cva6/core/cache_subsystem/cva6_hpdcache_wrapper.sv +++ b/flow/designs/src/cva6/core/cache_subsystem/cva6_hpdcache_wrapper.sv @@ -248,7 +248,8 @@ module cva6_hpdcache_wrapper dcache_req[NumPorts] = '0, dcache_req_abort[NumPorts] = 1'b0, dcache_req_tag[NumPorts] = '0, - dcache_req_pma[NumPorts] = '0; + dcache_req_pma[NumPorts] = '0, + dcache_cmo_resp_o = '0; `endif endgenerate diff --git a/flow/designs/src/cva6/core/cache_subsystem/hpdcache/rtl/src/hwpf_stride/hwpf_stride.sv b/flow/designs/src/cva6/core/cache_subsystem/hpdcache/rtl/src/hwpf_stride/hwpf_stride.sv index fd846bd915..40e078a592 100644 --- a/flow/designs/src/cva6/core/cache_subsystem/hpdcache/rtl/src/hwpf_stride/hwpf_stride.sv +++ b/flow/designs/src/cva6/core/cache_subsystem/hpdcache/rtl/src/hwpf_stride/hwpf_stride.sv @@ -147,7 +147,8 @@ import hpdcache_pkg::*; hpdcache_req_o.phys_indexed = 1'b1, hpdcache_req_o.addr_tag = hpdcache_req_tag, hpdcache_req_o.pma.uncacheable = 1'b0, - hpdcache_req_o.pma.io = 1'b0; + hpdcache_req_o.pma.io = 1'b0, + hpdcache_req_o.pma.wr_policy_hint = HPDCACHE_WR_POLICY_AUTO; // }}} // Set state of internal registers diff --git a/flow/designs/src/cva6/core/csr_regfile.sv b/flow/designs/src/cva6/core/csr_regfile.sv index 7bbf529048..321ac78f1f 100644 --- a/flow/designs/src/cva6/core/csr_regfile.sv +++ b/flow/designs/src/cva6/core/csr_regfile.sv @@ -2531,7 +2531,7 @@ module csr_regfile // determine if mprv needs to be considered if in debug mode assign mprv = (CVA6Cfg.DebugEn && debug_mode_q && !dcsr_q.mprven) ? 1'b0 : mstatus_q.mprv; - assign debug_mode_o = debug_mode_q; + assign debug_mode_o = CVA6Cfg.DebugEn ? debug_mode_q : 1'b0; assign single_step_o = CVA6Cfg.DebugEn ? dcsr_q.step : 1'b0; assign mcountinhibit_o = {{29 - MHPMCounterNum{1'b0}}, mcountinhibit_q}; diff --git a/flow/designs/src/cva6/core/cva6_mmu/cva6_mmu.sv b/flow/designs/src/cva6/core/cva6_mmu/cva6_mmu.sv index eebb9b6e46..9f84448b8b 100644 --- a/flow/designs/src/cva6/core/cva6_mmu/cva6_mmu.sv +++ b/flow/designs/src/cva6/core/cva6_mmu/cva6_mmu.sv @@ -528,6 +528,8 @@ module cva6_mmu ((ld_st_priv_lvl_i == riscv::PRIV_LVL_S && (ld_st_v_i ? !vs_sum_i : !sum_i ) && dtlb_pte_q.u) || // SUM is not set and we are trying to access a user page in supervisor mode (ld_st_priv_lvl_i == riscv::PRIV_LVL_U && !dtlb_pte_q.u)); + csr_hs_ld_st_inst_o = 1'b0; + if (CVA6Cfg.RVH) begin lsu_tinst_n = lsu_tinst_i; hs_ld_st_inst_n = hs_ld_st_inst_i; diff --git a/flow/designs/src/cva6/core/cvxif_fu.sv b/flow/designs/src/cva6/core/cvxif_fu.sv index cf6ee15215..515e9c28cc 100644 --- a/flow/designs/src/cva6/core/cvxif_fu.sv +++ b/flow/designs/src/cva6/core/cvxif_fu.sv @@ -64,6 +64,7 @@ module cvxif_fu // Handling of illegal instruction exception always_comb begin + x_exception_o = '0; x_exception_o.valid = x_illegal_i; x_exception_o.cause = x_illegal_i ? riscv::ILLEGAL_INSTR : '0; if (CVA6Cfg.TvalEn) diff --git a/flow/designs/src/cva6/core/id_stage.sv b/flow/designs/src/cva6/core/id_stage.sv index d37554db4f..2f6f312ad2 100644 --- a/flow/designs/src/cva6/core/id_stage.sv +++ b/flow/designs/src/cva6/core/id_stage.sv @@ -229,6 +229,7 @@ module id_stage #( assign is_compressed_zcmt = is_compressed_rvc; assign stall_macro_deco_zcmt = '0; assign jump_address = '0; + assign dcache_req_ports_o = '0; end if (CVA6Cfg.RVZCMT) begin diff --git a/flow/designs/src/cva6/core/load_store_unit.sv b/flow/designs/src/cva6/core/load_store_unit.sv index ccce630112..6279b1d17f 100644 --- a/flow/designs/src/cva6/core/load_store_unit.sv +++ b/flow/designs/src/cva6/core/load_store_unit.sv @@ -349,13 +349,16 @@ module load_store_unit assign dcache_req_ports_o[0].address_index = '0; assign dcache_req_ports_o[0].address_tag = '0; assign dcache_req_ports_o[0].data_wdata = '0; + assign dcache_req_ports_o[0].data_wuser = '0; assign dcache_req_ports_o[0].data_req = 1'b0; assign dcache_req_ports_o[0].data_be = '1; assign dcache_req_ports_o[0].data_size = 2'b11; + assign dcache_req_ports_o[0].data_id = '0; assign dcache_req_ports_o[0].data_we = 1'b0; assign dcache_req_ports_o[0].kill_req = '0; assign dcache_req_ports_o[0].tag_valid = 1'b0; + assign csr_hs_ld_st_inst_o = 1'b0; assign itlb_miss_o = 1'b0; assign dtlb_miss_o = 1'b0; assign dtlb_ppn = lsu_paddr[CVA6Cfg.PLEN-1:12]; diff --git a/flow/designs/src/cva6/core/load_unit.sv b/flow/designs/src/cva6/core/load_unit.sv index 0a66c51062..ef10d231d7 100644 --- a/flow/designs/src/cva6/core/load_unit.sv +++ b/flow/designs/src/cva6/core/load_unit.sv @@ -196,6 +196,7 @@ module load_unit // this is a read-only interface so set the write enable to 0 assign req_port_o.data_we = 1'b0; assign req_port_o.data_wdata = '0; + assign req_port_o.data_wuser = '0; // compose the load buffer write data, control is handled in the FSM assign ldbuf_wdata = { lsu_ctrl_i.trans_id, lsu_ctrl_i.vaddr[CVA6Cfg.XLEN_ALIGN_BYTES-1:0], lsu_ctrl_i.operation diff --git a/flow/designs/src/ethmac/BUILD.bazel b/flow/designs/src/ethmac/BUILD.bazel deleted file mode 100644 index 1639cf0a3b..0000000000 --- a/flow/designs/src/ethmac/BUILD.bazel +++ /dev/null @@ -1,5 +0,0 @@ -filegroup( - name = "verilog", - srcs = glob(include = ["*.v"]), - visibility = ["//visibility:public"], -) diff --git a/flow/designs/src/gcd/BUILD.bazel b/flow/designs/src/gcd/BUILD.bazel deleted file mode 100644 index 1639cf0a3b..0000000000 --- a/flow/designs/src/gcd/BUILD.bazel +++ /dev/null @@ -1,5 +0,0 @@ -filegroup( - name = "verilog", - srcs = glob(include = ["*.v"]), - visibility = ["//visibility:public"], -) diff --git a/flow/designs/src/ibex_sv/BUILD.bazel b/flow/designs/src/ibex_sv/BUILD.bazel deleted file mode 100644 index 964365b4e1..0000000000 --- a/flow/designs/src/ibex_sv/BUILD.bazel +++ /dev/null @@ -1,9 +0,0 @@ -filegroup( - name = "verilog", - srcs = glob(include = [ - "**/*.sv", - "**/*.svh", - "**/*.v", - ]), - visibility = ["//visibility:public"], -) diff --git a/flow/designs/src/mock-alu/plot-area-min-clock-period.py b/flow/designs/src/mock-alu/plot-area-min-clock-period.py deleted file mode 100644 index 76e2e630b4..0000000000 --- a/flow/designs/src/mock-alu/plot-area-min-clock-period.py +++ /dev/null @@ -1,161 +0,0 @@ -import subprocess -import os -import re -from matplotlib import pyplot as plt -import numpy as np -from matplotlib import cm -import itertools -import argparse - - -def run(platform): - test_design = "make DESIGN_CONFIG=designs/asap7/mock-alu/config.mk" - - values = {} - - # measure three variables at the time. - measurements = { - # "datawidth": (("MOCK_ALU_WIDTH",), (8, 16, 32, 64)), - "operations": ( - ("MOCK_ALU_OPERATIONS",), - ( - "ADD", - "ADD_BRENTKUNG", - "ADD_HANCARLSON", - "ADD_INFERRED", - "ADD_KOGGESTONE", - # "ADD_RIPPLE", - # "MULT_BRENTKUNG", - # "MULT_HANCARLSON", - # "MULT_INFERRED", - # "MULT_KOGGESTONE", - # "MULT_RIPPLE", - # "MULT_HANCARLSON16", - # "MULT_HANCARLSON32", - # "MULT_HANCARLSON48", - # "MULT_HANCARLSON64", - # "MULT_HANCARLSON128", - # "ADD", - # "CLAADD", - # "KOGGESTONEADD", - # "ADD8", - # "ADD16", - # "ADD32", - # "MUX1,MUX2", - # "MUX1,MUX2,MUX3,MUX4", - # "MUX1,MUX2,MUX3,MUX4,MUX5,MUX6,MUX7,MUX8", - # "ADD", - # "AND,OR,XOR", - # "OR", - # "SHL,SHR,SRA", - # "ADD,SUB,SETCC_EQ,SETCC_NE,SETCC_LT,SETCC_ULT,SETCC_LE,SETCC_ULE", - # "MULT", - # "AND,OR,XOR,SHL,SHR,SRA,ADD,SUB,SETCC_EQ,SETCC_NE,SETCC_LT,SETCC_ULT,SETCC_LE,SETCC_ULE", - # "AND,OR,XOR,SHL,SHR,SRA,ADD,SUB,SETCC_EQ,SETCC_NE,SETCC_LT,SETCC_ULT,SETCC_LE,SETCC_ULE,MULT", - ), - ), - } - measure_ids = sorted(measurements.keys()) - - for measurement in itertools.product( - *map(lambda key: measurements[key][1], measure_ids) - ): - variant = "-".join(map(str, measurement)).replace(" ", "-") - print(f"testing {variant}") - env_change = {"FLOW_VARIANT": variant, "PLATFORM": platform} - for e in itertools.chain( - *map( - lambda measure: map( - lambda var: {var: measure[1]}, measurements[measure[0]][0] - ), - zip(measure_ids, measurement), - ) - ): - u = dict(map(lambda item: (item[0], str(item[1])), e.items())) - env_change.update(u) - env = os.environ.copy() - env.update(env_change) - - if not os.path.exists(f"results/{platform}/mock-alu/{variant}/5_route.odb"): - print(f"Measuring {variant}") - for cmd in ( - test_design + " verilog", - test_design + " route", - ): - returncode = subprocess.call(cmd, env=env, shell=True) - if returncode != 0: - print("Skipping variant, doesn't compile: " + variant) - input_string = "report_design_area\nreport_clock_min_period\n" - result = subprocess.check_output( - test_design + " open_route", - shell=True, - env=env, - input=input_string, - text=True, - ) - - m = re.search(r"period_min\s*=\s*(\d+\.\d+)", result) - if m: - min_period = float(m.group(1)) - if m is None: - print("Variant skipped: " + variant) - continue - m = re.search(r"Design area (\d+) u.*", result) - if m: - design_area = float(m.group(1)) - if m is None: - print("Variant skipped: " + variant) - continue - values[measurement] = [min_period, design_area] - - # Splitting the dictionary into x and y coordinates, and labels - x_coords = [value[0] for value in values.values()] - y_coords = [value[1] for value in values.values()] - labels = list(values.keys()) - - # Creating the scatter plot - plt.scatter(x_coords, y_coords, color="red") - - def custom_wrap(text, max_len=20): - line, length = "", 0 - - for part in text.split(","): - if length + len(part) > max_len: - yield line - line, length = part, len(part) - else: - line = f"{line},{part}" if line else part - length += len(part) + 1 - - yield line - - # Annotating each point with its label - for i, label in enumerate(labels): - plt.annotate( - "\n".join(custom_wrap(label[0])), - (x_coords[i], y_coords[i] + 0), - ha="center", - va="bottom", - ) - - # Displaying the plot - units = { - "asap7": "ps", - "sky130hd": "ns", - } - - plt.xlabel(f"minimum period/{units[platform]}") - plt.ylabel("area/u^2") - plt.title(f"{platform} ALU Operations and minimum period and area") - plt.grid(True) - - plt.show() - - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Process some arguments.") - parser.add_argument( - "--platform", default="asap7", help="Specify the platform. Default is asap7." - ) - args = parser.parse_args() - run(args.platform) diff --git a/flow/designs/src/riscv32i/dmem.v b/flow/designs/src/riscv32i/dmem.v index 46f6a58f65..6cda09216e 100755 --- a/flow/designs/src/riscv32i/dmem.v +++ b/flow/designs/src/riscv32i/dmem.v @@ -59,10 +59,10 @@ module dmem (clk, r_w, mem_addr, mem_data, mem_out); always @* begin case (sel_mem) - 2'b00: mem_out = inter_dmem3; - 2'b01: mem_out = inter_dmem2; - 2'b10: mem_out = inter_dmem1; - 2'b11: mem_out = inter_dmem0; + 2'b11: mem_out = inter_dmem3; + 2'b10: mem_out = inter_dmem2; + 2'b01: mem_out = inter_dmem1; + 2'b00: mem_out = inter_dmem0; endcase // case (sel_mem) end diff --git a/flow/designs/src/swerv/BUILD.bazel b/flow/designs/src/swerv/BUILD.bazel deleted file mode 100644 index 1639cf0a3b..0000000000 --- a/flow/designs/src/swerv/BUILD.bazel +++ /dev/null @@ -1,5 +0,0 @@ -filegroup( - name = "verilog", - srcs = glob(include = ["*.v"]), - visibility = ["//visibility:public"], -) diff --git a/flow/docs/KLayoutOptionalDependency.md b/flow/docs/KLayoutOptionalDependency.md new file mode 100644 index 0000000000..c469160a27 --- /dev/null +++ b/flow/docs/KLayoutOptionalDependency.md @@ -0,0 +1,59 @@ +# KLayout as an Optional Dependency + +KLayout is only required for GDS/OAS stream generation, DRC, and LVS +verification. All other ORFS functionality — synthesis, floorplanning, +placement, CTS, routing, timing reports, and abstract generation — works +without KLayout installed. + +## Makefile Targets + +| Target | Requires KLayout | Description | +|---|---|---| +| `make finish` | Yes | Complete flow including GDS generation | +| `make gds` | Yes | Generate GDS/OAS from finished design | +| `make drc` | Yes | Run DRC checks (requires GDS) | +| `make lvs` | Yes | Run LVS checks (requires GDS) | +| `make gallery` | Yes | Generate layout screenshots | +| `make klayout_` | Yes | Open result in KLayout viewer | +| `make generate_abstract` | No | Generate LEF/LIB abstracts | + +A `check-klayout` guard produces a clear error message when KLayout is +missing and a KLayout-dependent target is invoked: + +``` +Error: KLayout not found. Install KLayout or set KLAYOUT_CMD. +Hint: KLayout is needed for GDS/DRC/LVS targets. +``` + +## bazel-orfs Integration + +bazel-orfs uses the `do-` prefixed targets which bypass Make's dependency +management. `do-finish` / `do-final` only run the finish stage recipe +itself, while `make finish` also pulls in the GDS target as a Make +dependency. `do-gds` runs GDS generation separately (requires KLayout). + +An `orfs_gds()` Bazel rule can call `do-gds` independently from +`orfs_flow()`, making KLayout an optional toolchain dependency configured +in `MODULE.bazel`. + +## KLayout Tech File Generation + +The `do-klayout` and `do-klayout_wrap` targets generate `.lyt` technology +files by substituting LEF and map file paths into platform templates. +This is implemented in `util/generate_klayout_tech.py` using stdlib XML +processing — no KLayout dependency required. + +## Testing Without KLayout + +Unit tests for all KLayout-related Python scripts use `unittest.mock` to +mock the `pya` API: + +``` +cd flow/test +python -m unittest test_generate_klayout_tech test_def2stream test_convertDrc +``` + +These tests cover: +- `.lyt` tech file generation (`test_generate_klayout_tech.py`) +- DEF-to-GDS merging logic (`test_def2stream.py`) +- DRC report conversion (`test_convertDrc.py`) diff --git a/flow/scripts/cts.tcl b/flow/scripts/cts.tcl index 293206121d..05f65e8958 100644 --- a/flow/scripts/cts.tcl +++ b/flow/scripts/cts.tcl @@ -3,6 +3,7 @@ source $::env(SCRIPTS_DIR)/load.tcl source $::env(SCRIPTS_DIR)/lec_check.tcl erase_non_stage_variables cts load_design 3_place.odb 3_place.sdc +source_step_tcl PRE CTS # Clone clock tree inverters next to register loads # so cts does not try to buffer the inverted clocks. @@ -86,7 +87,7 @@ if { !$::env(SKIP_CTS_REPAIR_TIMING) } { report_metrics 4 "cts final" -source_env_var_if_exists POST_CTS_TCL +source_step_tcl POST CTS orfs_write_db $::env(RESULTS_DIR)/4_1_cts.odb orfs_write_sdc $::env(RESULTS_DIR)/4_cts.sdc diff --git a/flow/scripts/density_fill.tcl b/flow/scripts/density_fill.tcl index a0f45f7276..8b1d019eab 100644 --- a/flow/scripts/density_fill.tcl +++ b/flow/scripts/density_fill.tcl @@ -1,6 +1,7 @@ source $::env(SCRIPTS_DIR)/load.tcl erase_non_stage_variables final load_design 5_route.odb 5_route.sdc +source_step_tcl PRE DENSITY_FILL if { $::env(USE_FILL) } { set_propagated_clock [all_clocks] @@ -13,3 +14,5 @@ if { $::env(USE_FILL) } { log_cmd exec cp $::env(RESULTS_DIR)/5_route.odb $::env(RESULTS_DIR)/6_1_fill.odb # There is no 5_route.v file to copy } + +source_step_tcl POST DENSITY_FILL diff --git a/flow/scripts/detail_place.tcl b/flow/scripts/detail_place.tcl index 2a0babb8d6..17c14e41bb 100644 --- a/flow/scripts/detail_place.tcl +++ b/flow/scripts/detail_place.tcl @@ -2,6 +2,7 @@ utl::set_metrics_stage "detailedplace__{}" source $::env(SCRIPTS_DIR)/load.tcl erase_non_stage_variables place load_design 3_4_place_resized.odb 2_floorplan.sdc +source_step_tcl PRE DETAIL_PLACE source $::env(PLATFORM_DIR)/setRC.tcl @@ -38,4 +39,6 @@ if { $result != 0 } { report_metrics 3 "detailed place" true false +source_step_tcl POST DETAIL_PLACE + orfs_write_db $::env(RESULTS_DIR)/3_5_place_dp.odb diff --git a/flow/scripts/detail_route.tcl b/flow/scripts/detail_route.tcl index e38a03089c..c3503558f6 100644 --- a/flow/scripts/detail_route.tcl +++ b/flow/scripts/detail_route.tcl @@ -1,6 +1,7 @@ utl::set_metrics_stage "detailedroute__{}" source $::env(SCRIPTS_DIR)/load.tcl load_design 5_1_grt.odb 5_1_grt.sdc +source_step_tcl PRE DETAIL_ROUTE if { ![grt::have_routes] } { error "Global routing failed, run `make gui_grt` and load $::global_route_congestion_report \ in DRC viewer to view congestion" @@ -69,7 +70,7 @@ if { utl::metric_int "antenna_diodes_count" -1 } -source_env_var_if_exists POST_DETAIL_ROUTE_TCL +source_step_tcl POST DETAIL_ROUTE check_antennas -report_file $env(REPORTS_DIR)/drt_antennas.log @@ -77,6 +78,8 @@ if { ![design_is_routed] } { error "Design has unrouted nets." } +report_design_area + # Don't report metrics as we have not extracted parasitics, which will happen # in final so there is no need to repeat it here. diff --git a/flow/scripts/fillcell.tcl b/flow/scripts/fillcell.tcl index ba4b96912e..b778ccb717 100644 --- a/flow/scripts/fillcell.tcl +++ b/flow/scripts/fillcell.tcl @@ -2,13 +2,17 @@ source $::env(SCRIPTS_DIR)/load.tcl erase_non_stage_variables route if { [env_var_exists_and_non_empty FILL_CELLS] } { load_design 5_2_route.odb 5_1_grt.sdc + source_step_tcl PRE FILLCELL set_propagated_clock [all_clocks] log_cmd filler_placement $::env(FILL_CELLS) check_placement + report_design_area orfs_write_db $::env(RESULTS_DIR)/5_3_fillcell.odb } else { log_cmd exec cp $::env(RESULTS_DIR)/5_2_route.odb $::env(RESULTS_DIR)/5_3_fillcell.odb } + +source_step_tcl POST FILLCELL diff --git a/flow/scripts/final_report.tcl b/flow/scripts/final_report.tcl index 928e92bf2b..d81acc986e 100644 --- a/flow/scripts/final_report.tcl +++ b/flow/scripts/final_report.tcl @@ -2,6 +2,7 @@ utl::set_metrics_stage "finish__{}" source $::env(SCRIPTS_DIR)/load.tcl erase_non_stage_variables final load_design 6_1_fill.odb 6_1_fill.sdc +source_step_tcl PRE FINAL_REPORT set_propagated_clock [all_clocks] @@ -63,6 +64,8 @@ report_cell_usage report_metrics 6 "finish" +source_step_tcl POST FINAL_REPORT + # Save a final image if openroad is compiled with the gui if { [ord::openroad_gui_compiled] } { gui::show "source $::env(SCRIPTS_DIR)/save_images.tcl" false diff --git a/flow/scripts/floorplan.tcl b/flow/scripts/floorplan.tcl index c439174bc5..3cb381904c 100644 --- a/flow/scripts/floorplan.tcl +++ b/flow/scripts/floorplan.tcl @@ -2,6 +2,7 @@ utl::set_metrics_stage "floorplan__{}" source $::env(SCRIPTS_DIR)/load.tcl erase_non_stage_variables floorplan load_design 1_synth.odb 1_synth.sdc +source_step_tcl PRE FLOORPLAN proc report_unused_masters { } { set db [ord::get_db] @@ -31,6 +32,10 @@ proc report_unused_masters { } { report_unused_masters +# Eliminate dead logic +eliminate_dead_logic + + #Run check_setup puts "\n==========================================================================" puts "Floorplan check_setup" @@ -146,9 +151,10 @@ if { $::env(REMOVE_ABC_BUFFERS) } { puts "Default units for flow" report_units report_units_metric +report_layer_rc report_metrics 2 "floorplan final" false false -source_env_var_if_exists POST_FLOORPLAN_TCL +source_step_tcl POST FLOORPLAN source_env_var_if_exists IO_CONSTRAINTS orfs_write_db $::env(RESULTS_DIR)/2_1_floorplan.odb diff --git a/flow/scripts/flow.sh b/flow/scripts/flow.sh index 018031ae2c..10f065394f 100755 --- a/flow/scripts/flow.sh +++ b/flow/scripts/flow.sh @@ -8,7 +8,7 @@ echo "Running $2.tcl, stage $1" ( trap 'mv "$LOG_DIR/$1.tmp.log" "$LOG_DIR/$1.log"' EXIT - "$OPENROAD_EXE" $OPENROAD_ARGS -exit "$SCRIPTS_DIR/noop.tcl" \ + eval "$OPENROAD_EXE $OPENROAD_ARGS -exit \"$SCRIPTS_DIR/noop.tcl\"" \ >"$LOG_DIR/$1.tmp.log" 2>&1 eval "$TIME_CMD $OPENROAD_CMD -no_splash \"$SCRIPTS_DIR/$2.tcl\" -metrics \"$LOG_DIR/$1.json\"" \ diff --git a/flow/scripts/global_place.tcl b/flow/scripts/global_place.tcl index 6ef3df9a34..5ed29fc24e 100644 --- a/flow/scripts/global_place.tcl +++ b/flow/scripts/global_place.tcl @@ -2,6 +2,7 @@ utl::set_metrics_stage "globalplace__{}" source $::env(SCRIPTS_DIR)/load.tcl erase_non_stage_variables place load_design 3_2_place_iop.odb 2_floorplan.sdc +source_step_tcl PRE GLOBAL_PLACE set_dont_use $::env(DONT_USE_CELLS) @@ -74,4 +75,6 @@ if { $::env(CLUSTER_FLOPS) } { report_metrics 3 "global place" false false +source_step_tcl POST GLOBAL_PLACE + orfs_write_db $::env(RESULTS_DIR)/3_3_place_gp.odb diff --git a/flow/scripts/global_place_skip_io.tcl b/flow/scripts/global_place_skip_io.tcl index 550df07fb6..7f8f1d0e82 100644 --- a/flow/scripts/global_place_skip_io.tcl +++ b/flow/scripts/global_place_skip_io.tcl @@ -1,6 +1,7 @@ source $::env(SCRIPTS_DIR)/load.tcl erase_non_stage_variables place load_design 2_floorplan.odb 2_floorplan.sdc +source_step_tcl PRE GLOBAL_PLACE_SKIP_IO if { [env_var_exists_and_non_empty FLOORPLAN_DEF] } { puts "FLOORPLAN_DEF is set. Skipping global placement without IOs" @@ -13,4 +14,8 @@ if { [env_var_exists_and_non_empty FLOORPLAN_DEF] } { {*}[env_var_or_empty GLOBAL_PLACEMENT_ARGS] } +source_step_tcl POST GLOBAL_PLACE_SKIP_IO + +report_design_area + orfs_write_db $::env(RESULTS_DIR)/3_1_place_gp_skip_io.odb diff --git a/flow/scripts/global_route.tcl b/flow/scripts/global_route.tcl index ba95205db6..ddc5e90c0b 100644 --- a/flow/scripts/global_route.tcl +++ b/flow/scripts/global_route.tcl @@ -6,7 +6,7 @@ load_design 4_cts.odb 4_cts.sdc # This proc is here to allow us to use 'return' to return early from this # file which is sourced proc global_route_helper { } { - source_env_var_if_exists PRE_GLOBAL_ROUTE_TCL + source_step_tcl PRE GLOBAL_ROUTE set res_aware "" append_env_var res_aware ENABLE_RESISTANCE_AWARE -resistance_aware 0 @@ -113,6 +113,7 @@ proc global_route_helper { } { source [file join $::env(SCRIPTS_DIR) "write_ref_sdc.tcl"] write_guides $::env(RESULTS_DIR)/route.guide + source_step_tcl POST GLOBAL_ROUTE orfs_write_db $::env(RESULTS_DIR)/5_1_grt.odb orfs_write_sdc $::env(RESULTS_DIR)/5_1_grt.sdc } diff --git a/flow/scripts/io_placement.tcl b/flow/scripts/io_placement.tcl index 0ec25dc545..2241d997e1 100644 --- a/flow/scripts/io_placement.tcl +++ b/flow/scripts/io_placement.tcl @@ -7,12 +7,17 @@ if { ![env_var_exists_and_non_empty FOOTPRINT_TCL] } { load_design 3_1_place_gp_skip_io.odb 2_floorplan.sdc + source_step_tcl PRE IO_PLACEMENT log_cmd place_pins \ -hor_layers $::env(IO_PLACER_H) \ -ver_layers $::env(IO_PLACER_V) \ {*}[env_var_or_empty PLACE_PINS_ARGS] + report_design_area + orfs_write_db $::env(RESULTS_DIR)/3_2_place_iop.odb write_pin_placement $::env(RESULTS_DIR)/3_2_place_iop.tcl } else { log_cmd exec cp $::env(RESULTS_DIR)/3_1_place_gp_skip_io.odb $::env(RESULTS_DIR)/3_2_place_iop.odb } + +source_step_tcl POST IO_PLACEMENT diff --git a/flow/scripts/lec_check.tcl b/flow/scripts/lec_check.tcl index 9166092c21..8e1d35919a 100644 --- a/flow/scripts/lec_check.tcl +++ b/flow/scripts/lec_check.tcl @@ -1,8 +1,26 @@ proc write_lec_verilog { filename } { + set remove_cells [find_physical_only_masters] if { [env_var_exists_and_non_empty REMOVE_CELLS_FOR_LEC] } { - write_verilog -remove_cells $::env(REMOVE_CELLS_FOR_LEC) $::env(RESULTS_DIR)/$filename - } else { - write_verilog $::env(RESULTS_DIR)/$filename + lappend remove_cells {*}$::env(REMOVE_CELLS_FOR_LEC) + } + set out_file $::env(RESULTS_DIR)/$filename + write_verilog -remove_cells $remove_cells $out_file + + # Add auxiliary Verilog files (e.g., blackbox stubs) for LEC + if { [env_var_exists_and_non_empty LEC_AUX_VERILOG_FILES] } { + set out [open $out_file a] + foreach aux_file $::env(LEC_AUX_VERILOG_FILES) { + if { ![file exists $aux_file] } { + close $out + error "LEC auxiliary Verilog file not found: $aux_file" + } + puts $out "\n// ORFS auxiliary Verilog for Kepler LEC: $aux_file" + set in [open $aux_file r] + fcopy $in $out + close $in + puts $out "" + } + close $out } } @@ -25,7 +43,7 @@ proc run_lec_test { step file1 file2 } { # tclint-disable-next-line command-args eval exec $::env(KEPLER_FORMAL_EXE) --config $::env(OBJECTS_DIR)/${step}_lec_test.yml try { - set count [exec grep -c "Found difference" $::env(LOG_DIR)/${step}_lec_check.log]] + set count [exec grep -c "Found difference" $::env(LOG_DIR)/${step}_lec_check.log] } trap CHILDSTATUS {results options} { # This block executes if grep returns a non-zero exit code set count 0 diff --git a/flow/scripts/load.tcl b/flow/scripts/load.tcl index 23ea45dc27..34a680b7a4 100644 --- a/flow/scripts/load.tcl +++ b/flow/scripts/load.tcl @@ -32,7 +32,7 @@ proc load_design { design_file sdc_file } { } # Read SDC file - read_sdc $::env(RESULTS_DIR)/$sdc_file + log_cmd read_sdc $::env(RESULTS_DIR)/$sdc_file if { [file exists $::env(PLATFORM_DIR)/derate.tcl] } { log_cmd source $::env(PLATFORM_DIR)/derate.tcl diff --git a/flow/scripts/macro_place.tcl b/flow/scripts/macro_place.tcl index 302dd7b9c7..0789129e42 100644 --- a/flow/scripts/macro_place.tcl +++ b/flow/scripts/macro_place.tcl @@ -1,8 +1,13 @@ source $::env(SCRIPTS_DIR)/load.tcl erase_non_stage_variables floorplan load_design 2_1_floorplan.odb 2_1_floorplan.sdc +source_step_tcl PRE MACRO_PLACE source $::env(SCRIPTS_DIR)/macro_place_util.tcl +source_step_tcl POST MACRO_PLACE + +report_design_area + orfs_write_db $::env(RESULTS_DIR)/2_2_floorplan_macro.odb write_macro_placement $::env(RESULTS_DIR)/2_2_floorplan_macro.tcl diff --git a/flow/scripts/macro_place_util.tcl b/flow/scripts/macro_place_util.tcl index c59e1adead..70ac5ea23f 100644 --- a/flow/scripts/macro_place_util.tcl +++ b/flow/scripts/macro_place_util.tcl @@ -67,9 +67,6 @@ if { [find_macros] != "" } { } log_cmd rtl_macro_placer {*}$all_args - - source $::env(SCRIPTS_DIR)/placement_blockages.tcl - block_channels $blockage_width } else { puts "No macros found: Skipping macro_placement" } diff --git a/flow/scripts/pdn.tcl b/flow/scripts/pdn.tcl index 977fe71f1e..2230e05f80 100644 --- a/flow/scripts/pdn.tcl +++ b/flow/scripts/pdn.tcl @@ -1,11 +1,12 @@ source $::env(SCRIPTS_DIR)/load.tcl erase_non_stage_variables floorplan load_design 2_3_floorplan_tapcell.odb 2_1_floorplan.sdc +source_step_tcl PRE PDN source $::env(PDN_TCL) pdngen -source_env_var_if_exists POST_PDN_TCL +source_step_tcl POST PDN # Check all supply nets set block [ord::get_db_block] @@ -18,4 +19,6 @@ foreach net [$block getNets] { } } +report_design_area + orfs_write_db $::env(RESULTS_DIR)/2_4_floorplan_pdn.odb diff --git a/flow/scripts/placement_blockages.tcl b/flow/scripts/placement_blockages.tcl deleted file mode 100644 index 82c306474b..0000000000 --- a/flow/scripts/placement_blockages.tcl +++ /dev/null @@ -1,44 +0,0 @@ -proc block_channels { channel_width_in_microns } { - set tech [ord::get_db_tech] - set units [$tech getDbUnitsPerMicron] - set block [ord::get_db_block] - - # - # Collect up all the macros - # - set shapes {} - foreach inst [$block getInsts] { - if { [[$inst getMaster] getType] == "BLOCK" } { - set box [$inst getBBox] - lappend shapes [odb::newSetFromRect [$box xMin] [$box yMin] [$box xMax] [$box yMax]] - } - } - - # - # Resize to fill the channels and edge gap - # - set resize_by [expr round($channel_width_in_microns * $units)] - set shapeSet [odb::orSets $shapes] - set shapeSet [odb::bloatSet $shapeSet $resize_by] - - # - # Clip result to the core area - # - set core [$block getCoreArea] - set xl [$core xMin] - set yl [$core yMin] - set xh [$core xMax] - set yh [$core yMax] - set core_rect [odb::newSetFromRect $xl $yl $xh $yh] - set shapeSet [odb::andSet $shapeSet $core_rect] - - # - # Output the blockages - # - set rects [odb::getRectangles $shapeSet] - foreach rect $rects { - set b [odb::dbBlockage_create $block \ - [$rect xMin] [$rect yMin] [$rect xMax] [$rect yMax]] - $b setSoft - } -} diff --git a/flow/scripts/repair_timing_post_place.tcl b/flow/scripts/repair_timing_post_place.tcl index 88757727ea..57db9ff55a 100644 --- a/flow/scripts/repair_timing_post_place.tcl +++ b/flow/scripts/repair_timing_post_place.tcl @@ -2,6 +2,7 @@ utl::set_metrics_stage "place_repair_timing__{}" source $::env(SCRIPTS_DIR)/load.tcl erase_non_stage_variables place load_design 3_5_place_dp.odb 3_place.sdc +source_step_tcl PRE REPAIR_TIMING_POST_PLACE set_placement_padding -global \ -left $::env(CELL_PAD_IN_SITES_DETAIL_PLACEMENT) \ @@ -18,4 +19,6 @@ puts "Estimate parasitics" log_cmd estimate_parasitics -placement report_metrics 3 "place repair timing" true false +source_step_tcl POST REPAIR_TIMING_POST_PLACE + orfs_write_db $::env(RESULTS_DIR)/3_6_place_repair_timing.odb diff --git a/flow/scripts/report_metrics.tcl b/flow/scripts/report_metrics.tcl index edfa501dd9..5accb72a34 100644 --- a/flow/scripts/report_metrics.tcl +++ b/flow/scripts/report_metrics.tcl @@ -224,7 +224,11 @@ proc report_metrics { stage when { include_erc true } { include_clock_skew true report_puts "\n==========================================================================" report_puts "$when slack div critical path delay" report_puts "--------------------------------------------------------------------------" - report_puts "[format "%4f" [expr $path_slack / $path_delay * 100]]" + if { $path_delay != 0.0 } { + report_puts "[format "%4f" [expr $path_slack / $path_delay * 100]]" + } else { + report_puts "N/A (0 delay)" + } } report_puts "\n==========================================================================" diff --git a/flow/scripts/resize.tcl b/flow/scripts/resize.tcl index b1d8ca5aa9..b26ea447e8 100644 --- a/flow/scripts/resize.tcl +++ b/flow/scripts/resize.tcl @@ -2,6 +2,7 @@ utl::set_metrics_stage "placeopt__{}" source $::env(SCRIPTS_DIR)/load.tcl erase_non_stage_variables place load_design 3_3_place_gp.odb 2_floorplan.sdc +source_step_tcl PRE RESIZE log_cmd estimate_parasitics -placement @@ -35,4 +36,6 @@ report_metrics 3 "resizer" true false puts "Instance count before $instance_count_before, after [sta::network_leaf_instance_count]" puts "Pin count before $pin_count_before, after [sta::network_leaf_pin_count]" +source_step_tcl POST RESIZE + orfs_write_db $::env(RESULTS_DIR)/3_4_place_resized.odb diff --git a/flow/scripts/synth_odb.tcl b/flow/scripts/synth_odb.tcl index ad56b542e8..1ec969cafb 100644 --- a/flow/scripts/synth_odb.tcl +++ b/flow/scripts/synth_odb.tcl @@ -2,7 +2,9 @@ utl::set_metrics_stage "floorplan__{}" source $::env(SCRIPTS_DIR)/load.tcl erase_non_stage_variables synth load_design 1_2_yosys.v 1_2_yosys.sdc +source_step_tcl PRE SYNTH +source_step_tcl POST SYNTH orfs_write_db $::env(RESULTS_DIR)/1_synth.odb # Canonicalize 1_synth.sdc. The original SDC_FILE provided by # the user could have dependencies, such as sourcing util.tcl, diff --git a/flow/scripts/synth_preamble.tcl b/flow/scripts/synth_preamble.tcl index d8f98c8f69..3edee2d454 100644 --- a/flow/scripts/synth_preamble.tcl +++ b/flow/scripts/synth_preamble.tcl @@ -63,6 +63,16 @@ proc read_design_sources { } { lappend slang_args -G "$key=$value" } + # Automatically blackbox macros from ADDITIONAL_LIBS so that + # any competing Verilog definitions in the source files are + # ignored in favor of the liberty view, consistent with the + # behavior of the builtin Verilog frontend. + if { [env_var_exists_and_non_empty ADDITIONAL_LIBS] } { + foreach m [get_liberty_cell_names] { + lappend slang_args --blackboxed-module "$m" + } + } + # Apply module blackboxing based on module names as they appear # in the input, that is before any module name mangling done # by elaboration and synthesis diff --git a/flow/scripts/synth_stdcells.tcl b/flow/scripts/synth_stdcells.tcl index 1cd5d5c06f..5fb2039171 100644 --- a/flow/scripts/synth_stdcells.tcl +++ b/flow/scripts/synth_stdcells.tcl @@ -2,3 +2,6 @@ read_liberty -overwrite -setattr liberty_cell -lib {*}$::env(LIB_FILES) read_liberty -overwrite -setattr liberty_cell \ -unit_delay -wb -ignore_miss_func -ignore_buses {*}$::env(LIB_FILES) +if { [info exists ::env(UNSET_ABC9_BOX_CELLS)] } { + setattr -mod -unset abc9_box {*}$::env(UNSET_ABC9_BOX_CELLS) +} diff --git a/flow/scripts/tapcell.tcl b/flow/scripts/tapcell.tcl index cbd4ede9fc..94620cbef8 100644 --- a/flow/scripts/tapcell.tcl +++ b/flow/scripts/tapcell.tcl @@ -2,6 +2,7 @@ source $::env(SCRIPTS_DIR)/load.tcl erase_non_stage_variables floorplan load_design 2_2_floorplan_macro.odb 2_1_floorplan.sdc +source_step_tcl PRE TAPCELL if { [env_var_exists_and_non_empty TAPCELL_TCL] } { source $::env(TAPCELL_TCL) @@ -9,4 +10,8 @@ if { [env_var_exists_and_non_empty TAPCELL_TCL] } { cut_rows } +source_step_tcl POST TAPCELL + +report_design_area + orfs_write_db $::env(RESULTS_DIR)/2_3_floorplan_tapcell.odb diff --git a/flow/scripts/util.tcl b/flow/scripts/util.tcl index 04b4d3727e..e5e0bb32e0 100644 --- a/flow/scripts/util.tcl +++ b/flow/scripts/util.tcl @@ -1,3 +1,8 @@ +# Extract cell names +proc get_liberty_cell_names { } { + return [tee -q -s result.string select -list-mod =A:liberty_cell] +} + proc log_cmd { cmd args } { # log the command, escape arguments with spaces set log_cmd "$cmd[join [lmap arg $args { format " %s" [expr { [string match {* *} $arg] ? "\"$arg\"" : "$arg" }] }] ""]" ;# tclint-disable-line line-length @@ -192,6 +197,7 @@ proc source_env_var_if_exists { env_var } { } } + # Feature toggle for now, eventually the -hier option # will be default and this code will be deleted. proc hier_options { } { @@ -229,6 +235,27 @@ proc is_physical_only_master { master } { return 0 } +# Returns 1 if the master has no signal pins (only power/ground or none). +proc has_signal_pins { master } { + foreach mterm [$master getMTerms] { + set sig_type [$mterm getSigType] + if { $sig_type != "POWER" && $sig_type != "GROUND" } { + return 1 + } + } + return 0 +} + +# Returns 1 if the master has a corresponding liberty cell. +proc has_liberty_cell { master } { + set master_name [$master getName] + set lib_cells [get_lib_cells -quiet */$master_name] + if { $lib_cells == {} } { + return 0 + } + return 1 +} + # Finds all physical-only masters in the current database and # returns their names. proc find_physical_only_masters { } { @@ -237,8 +264,19 @@ proc find_physical_only_masters { } { set physical_only_masters [list] foreach lib $libs { foreach master [$lib getMasters] { + set master_name [$master getName] if { [is_physical_only_master $master] } { - lappend physical_only_masters [$master getName] + lappend physical_only_masters $master_name + continue + } + + # Consider cells with no signal pins and no liberty cell as physical-only + if { [has_liberty_cell $master] == 0 } { + if { [has_signal_pins $master] == 0 } { + lappend physical_only_masters $master_name + } else { + puts "Warning: master $master_name has signal pins but no liberty cell" + } } } } @@ -258,3 +296,8 @@ proc orfs_write_sdc { output_file } { } log_cmd write_sdc -no_timestamp $output_file } + +proc source_step_tcl { hook_type step_name } { + set env_var "${hook_type}_${step_name}_TCL" + source_env_var_if_exists $env_var +} diff --git a/flow/scripts/variables.yaml b/flow/scripts/variables.yaml index 7fcc3fb9c4..dcfe9d9a2a 100644 --- a/flow/scripts/variables.yaml +++ b/flow/scripts/variables.yaml @@ -52,12 +52,12 @@ ROUTING_LAYER_ADJUSTMENT: a too low value, such as 0.10, and bisect to value that works by doing multiple global routing runs. As a last resort, `make global_route_issue` and using - the tools/OpenROAD/etc/deltaDebug.py can be useful to debug + the tools/OpenROAD/etc/whittle.py can be useful to debug global routing errors. If there is something specific that is impossible to route, such as a clock line over a macro, global routing will terminate with DRC errors routes that could have been routed were it not for the specific impossible routes. - deltaDebug.py should weed out the possible routes and leave + whittle.py should weed out the possible routes and leave a minimal failing case that pinpoints the problem. stages: - floorplan @@ -354,6 +354,11 @@ TIE_SEPARATION: stages: - floorplan default: 0 +UNSET_ABC9_BOX_CELLS: + description: | + List of cells to unset the abc9_box attribute on + stages: + - synth EARLY_SIZING_CAP_RATIO: description: | Ratio between the input pin capacitance and the output pin load during initial gate sizing. @@ -1032,6 +1037,166 @@ POST_CTS_TCL: Specifies a Tcl script with commands to run after CTS is completed. stages: - cts +POST_DENSITY_FILL_TCL: + description: | + Specifies a Tcl script with commands to run after density fill. + stages: + - final +POST_DETAIL_PLACE_TCL: + description: | + Specifies a Tcl script with commands to run after detailed placement. + stages: + - place +POST_DETAIL_ROUTE_TCL: + description: | + Specifies a Tcl script with commands to run after detailed route. + stages: + - route +POST_FILLCELL_TCL: + description: | + Specifies a Tcl script with commands to run after fillcell insertion. + stages: + - route +POST_FINAL_REPORT_TCL: + description: | + Specifies a Tcl script with commands to run after final report generation. + stages: + - final +POST_FLOORPLAN_TCL: + description: | + Specifies a Tcl script with commands to run after floorplan is completed. + stages: + - floorplan +POST_GLOBAL_PLACE_SKIP_IO_TCL: + description: | + Specifies a Tcl script with commands to run after global placement (skip IO). + stages: + - place +POST_GLOBAL_PLACE_TCL: + description: | + Specifies a Tcl script with commands to run after global placement. + stages: + - place +POST_GLOBAL_ROUTE_TCL: + description: | + Specifies a Tcl script with commands to run after global route. + stages: + - grt +POST_IO_PLACEMENT_TCL: + description: | + Specifies a Tcl script with commands to run after IO placement. + stages: + - place +POST_MACRO_PLACE_TCL: + description: | + Specifies a Tcl script with commands to run after macro placement. + stages: + - floorplan +POST_PDN_TCL: + description: | + Specifies a Tcl script with commands to run after PDN generation. + stages: + - floorplan +POST_REPAIR_TIMING_POST_PLACE_TCL: + description: | + Specifies a Tcl script with commands to run after post-place timing repair. + stages: + - place +POST_RESIZE_TCL: + description: | + Specifies a Tcl script with commands to run after resize. + stages: + - place +POST_SYNTH_TCL: + description: | + Specifies a Tcl script with commands to run after synthesis ODB generation. + stages: + - synth +POST_TAPCELL_TCL: + description: | + Specifies a Tcl script with commands to run after tapcell. + stages: + - floorplan +PRE_CTS_TCL: + description: | + Specifies a Tcl script with commands to run before CTS. + stages: + - cts +PRE_DENSITY_FILL_TCL: + description: | + Specifies a Tcl script with commands to run before density fill. + stages: + - final +PRE_DETAIL_PLACE_TCL: + description: | + Specifies a Tcl script with commands to run before detailed placement. + stages: + - place +PRE_DETAIL_ROUTE_TCL: + description: | + Specifies a Tcl script with commands to run before detailed route. + stages: + - route +PRE_FILLCELL_TCL: + description: | + Specifies a Tcl script with commands to run before fillcell insertion. + stages: + - route +PRE_FINAL_REPORT_TCL: + description: | + Specifies a Tcl script with commands to run before final report generation. + stages: + - final +PRE_FLOORPLAN_TCL: + description: | + Specifies a Tcl script with commands to run before floorplan. + stages: + - floorplan +PRE_GLOBAL_PLACE_SKIP_IO_TCL: + description: | + Specifies a Tcl script with commands to run before global placement (skip IO). + stages: + - place +PRE_GLOBAL_PLACE_TCL: + description: | + Specifies a Tcl script with commands to run before global placement. + stages: + - place +PRE_IO_PLACEMENT_TCL: + description: | + Specifies a Tcl script with commands to run before IO placement. + stages: + - place +PRE_MACRO_PLACE_TCL: + description: | + Specifies a Tcl script with commands to run before macro placement. + stages: + - floorplan +PRE_PDN_TCL: + description: | + Specifies a Tcl script with commands to run before PDN generation. + stages: + - floorplan +PRE_REPAIR_TIMING_POST_PLACE_TCL: + description: | + Specifies a Tcl script with commands to run before post-place timing repair. + stages: + - place +PRE_RESIZE_TCL: + description: | + Specifies a Tcl script with commands to run before resize. + stages: + - place +PRE_SYNTH_TCL: + description: | + Specifies a Tcl script with commands to run before synthesis ODB generation. + stages: + - synth +PRE_TAPCELL_TCL: + description: | + Specifies a Tcl script with commands to run before tapcell. + stages: + - floorplan FASTROUTE_TCL: description: | Specifies a Tcl script with commands to run before FastRoute. diff --git a/flow/settings.mk b/flow/settings.mk index e824878e7f..413a40682c 100644 --- a/flow/settings.mk +++ b/flow/settings.mk @@ -1 +1,5 @@ -export LEC_CHECK ?= 1 +# Enable LEC (Logical Equivalence Check) only if kepler-formal is installed. +# kepler-formal is primarily an OpenROAD/ORFS developer tool, not an end-user +# tool. End-users would typically run LEC transactionally at project completion, +# not in every CI run where it wastes CI time. +export LEC_CHECK ?= $(if $(wildcard $(KEPLER_FORMAL_EXE)),1,0) diff --git a/flow/test/test_convertDrc.py b/flow/test/test_convertDrc.py new file mode 100644 index 0000000000..87f5894dcc --- /dev/null +++ b/flow/test/test_convertDrc.py @@ -0,0 +1,255 @@ +#!/usr/bin/env python3 + +import unittest +from unittest.mock import MagicMock, patch +import sys +import os + +# Mock pya before importing convertDrc since it imports pya at module level +sys.modules["pya"] = MagicMock() + +sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "util")) + +# convertDrc uses a global `in_drc` set by klayout -rd, so we must set it +import builtins + +builtins.in_drc = "/tmp/test.drc" +builtins.out_file = "/tmp/test.json" + +# Now we can import - but the module-level code tries to use pya.Application +# We need to handle this by patching before import +import importlib + +# Import just the convert_drc function by reading the source +import types + +_util_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "util") +_src_path = os.path.join(_util_dir, "convertDrc.py") + +# Load only the convert_drc function, not the module-level klayout code +with open(_src_path) as f: + source = f.read() + +# Extract just the function definition +import textwrap +import re as _re + +# Parse out the convert_drc function +_func_start = source.index("def convert_drc(rdb):") +_func_end = source.index("\n\napp = pya.Application") +_func_source = source[_func_start:_func_end] + +# Create a module with just the function +_mod = types.ModuleType("convertDrc_test") +_mod.__dict__["os"] = os +_mod.__dict__["in_drc"] = "/tmp/test.drc" +exec(compile(_func_source, _src_path, "exec"), _mod.__dict__) +convert_drc = _mod.convert_drc + + +def make_mock_point(x, y): + p = MagicMock() + p.x = x + p.y = y + return p + + +def make_mock_edge(p1_x, p1_y, p2_x, p2_y): + edge = MagicMock() + edge.p1 = make_mock_point(p1_x, p1_y) + edge.p2 = make_mock_point(p2_x, p2_y) + return edge + + +def make_box_value(left, bottom, right, top): + value = MagicMock() + value.is_box.return_value = True + value.is_edge.return_value = False + value.is_edge_pair.return_value = False + value.is_polygon.return_value = False + value.is_path.return_value = False + value.is_text.return_value = False + value.is_string.return_value = False + box = MagicMock() + box.left = left + box.bottom = bottom + box.right = right + box.top = top + value.box.return_value = box + return value + + +def make_edge_value(p1_x, p1_y, p2_x, p2_y): + value = MagicMock() + value.is_box.return_value = False + value.is_edge.return_value = True + value.is_edge_pair.return_value = False + value.is_polygon.return_value = False + value.is_path.return_value = False + value.is_text.return_value = False + value.is_string.return_value = False + value.edge.return_value = make_mock_edge(p1_x, p1_y, p2_x, p2_y) + return value + + +def make_text_value(text): + value = MagicMock() + value.is_box.return_value = False + value.is_edge.return_value = False + value.is_edge_pair.return_value = False + value.is_polygon.return_value = False + value.is_path.return_value = False + value.is_text.return_value = True + value.is_string.return_value = False + value.text.return_value = text + return value + + +def make_mock_item(values, is_visited=False, tags_str="", comment=None): + item = MagicMock() + item.is_visited.return_value = is_visited + item.tags_str = tags_str + item.each_value.return_value = iter(values) + if comment is not None: + item.comment = comment + else: + # Remove hasattr for comment + del item.comment + return item + + +def make_mock_category(name, description, rdb_id, num_items, items): + cat = MagicMock() + cat.name.return_value = name + cat.description = description + cat.rdb_id.return_value = rdb_id + cat.num_items.return_value = num_items + return cat, items + + +class TestConvertDrc(unittest.TestCase): + def test_empty_rdb(self): + rdb = MagicMock() + rdb.each_category.return_value = iter([]) + + result = convert_drc(rdb) + + self.assertEqual(result["source"], os.path.abspath("/tmp/test.drc")) + self.assertEqual(result["category"], {}) + + def test_empty_category_skipped(self): + cat = MagicMock() + cat.num_items.return_value = 0 + + rdb = MagicMock() + rdb.each_category.return_value = iter([cat]) + + result = convert_drc(rdb) + self.assertEqual(result["category"], {}) + + def test_box_violation(self): + box_val = make_box_value(100, 200, 300, 400) + item = make_mock_item([box_val]) + + cat = MagicMock() + cat.name.return_value = "metal1.min_width" + cat.description = "Minimum width violation" + cat.rdb_id.return_value = 1 + cat.num_items.return_value = 1 + + rdb = MagicMock() + rdb.each_category.return_value = iter([cat]) + rdb.each_item_per_category.return_value = iter([item]) + + result = convert_drc(rdb) + + violations = result["category"]["metal1.min_width"]["violations"] + self.assertEqual(len(violations), 1) + self.assertEqual(len(violations[0]["shape"]), 1) + shape = violations[0]["shape"][0] + self.assertEqual(shape["type"], "box") + self.assertEqual(shape["points"][0], {"x": 100, "y": 200}) + self.assertEqual(shape["points"][1], {"x": 300, "y": 400}) + + def test_edge_violation(self): + edge_val = make_edge_value(10, 20, 30, 40) + item = make_mock_item([edge_val]) + + cat = MagicMock() + cat.name.return_value = "metal1.spacing" + cat.description = "Spacing violation" + cat.rdb_id.return_value = 2 + cat.num_items.return_value = 1 + + rdb = MagicMock() + rdb.each_category.return_value = iter([cat]) + rdb.each_item_per_category.return_value = iter([item]) + + result = convert_drc(rdb) + + violations = result["category"]["metal1.spacing"]["violations"] + shape = violations[0]["shape"][0] + self.assertEqual(shape["type"], "line") + self.assertEqual(shape["points"][0], {"x": 10, "y": 20}) + self.assertEqual(shape["points"][1], {"x": 30, "y": 40}) + + def test_waived_violation(self): + box_val = make_box_value(0, 0, 10, 10) + item = make_mock_item([box_val], tags_str="waived") + + cat = MagicMock() + cat.name.return_value = "rule1" + cat.description = "Rule 1" + cat.rdb_id.return_value = 1 + cat.num_items.return_value = 1 + + rdb = MagicMock() + rdb.each_category.return_value = iter([cat]) + rdb.each_item_per_category.return_value = iter([item]) + + result = convert_drc(rdb) + + violation = result["category"]["rule1"]["violations"][0] + self.assertTrue(violation["waived"]) + + def test_text_in_comment(self): + text_val = make_text_value("error detail") + item = make_mock_item([text_val]) + + cat = MagicMock() + cat.name.return_value = "rule1" + cat.description = "Rule 1" + cat.rdb_id.return_value = 1 + cat.num_items.return_value = 1 + + rdb = MagicMock() + rdb.each_category.return_value = iter([cat]) + rdb.each_item_per_category.return_value = iter([item]) + + result = convert_drc(rdb) + + violation = result["category"]["rule1"]["violations"][0] + self.assertEqual(violation["comment"], "error detail") + + def test_comment_with_text(self): + text_val = make_text_value("extra info") + item = make_mock_item([text_val], comment="base comment") + + cat = MagicMock() + cat.name.return_value = "rule1" + cat.description = "Rule 1" + cat.rdb_id.return_value = 1 + cat.num_items.return_value = 1 + + rdb = MagicMock() + rdb.each_category.return_value = iter([cat]) + rdb.each_item_per_category.return_value = iter([item]) + + result = convert_drc(rdb) + + violation = result["category"]["rule1"]["violations"][0] + self.assertEqual(violation["comment"], "base comment: extra info") + + +if __name__ == "__main__": + unittest.main() diff --git a/flow/test/test_def2stream.py b/flow/test/test_def2stream.py new file mode 100644 index 0000000000..db9e88de50 --- /dev/null +++ b/flow/test/test_def2stream.py @@ -0,0 +1,467 @@ +#!/usr/bin/env python3 + +import unittest +from unittest.mock import MagicMock, patch, call +import sys +import os + +sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "util")) + +import def2stream + + +def make_mock_cell(name, cell_index=0, is_empty=False, parent_cells=1): + """Create a mock cell object.""" + cell = MagicMock() + cell.name = name + cell.cell_index.return_value = cell_index + cell.is_empty.return_value = is_empty + cell.parent_cells.return_value = parent_cells + return cell + + +def make_mock_pya(cells_before_read=None, cells_after_read=None, top_only_cells=None): + """Create a mock pya module with configurable cell behavior. + + Args: + cells_before_read: Cells in main_layout before reading DEF. + cells_after_read: Cells in main_layout after reading DEF/GDS. + top_only_cells: Cells in top_only_layout after copy_tree. + """ + pya_mod = MagicMock() + + # Technology mock + tech = MagicMock() + pya_mod.Technology.return_value = tech + + # Main layout mock + main_layout = MagicMock() + pya_mod.Layout.side_effect = [main_layout] + + if cells_before_read is None: + cells_before_read = [] + if cells_after_read is None: + cells_after_read = [] + + # each_cell returns different results before and after read + main_layout.each_cell.side_effect = [ + iter(cells_before_read), # first call: before reading DEF + iter(cells_after_read), # second call: clearing non-top cells + ] + + # top_only_layout is the second Layout() call + top_only_layout = MagicMock() + + if top_only_cells is None: + top_only_cells = [] + + # top_only each_cell called twice: missing cell check and orphan check + top_only_layout.each_cell.side_effect = [ + iter(top_only_cells), # missing cell check + iter(top_only_cells), # orphan cell check + ] + + # Override Layout side_effect to return both layouts + pya_mod.Layout.side_effect = [main_layout, top_only_layout] + + top_cell = MagicMock() + top_cell.name = "test_design" + top_only_layout.create_cell.return_value = top_cell + top_only_layout.top_cell.return_value = top_cell + top_only_layout.top_cells.return_value = [] + + return pya_mod, main_layout, top_only_layout, top_cell + + +class TestMergeGdsBasic(unittest.TestCase): + def test_no_errors_clean_design(self): + """A clean design with no missing/orphan cells should return 0 errors.""" + top = make_mock_cell("test_design", cell_index=0) + + pya_mod, main_layout, top_only_layout, _ = make_mock_pya( + cells_before_read=[], + cells_after_read=[top], + top_only_cells=[], + ) + + main_layout.cell.return_value = top + + errors = def2stream.merge_gds( + pya_mod=pya_mod, + tech_file="/tmp/test.lyt", + layer_map="", + in_def="/tmp/test.def", + design_name="test_design", + in_files="/tmp/cells.gds", + seal_file="", + out_file="/tmp/out.gds", + ) + + self.assertEqual(errors, 0) + top_only_layout.write.assert_called_once_with("/tmp/out.gds") + + def test_layer_map_applied(self): + """When layer_map is non-empty, it should be set on layout options.""" + top = make_mock_cell("test_design", cell_index=0) + + pya_mod, main_layout, _, _ = make_mock_pya( + cells_before_read=[], + cells_after_read=[top], + top_only_cells=[], + ) + main_layout.cell.return_value = top + + tech = pya_mod.Technology.return_value + + def2stream.merge_gds( + pya_mod=pya_mod, + tech_file="/tmp/test.lyt", + layer_map="/tmp/layer.map", + in_def="/tmp/test.def", + design_name="test_design", + in_files="", + seal_file="", + out_file="/tmp/out.gds", + ) + + self.assertEqual( + tech.load_layout_options.lefdef_config.map_file, "/tmp/layer.map" + ) + + def test_empty_layer_map_not_applied(self): + """When layer_map is empty, map_file should not be set.""" + top = make_mock_cell("test_design", cell_index=0) + + pya_mod, main_layout, _, _ = make_mock_pya( + cells_before_read=[], + cells_after_read=[top], + top_only_cells=[], + ) + main_layout.cell.return_value = top + + tech = pya_mod.Technology.return_value + original_map = tech.load_layout_options.lefdef_config.map_file + + def2stream.merge_gds( + pya_mod=pya_mod, + tech_file="/tmp/test.lyt", + layer_map="", + in_def="/tmp/test.def", + design_name="test_design", + in_files="", + seal_file="", + out_file="/tmp/out.gds", + ) + + self.assertEqual(tech.load_layout_options.lefdef_config.map_file, original_map) + + +class TestCellClearing(unittest.TestCase): + def test_non_top_cells_cleared(self): + """Non-top cells (not VIA_ or _DEF_FILL) should be cleared.""" + top = make_mock_cell("test_design", cell_index=0) + filler = make_mock_cell("FILLER_cell", cell_index=1) + + pya_mod, main_layout, _, _ = make_mock_pya( + cells_before_read=[], + cells_after_read=[top, filler], + top_only_cells=[], + ) + main_layout.cell.return_value = top + + def2stream.merge_gds( + pya_mod=pya_mod, + tech_file="/tmp/test.lyt", + layer_map="", + in_def="/tmp/test.def", + design_name="test_design", + in_files="", + seal_file="", + out_file="/tmp/out.gds", + ) + + filler.clear.assert_called_once() + + def test_via_cells_preserved(self): + """Cells starting with VIA_ should NOT be cleared.""" + top = make_mock_cell("test_design", cell_index=0) + via = make_mock_cell("VIA_M1M2", cell_index=1) + + pya_mod, main_layout, _, _ = make_mock_pya( + cells_before_read=[], + cells_after_read=[top, via], + top_only_cells=[], + ) + main_layout.cell.return_value = top + + def2stream.merge_gds( + pya_mod=pya_mod, + tech_file="/tmp/test.lyt", + layer_map="", + in_def="/tmp/test.def", + design_name="test_design", + in_files="", + seal_file="", + out_file="/tmp/out.gds", + ) + + via.clear.assert_not_called() + + def test_def_fill_cells_preserved(self): + """Cells ending with _DEF_FILL should NOT be cleared.""" + top = make_mock_cell("test_design", cell_index=0) + fill = make_mock_cell("some_DEF_FILL", cell_index=2) + + pya_mod, main_layout, _, _ = make_mock_pya( + cells_before_read=[], + cells_after_read=[top, fill], + top_only_cells=[], + ) + main_layout.cell.return_value = top + + def2stream.merge_gds( + pya_mod=pya_mod, + tech_file="/tmp/test.lyt", + layer_map="", + in_def="/tmp/test.def", + design_name="test_design", + in_files="", + seal_file="", + out_file="/tmp/out.gds", + ) + + fill.clear.assert_not_called() + + +class TestMissingCells(unittest.TestCase): + def test_empty_cell_is_error(self): + """An empty cell without GDS_ALLOW_EMPTY should count as an error.""" + missing = make_mock_cell( + "missing_gds", cell_index=1, is_empty=True, parent_cells=1 + ) + + top = make_mock_cell("test_design", cell_index=0) + + pya_mod, main_layout, _, _ = make_mock_pya( + cells_before_read=[], + cells_after_read=[top], + top_only_cells=[missing], + ) + main_layout.cell.return_value = top + + errors = def2stream.merge_gds( + pya_mod=pya_mod, + tech_file="/tmp/test.lyt", + layer_map="", + in_def="/tmp/test.def", + design_name="test_design", + in_files="", + seal_file="", + out_file="/tmp/out.gds", + ) + + self.assertEqual(errors, 1) + + def test_allow_empty_regex_suppresses_error(self): + """GDS_ALLOW_EMPTY regex should suppress errors for matching cells.""" + missing = make_mock_cell( + "pad_io_cell", cell_index=1, is_empty=True, parent_cells=1 + ) + + top = make_mock_cell("test_design", cell_index=0) + + pya_mod, main_layout, _, _ = make_mock_pya( + cells_before_read=[], + cells_after_read=[top], + top_only_cells=[missing], + ) + main_layout.cell.return_value = top + + errors = def2stream.merge_gds( + pya_mod=pya_mod, + tech_file="/tmp/test.lyt", + layer_map="", + in_def="/tmp/test.def", + design_name="test_design", + in_files="", + seal_file="", + out_file="/tmp/out.gds", + allow_empty="pad_.*", + ) + + self.assertEqual(errors, 0) + + def test_allow_empty_regex_no_match_still_errors(self): + """GDS_ALLOW_EMPTY regex should not suppress non-matching cells.""" + missing = make_mock_cell( + "other_cell", cell_index=1, is_empty=True, parent_cells=1 + ) + + top = make_mock_cell("test_design", cell_index=0) + + pya_mod, main_layout, _, _ = make_mock_pya( + cells_before_read=[], + cells_after_read=[top], + top_only_cells=[missing], + ) + main_layout.cell.return_value = top + + errors = def2stream.merge_gds( + pya_mod=pya_mod, + tech_file="/tmp/test.lyt", + layer_map="", + in_def="/tmp/test.def", + design_name="test_design", + in_files="", + seal_file="", + out_file="/tmp/out.gds", + allow_empty="pad_.*", + ) + + self.assertEqual(errors, 1) + + +class TestOrphanCells(unittest.TestCase): + def test_orphan_cell_is_error(self): + """A cell with no parents (orphan) should count as an error.""" + orphan = make_mock_cell( + "orphan_cell", cell_index=1, is_empty=False, parent_cells=0 + ) + + top = make_mock_cell("test_design", cell_index=0) + + pya_mod, main_layout, _, _ = make_mock_pya( + cells_before_read=[], + cells_after_read=[top], + top_only_cells=[orphan], + ) + main_layout.cell.return_value = top + + errors = def2stream.merge_gds( + pya_mod=pya_mod, + tech_file="/tmp/test.lyt", + layer_map="", + in_def="/tmp/test.def", + design_name="test_design", + in_files="", + seal_file="", + out_file="/tmp/out.gds", + ) + + self.assertEqual(errors, 1) + + def test_top_cell_not_orphan(self): + """The top cell itself should not be counted as an orphan.""" + top = make_mock_cell( + "test_design", cell_index=0, is_empty=False, parent_cells=0 + ) + + pya_mod, main_layout, _, _ = make_mock_pya( + cells_before_read=[], + cells_after_read=[top], + top_only_cells=[top], + ) + main_layout.cell.return_value = top + + errors = def2stream.merge_gds( + pya_mod=pya_mod, + tech_file="/tmp/test.lyt", + layer_map="", + in_def="/tmp/test.def", + design_name="test_design", + in_files="", + seal_file="", + out_file="/tmp/out.gds", + ) + + self.assertEqual(errors, 0) + + +class TestSealFile(unittest.TestCase): + def test_seal_file_merged(self): + """When seal_file is provided, seal cells should be merged.""" + top = make_mock_cell("test_design", cell_index=0) + + pya_mod, main_layout, top_only_layout, top_cell = make_mock_pya( + cells_before_read=[], + cells_after_read=[top], + top_only_cells=[], + ) + main_layout.cell.return_value = top + + seal_cell = MagicMock() + seal_cell.name = "seal_ring" + seal_cell.cell_index.return_value = 5 + # top_cells returns original top + seal after reading seal file + top_only_layout.top_cells.return_value = [top_cell, seal_cell] + + errors = def2stream.merge_gds( + pya_mod=pya_mod, + tech_file="/tmp/test.lyt", + layer_map="", + in_def="/tmp/test.def", + design_name="test_design", + in_files="", + seal_file="/tmp/seal.gds", + out_file="/tmp/out.gds", + ) + + self.assertEqual(errors, 0) + top_only_layout.read.assert_called_once_with("/tmp/seal.gds") + pya_mod.CellInstArray.assert_called_once_with(5, pya_mod.Trans.return_value) + + def test_no_seal_file(self): + """When seal_file is empty, no seal merging should happen.""" + top = make_mock_cell("test_design", cell_index=0) + + pya_mod, main_layout, top_only_layout, _ = make_mock_pya( + cells_before_read=[], + cells_after_read=[top], + top_only_cells=[], + ) + main_layout.cell.return_value = top + + def2stream.merge_gds( + pya_mod=pya_mod, + tech_file="/tmp/test.lyt", + layer_map="", + in_def="/tmp/test.def", + design_name="test_design", + in_files="", + seal_file="", + out_file="/tmp/out.gds", + ) + + top_only_layout.read.assert_not_called() + + +class TestGdsFileMerging(unittest.TestCase): + def test_multiple_gds_files_read(self): + """All space-separated GDS files should be read into main_layout.""" + top = make_mock_cell("test_design", cell_index=0) + + pya_mod, main_layout, _, _ = make_mock_pya( + cells_before_read=[], + cells_after_read=[top], + top_only_cells=[], + ) + main_layout.cell.return_value = top + + def2stream.merge_gds( + pya_mod=pya_mod, + tech_file="/tmp/test.lyt", + layer_map="", + in_def="/tmp/test.def", + design_name="test_design", + in_files="/tmp/a.gds /tmp/b.gds /tmp/c.gds", + seal_file="", + out_file="/tmp/out.gds", + ) + + # read is called for DEF + 3 GDS files = 4 total + read_calls = main_layout.read.call_args_list + self.assertEqual(len(read_calls), 4) # 1 DEF + 3 GDS + + +if __name__ == "__main__": + unittest.main() diff --git a/flow/test/test_delta_debug.sh b/flow/test/test_delta_debug.sh deleted file mode 100755 index 59180cf8b8..0000000000 --- a/flow/test/test_delta_debug.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash -# -# deltaDebug.py integration smoke-test, run from ORFS/flow folder. -# -# Exit with error if anything is amiss, including evaluation of -# variable names such as $(false), unused variables, etc. -set -ue -o pipefail - -cd "$(dirname "$0")/.." -. ../env.sh - -echo "Test deltaDebug.py with a make invocation" -make DESIGN_CONFIG=designs/asap7/gcd/config.mk clean_all floorplan -openroad -exit -python ../tools/OpenROAD/etc/deltaDebug.py --persistence 2 --use_stdout --error_string " 100 | " --base_db_path results/asap7/gcd/base/2_floorplan.odb --step "make DESIGN_CONFIG=designs/asap7/gcd/config.mk do-3_1_place_gp_skip_io" - -echo "Test deltaDebug.py with a make issue" -testname=uart -make DESIGN_CONFIG=designs/asap7/$testname/config.mk place -make DESIGN_CONFIG=designs/asap7/$testname/config.mk global_place_issue -latest_file=$(ls -t global_place_${testname}_asap7_base*.tar.gz | head -n1) -echo "Testing $latest_file" -rm -rf results/delta-debug/ -mkdir -p results/delta-debug/ -cd results/delta-debug/ -tar --strip-components=1 -xzf ../../$latest_file -sed -i 's/openroad -no_init/openroad -exit -no_init/g' run-me-$testname-asap7-base.sh -openroad -exit -python ../../../tools/OpenROAD/etc/deltaDebug.py --persistence 3 --use_stdout --error_string " 100 | " --base_db_path results/asap7/$testname/base/3_2_place_iop.odb --step ./run-me-$testname-asap7-base.sh --multiplier 2 diff --git a/flow/test/test_generate_klayout_tech.py b/flow/test/test_generate_klayout_tech.py new file mode 100644 index 0000000000..22c6642127 --- /dev/null +++ b/flow/test/test_generate_klayout_tech.py @@ -0,0 +1,232 @@ +#!/usr/bin/env python3 + +import unittest +import os +import sys +import tempfile + +sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "util")) + +import generate_klayout_tech + +MINIMAL_LYT = """\ + + + Test + + + ./original.lef + + + +""" + +LYT_WITH_MAP = """\ + + + Test + + + ./original.lef + original.map + + + +""" + +LYT_WITH_EMPTY_MAP = """\ + + + Test + + + ./original.lef + + + + +""" + + +class TestReplaceLefFiles(unittest.TestCase): + def test_single_lef(self): + result = generate_klayout_tech.replace_lef_files(MINIMAL_LYT, ["tech.lef"]) + self.assertIn("tech.lef", result) + self.assertNotIn("original.lef", result) + + def test_multiple_lefs(self): + result = generate_klayout_tech.replace_lef_files( + MINIMAL_LYT, ["tech.lef", "sc.lef", "extra.lef"] + ) + self.assertIn( + "tech.lef" + "sc.lef" + "extra.lef", + result, + ) + self.assertNotIn("original.lef", result) + + def test_empty_lefs(self): + result = generate_klayout_tech.replace_lef_files(MINIMAL_LYT, []) + self.assertNotIn("original.lef", result) + # Empty replacement removes the element content + self.assertNotIn("", result) + + +class TestReplaceMapFiles(unittest.TestCase): + def test_replace_existing_map(self): + result = generate_klayout_tech.replace_map_files( + LYT_WITH_MAP, ["/abs/path/layer.map"] + ) + self.assertIn("/abs/path/layer.map", result) + self.assertNotIn("original.map", result) + + def test_replace_empty_map(self): + result = generate_klayout_tech.replace_map_files( + LYT_WITH_EMPTY_MAP, ["/abs/path/layer.map"] + ) + self.assertIn("/abs/path/layer.map", result) + + def test_no_map_files_noop(self): + result = generate_klayout_tech.replace_map_files(LYT_WITH_MAP, []) + self.assertEqual(result, LYT_WITH_MAP) + + def test_no_map_element_in_template(self): + result = generate_klayout_tech.replace_map_files(MINIMAL_LYT, ["/some/map"]) + # No map element to replace, content unchanged + self.assertEqual(result, MINIMAL_LYT) + + +class TestGenerateKlayoutTech(unittest.TestCase): + def setUp(self): + self.tmp_dir = tempfile.TemporaryDirectory() + self.template = os.path.join(self.tmp_dir.name, "test.lyt") + self.output = os.path.join(self.tmp_dir.name, "output.lyt") + self.results_dir = os.path.join(self.tmp_dir.name, "results") + os.makedirs(self.results_dir, exist_ok=True) + + def tearDown(self): + self.tmp_dir.cleanup() + + def test_basic_generation(self): + with open(self.template, "w") as f: + f.write(MINIMAL_LYT) + + lef_path = os.path.join(self.tmp_dir.name, "tech.lef") + with open(lef_path, "w") as f: + f.write("") + + generate_klayout_tech.generate_klayout_tech( + template_lyt=self.template, + output_lyt=self.output, + lef_files=[lef_path], + reference_dir=self.results_dir, + map_files=[], + use_relative_paths=True, + ) + + with open(self.output) as f: + content = f.read() + + self.assertIn("", content) + self.assertNotIn("original.lef", content) + # Path should be relative to results_dir + expected_rel = os.path.relpath( + os.path.realpath(lef_path), + os.path.realpath(self.results_dir), + ) + self.assertIn(expected_rel, content) + + def test_with_map_files(self): + with open(self.template, "w") as f: + f.write(LYT_WITH_MAP) + + lef_path = os.path.join(self.tmp_dir.name, "tech.lef") + map_path = os.path.join(self.tmp_dir.name, "layer.map") + for p in [lef_path, map_path]: + with open(p, "w") as f: + f.write("") + + generate_klayout_tech.generate_klayout_tech( + template_lyt=self.template, + output_lyt=self.output, + lef_files=[lef_path], + reference_dir=self.results_dir, + map_files=[map_path], + use_relative_paths=False, + ) + + with open(self.output) as f: + content = f.read() + + self.assertIn(os.path.realpath(map_path), content) + self.assertNotIn("original.map", content) + + def test_multiple_lef_files(self): + with open(self.template, "w") as f: + f.write(MINIMAL_LYT) + + lef_files = [] + for name in ["tech.lef", "sc.lef", "extra.lef"]: + path = os.path.join(self.tmp_dir.name, name) + with open(path, "w") as f: + f.write("") + lef_files.append(path) + + generate_klayout_tech.generate_klayout_tech( + template_lyt=self.template, + output_lyt=self.output, + lef_files=lef_files, + reference_dir=self.results_dir, + map_files=[], + use_relative_paths=True, + ) + + with open(self.output) as f: + content = f.read() + + # Should have three lef-files elements + self.assertEqual(content.count(""), 3) + + +class TestRealPlatformLyt(unittest.TestCase): + """Test against actual platform .lyt files to catch regressions.""" + + PLATFORMS_DIR = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "..", "platforms" + ) + + def _test_platform(self, lyt_path): + if not os.path.exists(lyt_path): + self.skipTest(f"{lyt_path} not found") + + with open(lyt_path) as f: + content = f.read() + + result = generate_klayout_tech.replace_lef_files( + content, ["replaced_tech.lef", "replaced_sc.lef"] + ) + self.assertIn("replaced_tech.lef", result) + self.assertIn("replaced_sc.lef", result) + # Original lef-files content should be gone + self.assertNotIn("NangateOpenCellLibrary", result) + self.assertNotIn("asap7_tech", result) + + def test_nangate45(self): + self._test_platform( + os.path.join(self.PLATFORMS_DIR, "nangate45", "FreePDK45.lyt") + ) + + def test_asap7(self): + self._test_platform( + os.path.join(self.PLATFORMS_DIR, "asap7", "KLayout", "asap7.lyt") + ) + + def test_sky130hd(self): + self._test_platform( + os.path.join(self.PLATFORMS_DIR, "sky130hd", "sky130hd.lyt") + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/flow/test/test_helper.sh b/flow/test/test_helper.sh index 0b6af7e2d7..dcd5081631 100755 --- a/flow/test/test_helper.sh +++ b/flow/test/test_helper.sh @@ -13,8 +13,11 @@ if [ $# -ge 4 ]; then fi TARGET=${5:-'finish metadata'} DESIGN_CONFIG=./designs/$PLATFORM/$DESIGN_NAME/$CONFIG_MK -LOG_FILE=./logs/$PLATFORM/$DESIGN_NAME.log -mkdir -p "./logs/$PLATFORM" +if [ -z "${WORK_HOME+x}" ]; then + WORK_HOME=. +fi +LOG_FILE=${WORK_HOME}/logs/$PLATFORM/$DESIGN_NAME.log +mkdir -p "${WORK_HOME}/logs/$PLATFORM" __make="make DESIGN_CONFIG=$DESIGN_CONFIG" if [ -n "${FLOW_VARIANT+x}" ]; then @@ -83,38 +86,4 @@ if [ $ret -eq 0 ] && grep -q 'power:' <(echo $TARGETS); then fi set -x -# Run Autotuner CI specifically for gcd on selected platforms. -if [ -z "${RUN_AUTOTUNER+x}" ]; then - echo "RUN_AUTOTUNER not set, disable AT test." - RUN_AUTOTUNER="false" -fi - -if [ "${RUN_AUTOTUNER}" == "true" ]; then - case $DESIGN_NAME in - "gcd") - # Keep RUN_AUTOTUNER enabled only for these designs - ;; - *) - echo "Disable AT test for design ${DESIGN_NAME}." - RUN_AUTOTUNER="false" - ;; - esac - case $PLATFORM in - "asap7" | "sky130hd" | "ihp-sg13g2" ) - # Keep RUN_AUTOTUNER enabled only for these platforms - ;; - *) - echo "Disable AT test for platform ${PLATFORM}." - RUN_AUTOTUNER="false" - ;; - esac -fi - -if [ "${RUN_AUTOTUNER}" == "true" ]; then - set +x - echo "Start AutoTuner test." - ./test/test_autotuner.sh $DESIGN_NAME $PLATFORM - set -x -fi - exit $ret diff --git a/flow/test/test_outoftree.sh b/flow/test/test_outoftree.sh index 5474b3012b..884873470f 100755 --- a/flow/test/test_outoftree.sh +++ b/flow/test/test_outoftree.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# deltaDebug.py integration smoke-test, run from ORFS/flow folder. +# Out of tree integration smoke-test, run from ORFS/flow folder. # # Exit with error if anything is amiss, including evaluation of # variable names such as $(false), unused variables, etc. diff --git a/flow/util/BUILD.bazel b/flow/util/BUILD.bazel index b8892cbab6..0d9f174267 100644 --- a/flow/util/BUILD.bazel +++ b/flow/util/BUILD.bazel @@ -34,9 +34,6 @@ filegroup( # for scripts/synth.sh steps filegroup( name = "makefile_yosys", - srcs = glob(MAKEFILE_SHARED) + [ - "merge_lib.py", - "preprocessLib.py", - ], + srcs = glob(MAKEFILE_SHARED), visibility = ["//visibility:public"], ) diff --git a/flow/util/addDummyToLef.py b/flow/util/addDummyToLef.py index 3c0c828eec..2dc433f40e 100755 --- a/flow/util/addDummyToLef.py +++ b/flow/util/addDummyToLef.py @@ -1,4 +1,5 @@ #!/usr/bin/env python3 +import os import re import sys import argparse # argument parsing @@ -14,9 +15,12 @@ args = parser.parse_args() -f = open(args.inputLef) -content = f.read() -f.close() +if not os.path.isfile(args.inputLef): + print(f"Error: Input LEF not found: {args.inputLef}", file=sys.stderr) + sys.exit(1) + +with open(args.inputLef) as f: + content = f.read() # refMacro = "BUFH_X1M_A12TR" @@ -26,9 +30,8 @@ result, count = re.subn(pattern, replace, content, 1, re.S) if count > 0: - f = open(args.outputLef, "w") - f.write(result) - f.close() + with open(args.outputLef, "w") as f: + f.write(result) else: - print("Error: Pattern not found") + print("Error: Pattern not found", file=sys.stderr) sys.exit(1) diff --git a/flow/util/correlateRC.py b/flow/util/correlateRC.py index 6c19f807f3..65702ee102 100755 --- a/flow/util/correlateRC.py +++ b/flow/util/correlateRC.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 -# Read grt/rcx capacitance/wire length files for multiple designs and -# use linear regression to fit layer capacitances to rcx net capacitances. -# Use ORFS 'make write_net_rc' to write cap files. +# Script for generating and comparing per-layer parasitics values. +# These values are used by set_layer_rc and will be the base +# values for the parasitics estimations across the flow. import os from sys import exit, stderr @@ -46,6 +46,13 @@ def parse_args(): default=False, help="Plot grt/rcx resistance differences", ) + parser.add_argument( + "--mode", + required=False, + choices=["net", "segment"], + default="net", + help="Input mode: 'net' for net-level RC (make write_net_rc), 'segment' for segment-level RC (make write_segment_rc)", + ) parser.add_argument( "rc_file", nargs="+", help="rc csv file written by make compare_rc" ) @@ -66,7 +73,7 @@ def parse_args(): res_scale = 1e3 else: print("unknown resistance unit") - exit + exit(1) cap_unit = args.cap_unit if cap_unit == "ff": @@ -75,7 +82,7 @@ def parse_args(): cap_scale = 1e-12 else: print("unknown capacitance unit") - exit + exit(1) def makeDict(): @@ -87,6 +94,14 @@ def makeDict(): stack = [] stack_line = None +# For segment mode. +layer_segments = defaultdict( + lambda: {"lengths": [], "resistances": [], "capacitances": []} +) +layer_net_type_length = defaultdict(lambda: defaultdict(float)) +routing_layers = [] +routing_layers_line = None + # indices of relevant layers (routable layers or via layers) active_layers = set() @@ -97,6 +112,17 @@ def makeDict(): with open(rc_file) as f: nonGrtNets = 0 for line in f: + if line.startswith("# routing layers: "): + if routing_layers_line is not None and routing_layers_line != line: + print(f"layer stack inconsistent", file=stderr) + exit(1) + elif routing_layers_line is None: + routing_layers = ( + line.removeprefix("# routing layers: ").strip().split(" ") + ) + routing_layers_line = line + continue + if line.startswith("# stack: "): if stack_line is not None and stack_line != line: print(f"layer stack inconsistent", file=stderr) @@ -120,45 +146,50 @@ def makeDict(): continue tokens = line.strip().split(",") - netName = tokens[0] - - data[design][netName] = { - "type": tokens[1], - "gpl_res": float(tokens[2]), - "gpl_cap": float(tokens[3]), - "grt_res": float(tokens[4]), - "grt_cap": float(tokens[5]), - "rcx_res": float(tokens[6]), - "rcx_cap": float(tokens[7]), - } - - layer_lengths = [float(tok) for tok in tokens[8:]] - for i, length in enumerate(layer_lengths): - if length > 0: - active_layers.add(i) - - data[design][netName]["layer_lengths"] = layer_lengths - data[design][netName]["routable_layer_lengths"] = [ - length - for i, length in enumerate(layer_lengths) - # ignore non-routable layers - if stack[i][1] - ] - data[design][netName]["wire_length"] = sum( - length - for i, length in enumerate(layer_lengths) - # ignore non-routable layers - if stack[i][1] - ) - data[design][netName]["grt_via_res"] = sum( - (length * stack[i][2]) - for i, length in enumerate(layer_lengths) - if not stack[i][1] - ) + + if args.mode == "segment": + layer_segments[tokens[2]]["lengths"].append(float(tokens[3])) + layer_segments[tokens[2]]["resistances"].append(float(tokens[4])) + layer_segments[tokens[2]]["capacitances"].append(float(tokens[5])) + layer_net_type_length[tokens[2]][tokens[1]] += float(tokens[3]) + else: + netName = tokens[0] + + data[design][netName] = { + "type": tokens[1], + "grt_res": float(tokens[2]), + "grt_cap": float(tokens[3]), + "rcx_res": float(tokens[4]), + "rcx_cap": float(tokens[5]), + } + + layer_lengths = [float(tok) for tok in tokens[6:]] + for i, length in enumerate(layer_lengths): + if length > 0: + active_layers.add(i) + + data[design][netName]["layer_lengths"] = layer_lengths + data[design][netName]["routable_layer_lengths"] = [ + length + for i, length in enumerate(layer_lengths) + # ignore non-routable layers + if stack[i][1] + ] + data[design][netName]["wire_length"] = sum( + length + for i, length in enumerate(layer_lengths) + # ignore non-routable layers + if stack[i][1] + ) + data[design][netName]["grt_via_res"] = sum( + (length * stack[i][2]) + for i, length in enumerate(layer_lengths) + if not stack[i][1] + ) ################################################################ -if args.plot_cap: +if args.mode == "net" and args.plot_cap: # Compare the GRT cap estimate vs. OpenRCX SPEF cap diff_x = [] @@ -200,7 +231,7 @@ def makeDict(): ################################################################ -if args.plot_res: +if args.mode == "net" and args.plot_res: # Compare the GRT res estimate vs. OpenRCX SPEF res diff_x = [] @@ -243,96 +274,210 @@ def makeDict(): ################################################################ -# Use linear regression to find updated layer resistances. +if args.mode == "net": + # Use linear regression to find updated layer resistances. -x = [] -y = [] -for design in data: - for net in data[design]: - rcx_res = data[design][net]["rcx_res"] - if rcx_res > 0: - x.append(data[design][net]["routable_layer_lengths"]) - y.append(rcx_res - data[design][net]["grt_via_res"]) + x = [] + y = [] + for design in data: + for net in data[design]: + rcx_res = data[design][net]["rcx_res"] + if rcx_res > 0: + x.append(data[design][net]["routable_layer_lengths"]) + y.append(rcx_res - data[design][net]["grt_via_res"]) -x = np.array(x) -y = np.array(y) + x = np.array(x) + y = np.array(y) -res_model = LinearRegression(fit_intercept=False).fit(x, y) -r_sq = res_model.score(x, y) -print("# Resistance coefficient of determination: {:.4f}".format(r_sq)) + res_model = LinearRegression(fit_intercept=False).fit(x, y) + r_sq = res_model.score(x, y) + print("# Resistance coefficient of determination: {:.4f}".format(r_sq)) -################################################################ + ################################################################ -# Use linear regression to find updated layer capacitances. + # Use linear regression to find updated layer capacitances. -x = [] -y = [] -for design in data: - for net in data[design]: - x.append(data[design][net]["routable_layer_lengths"]) - y.append(data[design][net]["rcx_cap"]) + x = [] + y = [] + for design in data: + for net in data[design]: + x.append(data[design][net]["routable_layer_lengths"]) + y.append(data[design][net]["rcx_cap"]) -x = np.array(x) -y = np.array(y) + x = np.array(x) + y = np.array(y) -cap_model = LinearRegression(fit_intercept=False).fit(x, y) -r_sq = cap_model.score(x, y) -print("# Capacitance coefficient of determination: {:.4f}".format(r_sq)) -print("# Updated layer resistance {}/um capacitance {}/um".format(res_unit, cap_unit)) + cap_model = LinearRegression(fit_intercept=False).fit(x, y) + r_sq = cap_model.score(x, y) + print("# Capacitance coefficient of determination: {:.4f}".format(r_sq)) + print( + "# Updated layer resistance {}/um capacitance {}/um".format(res_unit, cap_unit) + ) -routable_layers = [layer for layer in stack if layer[1]] -for i, layer in enumerate(routable_layers): - res_coeff = res_model.coef_[i] - cap_coeff = cap_model.coef_[i] - if res_coeff != 0.0 or cap_coeff != 0.0: - print( - "set_layer_rc -layer {} -resistance {:.5E} -capacitance {:.5E}".format( - layer[0], res_coeff / res_scale, cap_coeff / cap_scale + routable_layers = [layer for layer in stack if layer[1]] + for i, layer in enumerate(routable_layers): + res_coeff = res_model.coef_[i] + cap_coeff = cap_model.coef_[i] + if res_coeff != 0.0 or cap_coeff != 0.0: + print( + "set_layer_rc -layer {} -resistance {:.5E} -capacitance {:.5E}".format( + layer[0], res_coeff / res_scale, cap_coeff / cap_scale + ) ) + + ################################################################ + + def generic_rc_fit(type_sieve): + x = [] + y = [] + for design in data: + for net in data[design]: + net_type = data[design][net]["type"] + wire_res = data[design][net]["rcx_res"] + wire_length = data[design][net]["wire_length"] + if net_type in type_sieve and wire_res != 0.0: + x.append([wire_length]) + y.append(wire_res) + x = np.array(x) + y = np.array(y) + wire_res_model = LinearRegression(fit_intercept=False).fit(x, y) + wire_res = wire_res_model.coef_[0] + + x = [] + y = [] + for design in data: + for net in data[design]: + net_type = data[design][net]["type"] + if net_type in type_sieve: + wire_length = data[design][net]["wire_length"] + wire_cap = data[design][net]["rcx_cap"] + x.append([wire_length]) + y.append(wire_cap) + x = np.array(x) + y = np.array(y) + wire_cap_model = LinearRegression(fit_intercept=False).fit(x, y) + wire_cap = wire_cap_model.coef_[0] + + return "-resistance {:.5E} -capacitance {:.5E}".format( + wire_res / res_scale, wire_cap / cap_scale ) + print("# Combined fit:") + print("set_wire_rc " + generic_rc_fit(["signal", "clock"])) + + print("# Split signal/clock fit:") + print("set_wire_rc -signal " + generic_rc_fit(["signal"])) + print("set_wire_rc -clock " + generic_rc_fit(["clock"])) + ################################################################ +if args.mode == "segment": + print("\nUnits: resistance [{}/um], capacitance [{}/um]".format(res_unit, cap_unit)) + + # Note that the .csv data comes from ODB which stores capacitance in fF. + cap_ff_to_f = 1e-15 + + layer_models = {} + for layer_name in routing_layers: + # There may be routing layers with no segments, so we check if the + # layer exists in the dict. + if layer_name not in layer_segments: + continue + + # sklearn requires the input to be 2D, so we reshape to add a dimension + # to the list. + lengths = np.array(layer_segments[layer_name]["lengths"]).reshape(-1, 1) + resistances = np.array(layer_segments[layer_name]["resistances"]) + capacitances_ff = np.array(layer_segments[layer_name]["capacitances"]) + + res_model = LinearRegression(fit_intercept=False).fit(lengths, resistances) + cap_model = LinearRegression(fit_intercept=False).fit(lengths, capacitances_ff) + layer_models[layer_name] = ( + res_model, + cap_model, + lengths, + resistances, + capacitances_ff, + ) -def generic_rc_fit(type_sieve): - x = [] - y = [] - for design in data: - for net in data[design]: - net_type = data[design][net]["type"] - wire_res = data[design][net]["rcx_res"] - wire_length = data[design][net]["wire_length"] - if net_type in type_sieve and wire_res != 0.0: - x.append([wire_length]) - y.append(wire_res) - x = np.array(x) - y = np.array(y) - wire_res_model = LinearRegression(fit_intercept=False).fit(x, y) - wire_res = wire_res_model.coef_[0] + # Print R² table + print("{:<13s} | {:>8s} | {:>8s}".format("\nLayer", "Res R²", "Cap R²")) + print("-" * 34) + for layer_name, ( + res_model, + cap_model, + lengths, + resistances, + capacitances_ff, + ) in layer_models.items(): + r_sq_res = res_model.score(lengths, resistances) + r_sq_cap = cap_model.score(lengths, capacitances_ff) + print("{:<12s} | {:>8.4f} | {:>8.4f}".format(layer_name, r_sq_res, r_sq_cap)) + print("-" * 34) + print("") + + for layer_name, ( + res_model, + cap_model, + lengths, + resistances, + capacitances_ff, + ) in layer_models.items(): + print( + "set_layer_rc -layer {} -resistance {:.5E} -capacitance {:.5E}".format( + layer_name, + res_model.coef_[0] / res_scale, + cap_model.coef_[0] * cap_ff_to_f / cap_scale, + ) + ) + print("") + + def wire_rc_fit(target_net_type=None): + total_length = 0.0 + total_resistance = 0.0 + total_capacitance = 0.0 + + for layer_name, (res_model, cap_model, lengths, _, _) in layer_models.items(): + if target_net_type is not None: + layer_length = sum( + layer_net_type_length[layer_name][net_type] + for net_type in target_net_type + ) + else: + layer_length = float(lengths.sum()) + + total_resistance += res_model.coef_[0] * layer_length + total_capacitance += cap_model.coef_[0] * layer_length + total_length += layer_length + + if total_length == 0.0: + return None + + return ( + total_resistance / total_length / res_scale, + total_capacitance / total_length * cap_ff_to_f / cap_scale, + ) - x = [] - y = [] - for design in data: - for net in data[design]: - net_type = data[design][net]["type"] - if net_type in type_sieve: - wire_length = data[design][net]["wire_length"] - wire_cap = data[design][net]["rcx_cap"] - x.append([wire_length]) - y.append(wire_cap) - x = np.array(x) - y = np.array(y) - wire_cap_model = LinearRegression(fit_intercept=False).fit(x, y) - wire_cap = wire_cap_model.coef_[0] + resistance, capacitance = wire_rc_fit() - return "-resistance {:.5E} -capacitance {:.5E}".format( - wire_res / res_scale, wire_cap / cap_scale + print( + "set_wire_rc -resistance {:.5E} -capacitance {:.5E}".format( + resistance, capacitance + ) ) + for net_type in ["signal", "clock"]: + result = wire_rc_fit([net_type]) + + if result is None: + print("[Warning] No {} nets were found.".format(net_type)) + continue -print("# Combined fit:") -print("set_wire_rc " + generic_rc_fit(["signal", "clock"])) + resistance, capacitance = result -print("# Split signal/clock fit:") -print("set_wire_rc -signal " + generic_rc_fit(["signal"])) -print("set_wire_rc -clock " + generic_rc_fit(["clock"])) + print( + "set_wire_rc -{} -resistance {:.5E} -capacitance {:.5E}".format( + net_type, resistance, capacitance + ) + ) + print("") diff --git a/flow/util/def2stream.py b/flow/util/def2stream.py index 5062474f9e..f6530d3db3 100644 --- a/flow/util/def2stream.py +++ b/flow/util/def2stream.py @@ -1,100 +1,151 @@ -import pya +try: + import pya +except ImportError: + pya = None + import re -import json -import copy import sys import os -errors = 0 - -# Load technology file -tech = pya.Technology() -tech.load(tech_file) -layoutOptions = tech.load_layout_options -if len(layer_map) > 0: - layoutOptions.lefdef_config.map_file = layer_map - -# Load def file -main_layout = pya.Layout() -print("[INFO] Reporting cells prior to loading DEF ...") -for i in main_layout.each_cell(): - print("[INFO] '{0}'".format(i.name)) - -main_layout.read(in_def, layoutOptions) - -# Clear cells -top_cell_index = main_layout.cell(design_name).cell_index() - -# remove orphan cell BUT preserve cell with VIA_ -# - KLayout is prepending VIA_ when reading DEF that instantiates LEF's via -for i in main_layout.each_cell(): - if i.cell_index() != top_cell_index: - if not i.name.startswith("VIA_") and not i.name.endswith("_DEF_FILL"): - i.clear() - -# Load in the gds to merge -for fil in in_files.split(): - print("\t{0}".format(fil)) - main_layout.read(fil) - -# Copy the top level only to a new layout -top_only_layout = pya.Layout() -top_only_layout.dbu = main_layout.dbu -top = top_only_layout.create_cell(design_name) -top.copy_tree(main_layout.cell(design_name)) - -missing_cell = False -allow_empty = os.environ.get("GDS_ALLOW_EMPTY", "") -regex = re.compile(allow_empty) if allow_empty else None - -if allow_empty: - print(f"[INFO] GDS_ALLOW_EMPTY={allow_empty}") - -for i in top_only_layout.each_cell(): - if i.is_empty(): - missing_cell = True - if regex is not None and regex.match(i.name): - print( - "[WARNING] LEF Cell '{0}' ignored. Matches GDS_ALLOW_EMPTY.".format( - i.name - ) - ) - else: - print( - "[ERROR] LEF Cell '{0}' has no matching GDS/OAS cell." - " Cell will be empty.".format(i.name) - ) - errors += 1 -if not missing_cell: - print("[INFO] All LEF cells have matching GDS/OAS cells") +def merge_gds( + pya_mod, + tech_file, + layer_map, + in_def, + design_name, + in_files, + seal_file, + out_file, + allow_empty="", +): + """Merge DEF and GDS/OAS files into a single stream file. + + Args: + pya_mod: The pya module (klayout Python API). + tech_file: Path to klayout technology file. + layer_map: Path to layer map file (empty string if none). + in_def: Path to input DEF file. + design_name: Top-level design name. + in_files: Space-separated string of GDS/OAS files to merge. + seal_file: Path to seal ring GDS/OAS file (empty string if none). + out_file: Path to output GDS/OAS file. + allow_empty: Regex pattern for cells allowed to be empty. + + Returns: + Number of errors encountered. + """ + errors = 0 + + # Load technology file + tech = pya_mod.Technology() + tech.load(tech_file) + layout_options = tech.load_layout_options + if len(layer_map) > 0: + layout_options.lefdef_config.map_file = layer_map + + # Load def file + main_layout = pya_mod.Layout() + print("[INFO] Reporting cells prior to loading DEF ...") + for i in main_layout.each_cell(): + print("[INFO] '{0}'".format(i.name)) + + main_layout.read(in_def, layout_options) + + # Clear cells + top_cell_index = main_layout.cell(design_name).cell_index() + + # remove orphan cell BUT preserve cell with VIA_ + # - KLayout is prepending VIA_ when reading DEF that instantiates LEF's via + for i in main_layout.each_cell(): + if i.cell_index() != top_cell_index: + if not i.name.startswith("VIA_") and not i.name.endswith("_DEF_FILL"): + i.clear() + + # Load in the gds to merge + for fil in in_files.split(): + print("\t{0}".format(fil)) + main_layout.read(fil) + + # Copy the top level only to a new layout + top_only_layout = pya_mod.Layout() + top_only_layout.dbu = main_layout.dbu + top = top_only_layout.create_cell(design_name) + top.copy_tree(main_layout.cell(design_name)) + + missing_cell = False + regex = re.compile(allow_empty) if allow_empty else None + + if allow_empty: + print(f"[INFO] GDS_ALLOW_EMPTY={allow_empty}") + + for i in top_only_layout.each_cell(): + if i.is_empty(): + missing_cell = True + if regex is not None and regex.match(i.name): + print( + "[WARNING] LEF Cell '{0}' ignored. Matches GDS_ALLOW_EMPTY.".format( + i.name + ) + ) + else: + print( + "[ERROR] LEF Cell '{0}' has no matching GDS/OAS cell." + " Cell will be empty.".format(i.name) + ) + errors += 1 -orphan_cell = False -for i in top_only_layout.each_cell(): - if i.name != design_name and i.parent_cells() == 0: - orphan_cell = True - print("[ERROR] Found orphan cell '{0}'".format(i.name)) - errors += 1 + if not missing_cell: + print("[INFO] All LEF cells have matching GDS/OAS cells") -if not orphan_cell: - print("[INFO] No orphan cells in the final layout") + orphan_cell = False + for i in top_only_layout.each_cell(): + if i.name != design_name and i.parent_cells() == 0: + orphan_cell = True + print("[ERROR] Found orphan cell '{0}'".format(i.name)) + errors += 1 + if not orphan_cell: + print("[INFO] No orphan cells in the final layout") -if seal_file: - top_cell = top_only_layout.top_cell() + if seal_file: + top_cell = top_only_layout.top_cell() - top_only_layout.read(seal_file) + top_only_layout.read(seal_file) - for cell in top_only_layout.top_cells(): - if cell != top_cell: - print( - "[INFO] Merging '{0}' as child of '{1}'".format( - cell.name, top_cell.name + for cell in top_only_layout.top_cells(): + if cell != top_cell: + print( + "[INFO] Merging '{0}' as child of '{1}'".format( + cell.name, top_cell.name + ) ) + top.insert(pya_mod.CellInstArray(cell.cell_index(), pya_mod.Trans())) + + # Write out the GDS + top_only_layout.write(out_file) + + return errors + + +# When run via klayout -r, globals tech_file, layer_map, in_def, etc. +# are set by klayout's -rd mechanism. +if pya is not None: + try: + # These globals are set by klayout -rd flags + sys.exit( + merge_gds( + pya_mod=pya, + tech_file=tech_file, # noqa: F821 - set by klayout -rd + layer_map=layer_map, # noqa: F821 + in_def=in_def, # noqa: F821 + design_name=design_name, # noqa: F821 + in_files=in_files, # noqa: F821 + seal_file=seal_file, # noqa: F821 + out_file=out_file, # noqa: F821 + allow_empty=os.environ.get("GDS_ALLOW_EMPTY", ""), ) - top.insert(pya.CellInstArray(cell.cell_index(), pya.Trans())) - -# Write out the GDS -top_only_layout.write(out_file) - -sys.exit(errors) + ) + except NameError: + # Not running under klayout -r, pya available but no -rd globals + pass diff --git a/flow/util/docker_shell b/flow/util/docker_shell index 110715233d..9a14e01961 100755 --- a/flow/util/docker_shell +++ b/flow/util/docker_shell @@ -1,7 +1,17 @@ #!/usr/bin/env bash - set -ex +# docker_shell — unified launcher for AutoTuner / OpenROAD +# +# Usage: etc/docker_shell [OPTIONS] [-- CMD [ARGS...]] +# +# Options: +# -i, --image IMAGE Docker image (overrides $OR_IMAGE and default) +# --user Map host UID/GID into the container via entrypoint.sh +# -p, --port SPEC Forward a port, e.g. --port 8265:8265 (repeatable) +# --dry-run Print the docker command without executing it +# -h|--help Show this help and exit + # # Method to use docker CLI to determine if we're using docker or podman # @@ -20,7 +30,34 @@ get_container_engine () { fi } -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +DEFAULT_IMAGE="openroad/orfs:latest" +FLOW_DIR="/OpenROAD-flow-scripts/flow" +USE_USER=false +DRY_RUN=false +PORTS=() +IMAGE="" +CMD_ARGS=() + +usage() { + grep '^#' "$0" | sed 's/^# \{0,1\}//' + exit 0 +} + +while [[ $# -gt 0 ]]; do + case "$1" in + -i|--image) IMAGE="$2"; shift 2 ;; + --user) USE_USER=true; shift ;; + -p|--port) PORTS+=("$2"); shift 2 ;; + --dry-run) DRY_RUN=true; shift ;; + -h|--help) usage ;; + --) shift; CMD_ARGS=("$@"); break ;; + -*) echo "Unknown option: $1" >&2; exit 1 ;; + *) CMD_ARGS=("$@"); break ;; + esac +done + +# Image resolution: --image > $OR_IMAGE > default +IMAGE="${IMAGE:-${OR_IMAGE:-$DEFAULT_IMAGE}}" get_container_engine @@ -31,41 +68,65 @@ KLAYOUT_CMD=${KLAYOUT_CMD:-/usr/bin/klayout} XSOCK=/tmp/.X11-unix XAUTH=/tmp/.docker.xauth -xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge - -ARGUMENTS=$@ +if ! $DRY_RUN; then + xauth nlist ${DISPLAY:-:0} | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge - +fi if test -t 0; then DOCKER_INTERACTIVE=-ti +else + DOCKER_INTERACTIVE= fi -if [[ $container_engine == "podman" ]]; then +if $USE_USER; then + user_args="--entrypoint=entrypoint.sh --user=root" + user_env="-e CUSTOM_USER=$(id --user --name) -e CUSTOM_USER_ID=$(id --user) -e CUSTOM_GROUP_ID=$(id --group)" +elif [[ $container_engine == "podman" ]]; then user_args="--privileged --userns=keep-id" + user_env= else user_args="-u $(id -u ${USER}):$(id -g ${USER})" + user_env= +fi + +PORT_ARGS=() +for port in "${PORTS[@]}"; do + PORT_ARGS+=(-p "$port") +done + +CMD_STR= +[[ ${#CMD_ARGS[@]} -gt 0 ]] && CMD_STR="${CMD_ARGS[*]}" + +ENV_SH_CMD='if [ -f ../env.sh ]; then . ../env.sh; fi;' + +# Build the command once; dry-run prints it, otherwise exec it. +DOCKER_CMD=( + "$container_engine" run --rm -i + $DOCKER_INTERACTIVE + $user_env $user_args + -e LIBGL_ALWAYS_SOFTWARE=1 + -e QT_X11_NO_MITSHM=1 + -e XDG_RUNTIME_DIR=/tmp/xdg-run + -e "DISPLAY=${DISPLAY:-:0}" + -e QT_XKB_CONFIG_ROOT=/usr/share/X11/xkb + -v "$XSOCK:$XSOCK" + -v "$XAUTH:$XAUTH" + -e "XAUTHORITY=$XAUTH" + -e FLOW_HOME=/OpenROAD-flow-scripts/flow/ + -e WORK_HOME=/work + -e "YOSYS_EXE=$YOSYS_EXE" + -e "OPENROAD_EXE=$OPENROAD_EXE" + -e "KLAYOUT_CMD=$KLAYOUT_CMD" + -v "$WORKSPACE:/work" + --network host + "${PORT_ARGS[@]}" + "$IMAGE" + bash -c "set -ex; mkdir /tmp/xdg-run; cd ${FLOW_DIR}; ${ENV_SH_CMD}$CMD_STR" +) + +if $DRY_RUN; then + echo "${DOCKER_CMD[*]}" + exit 0 fi -# Most of these options below has to do with allowing to -# run the OpenROAD GUI from within Docker. -docker run $user_args \ - -e LIBGL_ALWAYS_SOFTWARE=1 \ - -e "QT_X11_NO_MITSHM=1" \ - -e XDG_RUNTIME_DIR=/tmp/xdg-run \ - -e DISPLAY=$DISPLAY \ - -e QT_XKB_CONFIG_ROOT=/usr/share/X11/xkb \ - -v $XSOCK:$XSOCK \ - -v $XAUTH:$XAUTH \ - -e XAUTHORITY=$XAUTH \ - -e FLOW_HOME=/OpenROAD-flow-scripts/flow/ \ - -e YOSYS_EXE=$YOSYS_EXE \ - -e OPENROAD_EXE=$OPENROAD_EXE \ - -e KLAYOUT_CMD=$KLAYOUT_CMD \ - -v $WORKSPACE:/OpenROAD-flow-scripts/flow:Z \ - --network host \ - $DOCKER_INTERACTIVE \ - ${OR_IMAGE:-openroad/orfs:latest} \ - bash -c "set -ex - mkdir /tmp/xdg-run - cd /OpenROAD-flow-scripts/flow - . ../env.sh - $ARGUMENTS -" +exec "${DOCKER_CMD[@]}" diff --git a/flow/util/genMetrics.py b/flow/util/genMetrics.py index fbf746cdfc..536bfeb4fb 100755 --- a/flow/util/genMetrics.py +++ b/flow/util/genMetrics.py @@ -48,9 +48,9 @@ def parse_args(): "--output", "-o", required=False, default="metadata.json", help="Output file" ) parser.add_argument("--hier", "-x", action="store_true", help="Hierarchical JSON") - parser.add_argument("--logs", help="Path to logs") - parser.add_argument("--reports", help="Path to reports") - parser.add_argument("--results", help="Path to results") + parser.add_argument("--logs", required=True, help="Path to logs") + parser.add_argument("--reports", required=True, help="Path to reports") + parser.add_argument("--results", required=True, help="Path to results") args = parser.parse_args() return args @@ -142,17 +142,14 @@ def extractGnuTime(prefix, jsonFile, file): # def read_sdc(file_name): clkList = [] - sdcFile = None try: - sdcFile = open(file_name, "r") - except IOError: - print("[WARN] Failed to open file:", file_name) + with open(file_name, "r") as sdcFile: + lines = sdcFile.readlines() + except OSError as e: + print(f"[WARN] Failed to open file: {file_name} ({e})") return clkList - lines = sdcFile.readlines() - sdcFile.close() - for line in lines: if len(line.split()) < 2: continue @@ -175,19 +172,19 @@ def read_sdc(file_name): def is_git_repo(folder=None): cmd = ["git", "branch"] - if folder is not None: - return call(cmd, stderr=STDOUT, stdout=open(os.devnull, "w"), cwd=folder) == 0 - else: - return call(cmd, stderr=STDOUT, stdout=open(os.devnull, "w")) == 0 + with open(os.devnull, "w") as devnull: + if folder is not None: + return call(cmd, stderr=STDOUT, stdout=devnull, cwd=folder) == 0 + else: + return call(cmd, stderr=STDOUT, stdout=devnull) == 0 def merge_jsons(root_path, output, files): paths = sorted(glob(os.path.join(root_path, files))) for path in paths: - file = open(path, "r") - data = json.load(file) + with open(path, "r") as file: + data = json.load(file) output.update(data) - file.close() def extract_metrics( diff --git a/flow/util/genReport.py b/flow/util/genReport.py index f08fdd20e6..02b898775b 100755 --- a/flow/util/genReport.py +++ b/flow/util/genReport.py @@ -170,7 +170,7 @@ def gen_report(name, data): args.verbose - 2, ) - if len(d["drcs"].keys()) > 0: + if len(data["drcs"].keys()) > 0: if data["status"] == STATUS_GREEN: output += " Design has the violations under the allowed limit: " else: @@ -264,6 +264,7 @@ def write_summary(): # check if design ran to completion without errors or warnings d["log_errors"] = list() d["log_warnings"] = list() + d["last_log"] = "" for name_ in sorted(files): temp_e, temp_w = parse_messages(os.path.join(log_dir, name_)) d["log_errors"] += temp_e @@ -295,7 +296,7 @@ def write_summary(): with open(drc_report_file, "r") as file_: for line_ in file_.readlines(): if "violation type:" in line_: - type_ = line_.strip("violation type:").strip() + type_ = line_.split("violation type:", 1)[1].strip() if type_ in d["drcs"].keys(): d["drcs"][type_] += 1 else: diff --git a/flow/util/generate-vars.sh b/flow/util/generate-vars.sh index 299cbe23aa..90e9c13e04 100755 --- a/flow/util/generate-vars.sh +++ b/flow/util/generate-vars.sh @@ -51,9 +51,13 @@ while read -r VAR; do if [[ "${name}" == *"SCRIPTS_DIR"* ]]; then value=$(sed -e "s,${FLOW_ROOT},.,g" <<< "${value}") fi - for path in workspace platforms; do - value=$(sed -e "s,\(^\|[: \"']\)/${path},\1./${path},g" <<< "${value}") - done + + # PII members use PRESERVE_PATHS=1 make issue ... + if [[ ! -v PRESERVE_PATHS ]]; then + for path in workspace platforms; do + value=$(sed -e "s,\(^\|[: \"']\)/${path},\1./${path},g" <<< "${value}") + done + fi value=$(sed -e "s,${FLOW_ROOT},\${FLOW_HOME},g" <<< "${value}") value=$(sed -e "s,${ORFS_ROOT},\${FLOW_HOME}/\.\.,g" <<< "${value}") diff --git a/flow/util/generate_klayout_tech.py b/flow/util/generate_klayout_tech.py new file mode 100644 index 0000000000..c054945f71 --- /dev/null +++ b/flow/util/generate_klayout_tech.py @@ -0,0 +1,107 @@ +"""Generate klayout .lyt tech file from platform template. + +Replaces and elements with actual paths. +No klayout dependency - pure XML manipulation using stdlib. +""" + +import argparse +import os +import re + + +def replace_lef_files(content, lef_files): + """Replace the ... element(s) with new ones. + + The original .lyt template has a single element inside + . We replace it with one element + per LEF file, matching the existing sed-based behavior. + """ + replacement = "".join("{}".format(f) for f in lef_files) + return re.sub(r".*?", replacement, content) + + +def replace_map_files(content, map_files): + """Replace the ... or element(s) with new ones.""" + if not map_files: + return content + replacement = "".join("{}".format(f) for f in map_files) + content = re.sub(r".*?", replacement, content) + content = re.sub(r"", replacement, content) + return content + + +def generate_klayout_tech( + template_lyt, + output_lyt, + lef_files, + reference_dir, + map_files, + use_relative_paths, +): + """Generate a klayout .lyt file from a platform template. + + Args: + template_lyt: Path to the platform .lyt template file. + output_lyt: Path to write the generated .lyt file. + lef_files: List of LEF file paths to include. + reference_dir: Directory to compute relative paths from. + map_files: List of map file paths. + use_relative_paths: If True, compute paths relative to reference_dir. + """ + with open(template_lyt, "r") as f: + content = f.read() + + # Both modes use relative paths from reference_dir, matching the + # original sed-based behavior which always uses realpath --relative-to. + resolved_lefs = [ + os.path.relpath(os.path.realpath(f), os.path.realpath(reference_dir)) + for f in lef_files + ] + + content = replace_lef_files(content, resolved_lefs) + + resolved_maps = [os.path.realpath(f) for f in map_files] + content = replace_map_files(content, resolved_maps) + + with open(output_lyt, "w") as f: + f.write(content) + + +def main(): + parser = argparse.ArgumentParser( + description="Generate klayout .lyt tech file from platform template." + ) + parser.add_argument( + "--template", required=True, help="Path to platform .lyt template" + ) + parser.add_argument("--output", required=True, help="Output .lyt file path") + parser.add_argument( + "--lef-files", nargs="*", default=[], help="LEF files to include" + ) + parser.add_argument( + "--reference-dir", + required=True, + help="Directory for computing relative paths", + ) + parser.add_argument( + "--map-files", nargs="*", default=[], help="Map files to include" + ) + parser.add_argument( + "--use-relative-paths", + action="store_true", + help="Use paths relative to reference-dir", + ) + args = parser.parse_args() + + generate_klayout_tech( + template_lyt=args.template, + output_lyt=args.output, + lef_files=args.lef_files, + reference_dir=args.reference_dir, + map_files=args.map_files, + use_relative_paths=args.use_relative_paths, + ) + + +if __name__ == "__main__": + main() diff --git a/flow/util/makeIssue.sh b/flow/util/makeIssue.sh index 0d3e34bae8..f8307558f3 100755 --- a/flow/util/makeIssue.sh +++ b/flow/util/makeIssue.sh @@ -56,8 +56,8 @@ if [[ ! -v EXCLUDE_PLATFORM ]]; then fi fi -VARS_BASENAME=vars-$DESIGN_NICKNAME-$PLATFORM-$FLOW_VARIANT -RUN_ME_SCRIPT=run-me-$DESIGN_NICKNAME-$PLATFORM-$FLOW_VARIANT.sh +VARS_BASENAME=${WORK_HOME}/vars-$DESIGN_NICKNAME-$PLATFORM-$FLOW_VARIANT +RUN_ME_SCRIPT=${WORK_HOME}/run-me-$DESIGN_NICKNAME-$PLATFORM-$FLOW_VARIANT.sh for i in $ISSUE_CP_FILE_VARS ; do if [ -v ${i} ]; then diff --git a/flow/util/plot_congestion.py b/flow/util/plot_congestion.py deleted file mode 100644 index dfa0e600a1..0000000000 --- a/flow/util/plot_congestion.py +++ /dev/null @@ -1,30 +0,0 @@ -import matplotlib.pyplot as plt -import numpy as np -import sys -import re -import os - -sweep = sys.argv[1] -output = sys.argv[2] -remainder = sys.argv[3:] -files = remainder[: len(remainder) // 2] -values = remainder[len(remainder) // 2 :] - -# count lines in each file and divide by 3 and create a list of those -# numbers -congestion = [] -for file in files: - with open(file, "r") as f: - lines = f.readlines() - congestion.append(len(lines) // 4) - -# xy plot of density vs DRC errors -x = list(map(float, values)) -y = congestion -plt.plot(x, y, "o-") -plt.xlabel(sweep) -plt.ylabel("DRC Errors") -plt.title(sweep + " vs DRC Errors") -plt.grid() -plt.yscale("log") -plt.savefig(output) diff --git a/flow/util/plot_floorplan.py b/flow/util/plot_floorplan.py deleted file mode 100644 index 89bdd4ba58..0000000000 --- a/flow/util/plot_floorplan.py +++ /dev/null @@ -1,188 +0,0 @@ -import os -import matplotlib.pyplot as plt -from math import log - -# -# Helper function to visualize the rtlmp macro placement -# If run in ORFS rtlmp creates a dir in the objext////rtlmp -# link that dir to ./rtlmp -# run python3 utils/plot_floorplan.py -# - - -file_name = "./rtlmp/final_floorplan.txt" -net_file = "./rtlmp/partition.txt.net" - -net_threshold = 1500 - -cluster_list = [] -cluster_lx_list = [] -cluster_ly_list = [] -cluster_ux_list = [] -cluster_uy_list = [] - -macro_list = [] -macro_lx_list = [] -macro_ly_list = [] -macro_ux_list = [] -macro_uy_list = [] - -cluster_dict = {} - - -with open(file_name) as f: - content = f.read().splitlines() -f.close() - - -outline_width = float(content[0].split()[-1]) -outline_height = float(content[1].split()[-1]) - -terminal_dict = {} - -terminal_dict["LM"] = [0, outline_height / 2.0] -terminal_dict["RM"] = [outline_width, outline_height / 2.0] -terminal_dict["BM"] = [outline_width / 2.0, 0] -terminal_dict["TM"] = [outline_width / 2.0, outline_height] -terminal_dict["LL"] = [0, outline_height / 6.0] -terminal_dict["RL"] = [outline_width, outline_height / 6.0] -terminal_dict["BL"] = [outline_width / 6.0, 0.0] -terminal_dict["TL"] = [outline_width / 6.0, outline_height] -terminal_dict["LU"] = [0, outline_height * 5.0 / 6.0] -terminal_dict["RU"] = [outline_width, outline_height * 5.0 / 6.0] -terminal_dict["BU"] = [outline_width * 5.0 / 6.0, 0.0] -terminal_dict["TU"] = [outline_width * 5.0 / 6.0, outline_height] - - -i = 2 -while i < len(content): - words = content[i].split() - if len(words) == 0: - break - else: - cluster_list.append(words[0]) - cluster_lx_list.append(float(words[1])) - cluster_ly_list.append(float(words[2])) - cluster_ux_list.append(float(words[3])) - cluster_uy_list.append(float(words[4])) - cluster_dict[words[0]] = [ - (float(words[1]) + float(words[3])) / 2.0, - (float(words[2]) + float(words[4])) / 2.0, - ] - - i = i + 1 - - -i = i + 1 -while i < len(content): - words = content[i].split() - macro_list.append(words[0]) - macro_lx_list.append(float(words[1])) - macro_ly_list.append(float(words[2])) - macro_ux_list.append(float(words[3])) - macro_uy_list.append(float(words[4])) - i = i + 1 - - -net_list = [] - -with open(net_file) as f: - content = f.read().splitlines() -f.close() - -for line in content: - items = line.split() - if len(items) > 1: - source = items[1] - for j in range(2, len(items), 2): - target = items[j] - weight = float(items[j + 1]) - net_list.append([source, target, weight]) - - -plt.figure() -for i in range(len(cluster_list)): - rectangle = plt.Rectangle( - (cluster_lx_list[i], cluster_ly_list[i]), - cluster_ux_list[i] - cluster_lx_list[i], - cluster_uy_list[i] - cluster_ly_list[i], - fc="r", - ec="blue", - ) - plt.gca().add_patch(rectangle) - - -for i in range(len(macro_list)): - rectangle = plt.Rectangle( - (macro_lx_list[i], macro_ly_list[i]), - macro_ux_list[i] - macro_lx_list[i], - macro_uy_list[i] - macro_ly_list[i], - fc="yellow", - ec="blue", - ) - plt.gca().add_patch(rectangle) - - -for i in range(len(net_list)): - source = net_list[i][0] - target = net_list[i][1] - weight = net_list[i][2] - - x = [] - y = [] - - if source in cluster_dict: - x.append(cluster_dict[source][0]) - y.append(cluster_dict[source][1]) - else: - x.append(terminal_dict[source][0]) - y.append(terminal_dict[source][1]) - - if target in cluster_list: - x.append(cluster_dict[target][0]) - y.append(cluster_dict[target][1]) - else: - x.append(terminal_dict[target][0]) - y.append(terminal_dict[target][1]) - - if weight > net_threshold: - plt.plot(x, y, "k", lw=log(weight)) - - -x = [] -y = [] -x.append(0) -y.append(0) -x.append(outline_width) -y.append(0) -plt.plot(x, y, "--k") - -x = [] -y = [] -x.append(0) -y.append(0) -x.append(0) -y.append(outline_height) -plt.plot(x, y, "--k") - -x = [] -y = [] -x.append(0) -y.append(outline_height) -x.append(outline_width) -y.append(outline_height) -plt.plot(x, y, "--k") - -x = [] -y = [] -x.append(outline_width) -y.append(0) -x.append(outline_width) -y.append(outline_height) -plt.plot(x, y, "--k") - - -plt.xlim(0, outline_width) -plt.ylim(0, outline_height) -plt.axis("scaled") -plt.show() diff --git a/flow/util/utils.mk b/flow/util/utils.mk index f9f998aaff..25c1cfc2ac 100644 --- a/flow/util/utils.mk +++ b/flow/util/utils.mk @@ -91,6 +91,12 @@ write_net_rc: $(RESULTS_DIR)/6_net_rc.csv $(RESULTS_DIR)/6_net_rc.csv: ($(TIME_CMD) $(OPENROAD_CMD) $(UTILS_DIR)/write_net_rc_script.tcl) 2>&1 | tee $(LOG_DIR)/6_write_net_rc.log +.PHONY: write_segment_rc +write_segment_rc: $(RESULTS_DIR)/6_segment_rc.csv + +$(RESULTS_DIR)/6_segment_rc.csv: + ($(TIME_CMD) $(OPENROAD_CMD) $(UTILS_DIR)/write_segment_rc_script.tcl) 2>&1 | tee $(LOG_DIR)/6_write_segment_rc.log + .PHONY: correlate_rc correlate_rc: $(RESULTS_DIR)/6_net_rc.csv $(PYTHON_EXE) $(UTILS_DIR)/correlateRC.py $(RESULTS_DIR)/6_net_rc.csv @@ -151,7 +157,7 @@ $(RESULTS_DIR)/6_final_no_power.def: $(RESULTS_DIR)/6_final.def .PHONY: gallery -gallery: $(RESULTS_DIR)/6_final_no_power.def $(RESULTS_DIR)/6_final_only_clk.def +gallery: check-klayout $(RESULTS_DIR)/6_final_no_power.def $(RESULTS_DIR)/6_final_only_clk.def ($(TIME_CMD) klayout -z -nc -rx -rd gallery_json=util/gallery.json \ -rd results_path=$(RESULTS_DIR) \ -rd tech_file=$(OBJECTS_DIR)/klayout.lyt \ diff --git a/flow/util/write_net_rc.tcl b/flow/util/write_net_rc.tcl index c9d083034a..fbe7c956fd 100644 --- a/flow/util/write_net_rc.tcl +++ b/flow/util/write_net_rc.tcl @@ -33,7 +33,6 @@ proc report_var_caps { var_name count } { } proc write_rc_csv { filename } { - upvar 1 gpl gpl_net_name_to_rc upvar 1 grt grt_net_name_to_rc upvar 1 rcx rcx_net_name_to_rc @@ -68,13 +67,11 @@ proc write_rc_csv { filename } { (!$use_drt_data || [$db_net getWire] ne "NULL") } { set net_name [get_full_name $net] - lassign $gpl_net_name_to_rc($net_name) gpl_net_res gpl_net_cap lassign $grt_net_name_to_rc($net_name) grt_net_res grt_net_cap lassign $rcx_net_name_to_rc($net_name) rcx_net_res rcx_net_cap set net_type [expr { [string equal $type "CLOCK"] ? "clock" : "signal" }] puts -nonewline $stream "[get_full_name $net],$net_type," puts -nonewline $stream [concat \ - [format "%.3e" $gpl_net_res] "," [format "%.3e" $gpl_net_cap] "," \ [format "%.3e" $grt_net_res] "," [format "%.3e" $grt_net_cap] "," \ [format "%.3e" $rcx_net_res] "," [format "%.3e" $rcx_net_cap]] set db_net [sta::sta_to_db_net $net] diff --git a/flow/util/write_net_rc_script.tcl b/flow/util/write_net_rc_script.tcl index a2815ce5a6..0b7cd71a55 100644 --- a/flow/util/write_net_rc_script.tcl +++ b/flow/util/write_net_rc_script.tcl @@ -3,16 +3,11 @@ load_design 6_final.odb 6_final.sdc source $::env(UTILS_DIR)/write_net_rc.tcl -estimate_parasitics -placement -record_wire_rc gpl - estimate_parasitics -global_routing record_wire_rc grt read_spef $::env(RESULTS_DIR)/6_final.spef record_wire_rc rcx -#compare_wire_rc 50 grt rcx - -# write gpl/grt/rcx rc file for correlateRC.py +# write grt/rcx rc file for correlateRC.py write_rc_csv $::env(RESULTS_DIR)/6_net_rc.csv diff --git a/flow/util/write_segment_rc.tcl b/flow/util/write_segment_rc.tcl new file mode 100644 index 0000000000..05ce8b30a7 --- /dev/null +++ b/flow/util/write_segment_rc.tcl @@ -0,0 +1,90 @@ +# This function only works if each routing wire shape corresponds +# to one parasitic resistive model. +proc fetch_segments_rc { net_to_segments_var } { + upvar 1 $net_to_segments_var net_to_segments + + foreach sta_net [get_nets -hierarchical *] { + set db_net [sta::sta_to_db_net $sta_net] + set type [$db_net getSigType] + + if { !([string equal $type "CLOCK"] || [string equal $type "SIGNAL"]) } { + continue + } + + set wire [$db_net getWire] + + if { $wire eq "NULL" } { + continue + } + + set segments {} + set seen_shape_ids {} + foreach rseg [$db_net getRSegs] { + set shape [$wire getShape [$rseg getShapeId]] + + # We skip vias as they have no capacitance in RCX. + if { ![$shape isSegment] } { + continue + } + + set shape_id [$rseg getShapeId] + + if { $shape_id in $seen_shape_ids } { + error "Could not fetch segment parasitics data: shape\ + $shape_id on net [$db_net getName] has multiple rsegs." + } + + set layer [[$shape getTechLayer] getName] + + set width [$shape getDX] + set height [$shape getDY] + set length_um [ord::dbu_to_microns [expr { max($width, $height) }]] + + # Default corner + set corner 0 + set resistance [$rseg getResistance $corner] + set capacitance [$rseg getTotalCapacitance $corner] + + lappend segments $layer $length_um $resistance $capacitance + lappend seen_shape_ids $shape_id + } + + set net_to_segments([get_full_name $sta_net]) $segments + } +} + +proc write_segment_rc_csv { filename net_to_segments_var } { + upvar 1 $net_to_segments_var net_to_segments + + set stream [open $filename "w"] + + # First, write a header listing the routing layers in stack order. + puts -nonewline $stream "# routing layers:" + foreach layer [[ord::get_db_tech] getLayers] { + if { [$layer getRoutingLevel] != 0 } { + puts -nonewline $stream " [$layer getName]" + } + } + + puts $stream "" + + # Then, write the parasitics data of each wire segment. + foreach sta_net [get_nets -hierarchical *] { + set net_name [get_full_name $sta_net] + + if { ![info exists net_to_segments($net_name)] } { + continue + } + + set db_net [sta::sta_to_db_net $sta_net] + set type [$db_net getSigType] + set net_type [expr { $type eq "CLOCK" ? "clock" : "signal" }] + + foreach {layer length_um resistance capacitance} $net_to_segments($net_name) { + puts $stream [format "%s,%s,%s,%.3e,%.3e,%.3e" \ + $net_name $net_type $layer $length_um $resistance $capacitance] + } + } + + close $stream +} diff --git a/flow/util/write_segment_rc_script.tcl b/flow/util/write_segment_rc_script.tcl new file mode 100644 index 0000000000..7953deceb9 --- /dev/null +++ b/flow/util/write_segment_rc_script.tcl @@ -0,0 +1,10 @@ +source $::env(SCRIPTS_DIR)/load.tcl +load_design 6_final.odb 6_final.sdc + +source $::env(UTILS_DIR)/write_segment_rc.tcl + +# Set up RCX parameters to avoid any parasitics segment merging. +extract_parasitics -ext_model_file $::env(RCX_RULES) -max_res 0 -no_merge_via_res +fetch_segments_rc rcx + +write_segment_rc_csv $::env(RESULTS_DIR)/6_segment_rc.csv rcx diff --git a/jenkins/public_nightly.Jenkinsfile b/jenkins/public_nightly.Jenkinsfile deleted file mode 100644 index 02c1261812..0000000000 --- a/jenkins/public_nightly.Jenkinsfile +++ /dev/null @@ -1,76 +0,0 @@ -@Library('utils@orfs-v2.3.6') _ - -node { - - properties([copyArtifactPermission('${JOB_NAME},'+env.BRANCH_NAME)]); - - stage('Checkout ORFS') { - checkout([ - $class: 'GitSCM', - branches: [[name: scm.branches[0].name]], - doGenerateSubmoduleConfigurations: false, - extensions: [ - [$class: 'CloneOption', noTags: false], - [$class: 'SubmoduleOption', recursiveSubmodules: true] - ], - submoduleCfg: [], - userRemoteConfigs: scm.userRemoteConfigs - ]); - def description = sh(script: "git log -1 --pretty=%B", returnStdout: true).trim(); - if (description.contains('ci') && description.contains('skip')) { - currentBuild.result = 'SKIPPED'; // 'SUCCESS', 'SKIPPED' - return; - } - } - - - stage('Checkout OpenROAD Latest') { - checkout([$class: "GitSCM", - branches: [[name: "*/master"]], - doGenerateSubmoduleConfigurations: false, - extensions: [ - [ - $class: "SubmoduleOption", - disableSubmodules: false, - parentCredentials: true, - recursiveSubmodules: true, - reference: "", - trackingSubmodules: false - ], - [ - $class: "RelativeTargetDirectory", - relativeTargetDir: "tools/OpenROAD" - ] - ] - ]); - } - - def DOCKER_IMAGE; - stage('Build and Push Docker Image') { - DOCKER_IMAGE = dockerPush('ubuntu22.04', 'orfs'); - echo "Docker image is $DOCKER_IMAGE"; - } - - stage('Build ORFS and Stash bins') { - buildBins(DOCKER_IMAGE, '--local --no_init --latest'); - } - - try { - stage('Run Tests') { - if (env.CHANGE_BRANCH && env.CHANGE_BRANCH.contains('ci-dev')) { - runTests(DOCKER_IMAGE, 'dev'); - } else { - runTests(DOCKER_IMAGE, 'nightly'); - } - } - } catch (e) { - throw e - } finally { - stage ('Cleanup and Reporting') { - env.CHANGE_BRANCH = 'nightly' - env.BRANCH_NAME = 'nightly' - finalReport(DOCKER_IMAGE); - } - } - -} diff --git a/jenkins/public_tests_all.Jenkinsfile b/jenkins/public_tests_all.Jenkinsfile deleted file mode 100644 index 267804ea5a..0000000000 --- a/jenkins/public_tests_all.Jenkinsfile +++ /dev/null @@ -1,71 +0,0 @@ -@Library('utils@orfs-v2.3.6') _ - -node { - - def isDefaultBranch = (env.BRANCH_NAME == 'master') - def daysToKeep = '20'; - def numToKeep = (isDefaultBranch ? '-1' : '10'); - - properties([ - copyArtifactPermission('${JOB_NAME},'+env.BRANCH_NAME), - - buildDiscarder(logRotator( - daysToKeepStr: daysToKeep, - artifactDaysToKeepStr: daysToKeep, - - numToKeepStr: numToKeep, - artifactNumToKeepStr: numToKeep - )) - ]); - - stage('Checkout') { - if (env.BRANCH_NAME && env.BRANCH_NAME == 'master') { - checkout([ - $class: 'GitSCM', - branches: [[name: scm.branches[0].name]], - doGenerateSubmoduleConfigurations: false, - extensions: [ - [$class: 'CloneOption', noTags: false], - [$class: 'SubmoduleOption', recursiveSubmodules: true] - ], - submoduleCfg: [], - userRemoteConfigs: scm.userRemoteConfigs - ]); - } - else { - checkout scm; - } - def description = sh(script: "git log -1 --pretty=%B", returnStdout: true).trim(); - if (description.contains('ci') && description.contains('skip')) { - currentBuild.result = 'SKIPPED'; // 'SUCCESS', 'SKIPPED' - return; - } - } - - def DOCKER_IMAGE; - stage('Build and Push Docker Image') { - DOCKER_IMAGE = dockerPush('ubuntu22.04', 'orfs'); - echo "Docker image is $DOCKER_IMAGE"; - } - - stage('Build ORFS and Stash bins') { - buildBins(DOCKER_IMAGE); - } - - try { - stage('Run Tests') { - if (env.CHANGE_BRANCH && env.CHANGE_BRANCH.contains('ci-dev')) { - runTests(DOCKER_IMAGE, 'dev'); - } else { - runTests(DOCKER_IMAGE, 'pr'); - } - } - } catch (e) { - throw e - } finally { - stage ('Cleanup and Reporting') { - finalReport(DOCKER_IMAGE); - } - } - -} diff --git a/jenkins/public_tests_all.Jenkinsfile b/jenkins/public_tests_all.Jenkinsfile new file mode 120000 index 0000000000..46074c1231 --- /dev/null +++ b/jenkins/public_tests_all.Jenkinsfile @@ -0,0 +1 @@ +../Jenkinsfile \ No newline at end of file diff --git a/setup.sh b/setup.sh index 22a84cfea8..b9f2853e1e 100755 --- a/setup.sh +++ b/setup.sh @@ -5,8 +5,13 @@ set -euo pipefail # allow this script to be invoked from any folder DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -if [ $EUID -ne 0 ]; then - echo "This script must be run with sudo" +if [[ "$OSTYPE" == "darwin"* ]] && [[ $EUID -eq 0 ]]; then + echo "Do NOT run this script with sudo on macOS" + exit 1 +fi + +if [[ "$OSTYPE" != "darwin"* ]] && [[ $EUID -ne 0 ]]; then + echo "This script must be run with sudo on Linux" exit 1 fi @@ -17,7 +22,11 @@ tmpfile=$(mktemp) git submodule status --recursive > "$tmpfile" if grep -q "^-" "$tmpfile"; then - sudo -u $SUDO_USER git submodule update --init --recursive + if [[ "$OSTYPE" == "darwin"* ]]; then + git submodule update --init --recursive + else + sudo -u $SUDO_USER git submodule update --init --recursive + fi elif grep -q "^+" "$tmpfile"; then # Make it easy for users who are not hacking ORFS to do the right thing, # run with current submodules, at the cost of having ORFS @@ -27,4 +36,8 @@ elif grep -q "^+" "$tmpfile"; then fi "$DIR/etc/DependencyInstaller.sh" -base -sudo -u $SUDO_USER "$DIR/etc/DependencyInstaller.sh" -common -prefix="$DIR/dependencies" +if [[ "$OSTYPE" == "darwin"* ]]; then + "$DIR/etc/DependencyInstaller.sh" -common -prefix="$DIR/dependencies" +else + sudo -u $SUDO_USER "$DIR/etc/DependencyInstaller.sh" -common -prefix="$DIR/dependencies" +fi diff --git a/tools/OpenROAD b/tools/OpenROAD index 1f44de5c23..ce7ee82f49 160000 --- a/tools/OpenROAD +++ b/tools/OpenROAD @@ -1 +1 @@ -Subproject commit 1f44de5c231976d8ec020abc631ce5116bd26ac4 +Subproject commit ce7ee82f49a965e90de5dfc8de6e4d7d32534984 diff --git a/tools/kepler-formal b/tools/kepler-formal index 8d74eb30df..ae2acd4aa8 160000 --- a/tools/kepler-formal +++ b/tools/kepler-formal @@ -1 +1 @@ -Subproject commit 8d74eb30df93f2d73adf11b4a3438d5f34b95ce7 +Subproject commit ae2acd4aa825fbbffdc4f8e6591b720a4a0a9e12 diff --git a/tools/yosys b/tools/yosys index 776b4d06a6..9ed031ddd5 160000 --- a/tools/yosys +++ b/tools/yosys @@ -1 +1 @@ -Subproject commit 776b4d06a649e5d07db74e3e0b19bd761f599e24 +Subproject commit 9ed031ddd588442f22be13ce608547a5809b62f0