Versioning Improvements (#510)

* Get OpenLane version

* Remove OpenPhySyn and Antmicro Yosys

* Time-based tag names, current -> latest

* Made local installer comply with new versioning scheme

* Made Docker Get Commit/Repo Info From YAML file

~ Updater now also updates just the YAML file
~ Main makefile PDK option also consults the YAML file
~ Updated CI to reflect the above changes + reduce redundancy (Cleanup and Deploy Folded)

* CI Bugfix

* One Final CI Fix
This commit is contained in:
Donn
2021-07-28 23:09:50 +02:00
committed by GitHub
parent 71c064fbf2
commit 8d70ae306f
39 changed files with 423 additions and 806 deletions

View File

@@ -15,6 +15,7 @@
# limitations under the License.
import re
import os
import datetime
import subprocess
from gh import gh
@@ -22,24 +23,14 @@ new_tag = "NO_NEW_TAG"
print("Getting latest release index…")
lri = None
for tag in gh.openlane.tags:
_, name = tag
if "release-" in name:
relevant_component = name.split("-")[1]
lri = relevant_component.split(".")[0]
print("Getting the latest tag…")
prefix = lri if lri is not None else "v0"
print("Using prefix %s, getting the latest tag…" % prefix)
latest_tag = "%s.0" % prefix # Base case: Will create prefix.1
latest_tag_commit = "dad497fccc1b48f4f16e570b0214b6f0e1fc2f9b" # Base case: First commit, always > 2
latest_tag = None
latest_tag_commit = None
for tag in gh.openlane.tags:
commit, name = tag
if name.startswith(prefix):
latest_tag = name
latest_tag_commit = commit
latest_tag = name
latest_tag_commit = commit
commit_count = int(subprocess.check_output(["git", "rev-list", "--count", "%s..%s" % (latest_tag_commit, "HEAD")]))
@@ -48,14 +39,9 @@ if commit_count == 0:
gh.export_env("NEW_TAG", "NO_NEW_TAG")
exit(0)
new_tag = None
if not latest_tag.startswith("v"):
new_tag = "%s.1" % prefix
print("Last tag (%s) lacked a v, replacing with %s" % (latest_tag, new_tag))
else:
current = int(latest_tag.split(".")[1])
new = current + 1
new_tag = "%s.%i" % (prefix, new)
now = datetime.datetime.now()
new_tag = now.strftime("%Y.%m.%d_%H.%M.%S")
print("Naming new tag %s." % new_tag)
gh.export_env("NEW_TAG", new_tag)

16
.github/scripts/gh.py vendored
View File

@@ -93,17 +93,7 @@ class Repo(object):
tags.append((hash, name))
self._tags = tags
return self._tags
# Helper Functions
def match_branch(self, line):
match = re.match(self.branch_rx, line)
if match is not None:
return match[1]
def match_line(self, line):
match = re.match(self.extraction_rx, line)
if match is not None:
return match[1]
def out_of_date(self):
return self.commit != self.latest_commit
@@ -132,8 +122,8 @@ if os.getenv("GITHUB_ACTIONS") != "true":
export_env = export_env_alt
if os.getenv("TOOL") is None or os.getenv("PDK_ROOT") is None:
print("Environment variables \"TOOL\" and \"PDK_ROOT\" are required.")
if os.getenv("PDK_ROOT") is None:
print("Environment variables required: \"PDK_ROOT\"")
exit(os.EX_CONFIG)
origin = os.getenv("REPO_URL")

View File

@@ -1,49 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2020 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
from gh import gh
def process_update_on_repos(repos, files):
changed = False
for repo in repos:
print("Processing %s" % repo.name)
if not repo.out_of_date():
print("%s's commit is already on latest. No action required." % repo.name)
continue
# print("Checking if branch was already created…")
# branch_commit = None
# for branch in gh.openlane.branches:
# _, name = branch
# branch_commit = repo.match_branch(name) or branch_commit
# if branch_commit is not None and branch_commit == repo.latest_commit:
# print("Branch was already created for the latest commit. No update required.")
# continue
# if branch_commit is not None:
# print("Branch is out of date. Updating…")
# else:
# print("No matching branch found. Updating…")
changed = True
for file in files:
fstr = open(file).read()
new_fstr = re.sub(repo.commit, repo.latest_commit, fstr)
with open(file, 'w') as f:
f.write(new_fstr)
return changed

View File

@@ -1,51 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2020 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
import os
import subprocess
from gh import gh
from update_common import process_update_on_repos
makefile = os.path.join(gh.root, "Makefile")
documentation = os.path.join(gh.root, "docs", "source", "Manual_PDK_installation.md")
print("Reading Makefile…")
skywater = gh.Repo(
"Skywater PDK",
"https://github.com/google/skywater-pdk.git",
r"refs/heads/CID\-latest\-pdk(?:\-(\w+)-(?:\w+))?",
r"SKYWATER_COMMIT\s*\?=\s*(\w+)"
)
open_pdks = gh.Repo(
"Open PDKs",
"https://github.com/rtimothyedwards/open_pdks",
r"refs/heads/CID\-latest\-pdk(?:\-(?:\w+)-(\w+))?",
r"OPEN_PDKS_COMMIT\s*\?=\s*(\w+)"
)
with open(makefile) as f:
for line in f:
skywater.commit = skywater.match_line(line) or skywater.commit
open_pdks.commit = open_pdks.match_line(line) or open_pdks.commit
print("Found %s:%s. (latest: %s)" % (skywater.url, skywater.commit, skywater.latest_commit))
print("Found %s:%s. (latest: %s)" % (open_pdks.url, open_pdks.commit, open_pdks.latest_commit))
changed = process_update_on_repos([skywater, open_pdks], [makefile, documentation])
gh.export_env("SKYWATER_COMMIT_HASH", skywater.latest_commit)
gh.export_env("OPEN_PDKS_COMMIT_HASH", open_pdks.latest_commit)
gh.export_env("NO_UPDATE", "false" if changed else "true")

View File

@@ -1,46 +0,0 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2020 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re
import os
import subprocess
from gh import gh
from update_common import process_update_on_repos
dockerfile = os.path.join(gh.root, "docker_build", "docker", gh.tool, "Dockerfile")
print("Reading Dockerfile %s" % dockerfile)
repo = None
commit = None
repo_rx = r"ARG\s+(?:\w+?)_REPO\s*=\s*([^\s]+)"
commit_rx = r"ARG\s+(?:\w+?)_COMMIT\s*=\s*([^\s]+)"
with open(dockerfile) as f:
for line in f:
repo_match = re.match(repo_rx, line)
if repo_match is not None:
repo = repo_match[1]
commit_match = re.match(commit_rx, line)
if commit_match is not None:
commit = commit_match[1]
tool = gh.Repo(
gh.tool, repo, r"refs/heads/CID\-latest\-tools\-%s(?:\-(\w+))?" % gh.tool
)
tool.commit = commit
print("Found %s@%s (latest: %s)." % (tool.url, tool.commit, tool.latest_commit))
changed = process_update_on_repos([tool], [dockerfile])
gh.export_env("TOOL_COMMIT_HASH", tool.latest_commit)
gh.export_env("NO_UPDATE", "false" if changed else "true")

70
.github/scripts/update_tools.py vendored Normal file
View File

@@ -0,0 +1,70 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2020 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import sys
import yaml
import argparse
from gh import gh
dependencies_path = os.path.join(gh.root, "dependencies")
metadata_path = os.path.join(dependencies_path, "tool_metadata.yml")
sys.path.append(dependencies_path)
from tool import Tool
parser = argparse.ArgumentParser()
parser.add_argument("tools", nargs="+")
args = parser.parse_args()
tools = Tool.from_metadata_yaml(open(metadata_path).read())
# Handle Multiline Strings Properly / https://stackoverflow.com/a/33300001
def represent_str(dumper: yaml.Dumper, data: str):
if "\n" in data:
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
return dumper.represent_scalar('tag:yaml.org,2002:str', data)
yaml.add_representer(str, represent_str)
dump_options = { 'sort_keys': False }
changes = False
for tool_name in args.tools:
tool = tools[tool_name]
repo = gh.Repo(
tool_name, tool.repo
)
repo.commit = tool.commit
print("Found %s@%s (latest: %s)." % (repo.url, repo.commit, repo.latest_commit))
if repo.commit != repo.latest_commit:
changes = True
metadata_str = open(metadata_path).read()
metadata = yaml.safe_load(metadata_str)
for tool in metadata:
if tool['name'] == tool_name:
tool['commit'] = repo.latest_commit
metadata_str = yaml.dump(metadata, **dump_options)
with open(metadata_path, "w") as f:
f.write(metadata_str)
if len(args.tools) == 1:
gh.export_env("TOOL_COMMIT_HASH", repo.latest_commit)
else:
gh.export_env(f"{tool_name.upper()}_COMMIT_HASH", repo.latest_commit)
gh.export_env("NO_UPDATE", "0" if changes else "1")

View File

@@ -127,21 +127,19 @@ jobs:
env:
TEST_SET: completeTestSet${{ matrix.testset }}
run: cd ${GITHUB_WORKSPACE}/ && python3 ${GITHUB_WORKSPACE}/.github/scripts/run_tests.py
cleanup:
needs: test
if: ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-latest
steps:
- name: Delete Artifact
uses: geekyeggo/delete-artifact@v1
with:
name: docker-image
deploy:
cleanup_and_deploy:
name: Cleanup (and Possibly Deployment)
needs: test
if: ${{ github.event_name != 'pull_request' }}
runs-on: ubuntu-latest
steps:
- name: Check If Going To Push An Image To Docker
# Ruby snippet to print 0 if this is a PR or if there is no DOCKERHUB_USER secret set, otherwise, 1
run: |
export PUSHING=$(ruby -e 'if ("${{ github.event_name }}" != "pull_request" && "${{ secrets.DOCKERHUB_USER }}" != ""); print(1) else print(0) end')
echo "PUSHING=$PUSHING" >> $GITHUB_ENV
- uses: actions/checkout@v2
if: ${{ env.PUSHING == '1' }}
with:
fetch-depth: 0
@@ -167,6 +165,7 @@ jobs:
run: echo "IMAGE_NAME=openlane:intermediate" >> $GITHUB_ENV
- name: Download Docker Image
if: ${{ env.PUSHING == '1' }}
uses: actions/download-artifact@v2
with:
name: docker-image
@@ -178,43 +177,42 @@ jobs:
name: docker-image
- name: Import Docker Image
if: ${{ env.PUSHING == '1' }}
run: docker load --input /tmp/image.tar
- name: Write Main Branch
if: ${{ env.PUSHING == '1' }}
run: |
echo "MAIN_BRANCH=${{ secrets.MAIN_BRANCH }}" >> $GITHUB_ENV
- name: Create Tag (If scheduled or dispatched)
if: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && env.BRANCH_NAME == env.MAIN_BRANCH }}
if: ${{ env.PUSHING == '1' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && env.BRANCH_NAME == env.MAIN_BRANCH }}
run: cd ${GITHUB_WORKSPACE}/ && python3 ${GITHUB_WORKSPACE}/.github/scripts/generate_tag.py
- name: Tag Commit (If scheduled or dispatched)
if: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && env.NEW_TAG != 'NO_NEW_TAG' }}
if: ${{ env.PUSHING == '1' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && env.NEW_TAG != 'NO_NEW_TAG' }}
uses: tvdias/github-tagger@v0.0.1
with:
tag: "${{ env.NEW_TAG }}"
repo-token: "${{ secrets.MY_TOKEN }}"
- name: Login to DockerHub
if: ${{ env.PUSHING == '1' }}
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USER }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Docker Push (Branch Name)
if: ${{ env.PUSHING == '1' }}
run: |
TAG=${{ env.BRANCH_NAME }}
if [ "$TAG" = "${{ secrets.MAIN_BRANCH }}" ]; then
TAG=latest
fi
docker image tag ${{ env.IMAGE_NAME }} ${{ secrets.DOCKER_IMAGE }}:$TAG
docker push ${{ secrets.DOCKER_IMAGE }}:$TAG
docker image tag ${{ env.IMAGE_NAME }} ${{ secrets.DOCKER_IMAGE }}:${{ env.BRANCH_NAME }}
docker push ${{ secrets.DOCKER_IMAGE }}:${{ env.BRANCH_NAME }}
- name: Docker Push (Tag) (If scheduled or dispatched)
if: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && env.NEW_TAG != 'NO_NEW_TAG' }}
if: ${{ env.PUSHING == '1' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && env.NEW_TAG != 'NO_NEW_TAG' }}
run: |
docker image tag ${{ env.IMAGE_NAME }} ${{ secrets.DOCKER_IMAGE }}:${{ env.NEW_TAG }}
docker image tag ${{ env.IMAGE_NAME }} ${{ secrets.DOCKER_IMAGE }}:current
docker image tag ${{ env.IMAGE_NAME }} ${{ secrets.DOCKER_IMAGE }}:latest
docker push ${{ secrets.DOCKER_IMAGE }}:${{ env.NEW_TAG }}
docker push ${{ secrets.DOCKER_IMAGE }}:current
docker push ${{ secrets.DOCKER_IMAGE }}:latest

View File

@@ -40,14 +40,14 @@ jobs:
run: echo "TOOL=${{ matrix.tools }}" >> $GITHUB_ENV
- name: Update TOOL
run: cd ${GITHUB_WORKSPACE}/ && python3 ${GITHUB_WORKSPACE}/.github/scripts/update_tool.py
run: cd ${GITHUB_WORKSPACE}/ && python3 ${GITHUB_WORKSPACE}/.github/scripts/update_tools.py ${{ env.TOOL }}
- name: Build TOOL
if: ${{ env.NO_UPDATE == 'false' }}
if: ${{ env.NO_UPDATE != '1' }}
run: cd ${GITHUB_WORKSPACE}/docker_build && make build-${{ env.TOOL }}
- name: Create Pull Request
if: ${{ env.NO_UPDATE == 'false' }}
if: ${{ env.NO_UPDATE != '1' }}
uses: peter-evans/create-pull-request@v3
with:
token: ${{ secrets.MY_TOKEN }}
@@ -82,10 +82,10 @@ jobs:
ref: ${{ secrets.MAIN_BRANCH }}
- name: Update PDK
run: python3 ${GITHUB_WORKSPACE}/.github/scripts/update_pdk.py
run: python3 ${GITHUB_WORKSPACE}/.github/scripts/update_tools.py sky130 open_pdks
- name: Create Pull Request
if: ${{ env.NO_UPDATE == 'false' }}
if: ${{ env.NO_UPDATE != '1' }}
uses: peter-evans/create-pull-request@v3
with:
token: ${{ secrets.MY_TOKEN }}
@@ -97,7 +97,7 @@ jobs:
commit-message: |
[BOT] Update PDK
sky130 -> ${{ env.SKYWATER_COMMIT_HASH }}
sky130 -> ${{ env.SKY130_COMMIT_HASH }}
open_pdks -> ${{ env.OPEN_PDKS_COMMIT_HASH }}
base: ${{ env.BRANCH_NAME }}
branch: pdk-update-branch

3
.gitignore vendored
View File

@@ -29,3 +29,6 @@ default.cvcrc
# PDK
pdks/
# Misc
/resolved_version

View File

@@ -48,7 +48,8 @@ SPECIAL_VOLTAGE_LIBRARY ?= sky130_fd_sc_hvl
IO_LIBRARY ?= sky130_fd_io
INSTALL_SRAM ?= disabled
IMAGE_NAME ?= efabless/openlane:current
CURRENT_TAG ?= $(shell python3 ./get_tag.py)
IMAGE_NAME ?= efabless/openlane:$(CURRENT_TAG)
TEST_DESIGN ?= spm
DESIGN_LIST ?= spm
BENCHMARK ?= regression_results/benchmark_results/SW_HD.csv
@@ -57,8 +58,8 @@ FASTEST_TEST_SET_TAG ?= FASTEST_TEST_SET
COMPLETE_TEST_SET_TAG ?= COMPLETE_TEST_SET
PRINT_REM_DESIGNS_TIME ?= 0
SKYWATER_COMMIT ?= 00bdbcf4a3aa922cc1f4a0d0cd8b80dbd73149d3
OPEN_PDKS_COMMIT ?= 1d93a6bd9d6e481acfdf88f26aa3bb0600303d98
SKYWATER_COMMIT ?= $(shell python3 ./dependencies/tool.py sky130 -f commit)
OPEN_PDKS_COMMIT ?= $(shell python3 ./dependencies/tool.py open_pdks -f commit)
ENV_COMMAND ?= docker run --rm -v $(OPENLANE_DIR):/openLANE_flow -v $(PDK_ROOT):$(PDK_ROOT) -e PDK_ROOT=$(PDK_ROOT) $(DOCKER_UID_OPTIONS) $(IMAGE_NAME)
@@ -87,7 +88,7 @@ $(PDK_ROOT)/:
mkdir -p $(PDK_ROOT)
$(PDK_ROOT)/skywater-pdk:
git clone https://github.com/google/skywater-pdk.git $(PDK_ROOT)/skywater-pdk
git clone $(shell python3 ./dependencies/tool.py sky130 -f repo) $(PDK_ROOT)/skywater-pdk
.PHONY: skywater-pdk
skywater-pdk: $(PDK_ROOT)/ $(PDK_ROOT)/skywater-pdk
@@ -117,7 +118,7 @@ all-skywater-libraries: skywater-pdk
### OPEN_PDKS
$(PDK_ROOT)/open_pdks:
git clone https://github.com/rtimothyedwards/open_pdks $(PDK_ROOT)/open_pdks
git clone $(shell python3 ./dependencies/tool.py open_pdks -f repo) $(PDK_ROOT)/open_pdks
.PHONY: open_pdks
open_pdks: $(PDK_ROOT)/ $(PDK_ROOT)/open_pdks

View File

@@ -31,7 +31,12 @@ This documentation is also available at [ReadTheDocs](https://openlane.readthedo
- [Videos And Tutorials](#videos-and-tutorials)
# Prerequisites
At a minimum:
- Docker 19.03.12+
- GNU Make
- Python 3.6+ with PIP
- Pyyaml: `pip3 install pyyaml`
## Dockerless Install
Please see [LOCAL_INSTALL.md](./LOCAL_INSTALL.md).
@@ -44,7 +49,6 @@ You can start setting up the Sky130 PDK and OpenLane by running:
cd openlane/
make openlane
```
* Note that `make openlane` always pulls the **latest** version of OpenLane: to get a specific tag, you need to invoke `IMAGE_NAME=efabless/openlane:v0.18 make openlane`, for example.
---
@@ -119,7 +123,7 @@ To setup OpenLane you can pull the Docker container by following these instructi
```bash
git clone https://github.com/The-OpenROAD-Project/OpenLane.git
docker pull efabless/openlane:current
make openlane
```
For curious users: For more details about the docker container and its process, the [following instructions][1] walk you through the process of using docker containers to build the needed tools then integrate them into OpenLane flow. **You Don't Need To Re-Build It.**
@@ -359,8 +363,7 @@ OpenLane flow consists of several stages. By default all flow steps are run in s
3. **Placement**
1. `RePLace` - Performs global placement
2. `Resizer` - Performs optional optimizations on the design
3. `OpenPhySyn` - Performs timing optimizations on the design
4. `OpenDP` - Perfroms detailed placement to legalize the globally placed components
3. `OpenDP` - Perfroms detailed placement to legalize the globally placed components
4. **CTS**
1. `TritonCTS` - Synthesizes the clock distribution network (the clock tree)
5. **Routing**
@@ -381,7 +384,7 @@ OpenLane integrated several key open source tools over the execution stages:
- RTL Synthesis, Technology Mapping, and Formal Verification : [yosys + abc][4]
- Static Timing Analysis: [OpenSTA][8]
- Floor Planning: [init_fp][5], [ioPlacer][6], [pdn][16] and [tapcell][7]
- Placement: [RePLace][9] (Global), [Resizer][15] and [OpenPhySyn][28] (Optimizations), and [OpenDP][10] (Detailed)
- Placement: [RePLace][9] (Global), [Resizer][15] and [OpenPhySyn][28] (formerly), and [OpenDP][10] (Detailed)
- Clock Tree Synthesis: [TritonCTS][11]
- Fill Insertion: [OpenDP/filler_placement][10]
- Routing: [FastRoute][12] or [CU-GR][36] (Global) and [TritonRoute][13] (Detailed)

View File

@@ -103,9 +103,6 @@ These variables are optional that can be specified in the design configuration f
| `PL_RANDOM_GLB_PLACEMENT` | Specifies whether the placer should run random placement or not. This is useful if the design is tiny (less than 100 cells). 0 = false, 1 = true <br> (Default: `0`) |
| `PL_RANDOM_INITIAL_PLACEMENT` | Specifies whether the placer should run random placement or not followed by replace's initial placement. This is useful if the design is tiny (less than 100 cells). 0 = false, 1 = true <br> (Default: `0`) |
| `PL_ROUTABILITY_DRIVEN` | Specifies whether the placer should use routability driven placement. 0 = false, 1 = true <br> (Default: `0`) |
| `PL_OPENPHYSYN_OPTIMIZATIONS` | Specifies whether OpenPhySyn should be used to perform timing optimizations or not. 0 = false, 1 = true <br> (Default: `0`) |
| `PSN_ENABLE_RESIZING` | Enables driver resizing by OpenPhySyn. 0 = Disabled, 1 = Enabled <br> (Default: `1`)|
| `PSN_ENABLE_PIN_SWAP` | Enables pin swapping for timing optimization by OpenPhySyn. 0 = Disabled, 1 = Enabled <br> (Default: `1`)|
| `PL_RESIZER_DESIGN_OPTIMIZATIONS` | Specifies whether resizer design optimizations should be performed or not. 0 = false, 1 = true <br> (Default: `1`) |
| `PL_RESIZER_TIMING_OPTIMIZATIONS` | Specifies whether resizer timing optimizations should be performed or not. 0 = false, 1 = true <br> (Default: `1`) |
| `PL_RESIZER_MAX_WIRE_LENGTH` | Specifies the maximum wire length cap used by resizer to insert buffers. If set to 0, no buffers will be inserted. Value in microns. <br> (Default: `0`)|

View File

@@ -20,7 +20,6 @@ set ::env(PL_RANDOM_GLB_PLACEMENT) 0
set ::env(PL_BASIC_PLACEMENT) 0
set ::env(PL_SKIP_INITIAL_PLACEMENT) 0
set ::env(PL_RANDOM_INITIAL_PLACEMENT) 0
set ::env(PL_OPENPHYSYN_OPTIMIZATIONS) 0
set ::env(PSN_ENABLE_RESIZING) 1
set ::env(PSN_ENABLE_PIN_SWAP) 1
set ::env(PL_ESTIMATE_PARASITICS) 1

View File

@@ -1,5 +1,5 @@
https://repo.ius.io/ius-release-el7.rpm
https://www.klayout.org/downloads/CentOS_7/klayout-0.26.9-0.x86_64.rpm
https://www.klayout.org/downloads/CentOS_7/klayout-0.27.3-0.x86_64.rpm
centos-release-scl
devtoolset-8

View File

@@ -1,64 +0,0 @@
#!/usr/bin/env ruby
# Copyright 2021 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This is a simple script that looks for all the yum packages installed by the
# Docker images. It's finicky and will likely require human cleanup for the results.
# The ubuntu list was manually translated from the results for centos7.
require 'set'
dockerfiles = `find ../docker_build | grep Dockerfile`.split("\n")
yum_packages_set = Set.new
for file in dockerfiles
str = File.read(file)
entries = str.split("\n")
i = 0
while i < entries.count
if not entries[i].end_with?("\\")
i += 1
next
end
eil = entries[i].length
entries[i] = entries[i][...eil - 1] + entries[i + 1]
entries.delete_at(i + 1)
end
for entry in entries
yum_rx = /\s*yum\s+(?:\-y\s+)?install\s+([^&]+)/
matches = entry.scan(yum_rx)
if matches.count == 0
next
end
for match in matches
packages = match[0].split(/\s+/)
yum_packages_set.merge(packages)
end
end
end
yum_package_list_raw = Array(yum_packages_set).sort
yum_package_list = yum_package_list_raw.filter { |p|
not p.start_with?("-") and
not p.include?("/") and
not p.include?(".")
}
puts yum_package_list

1
dependencies/python/compile_time.txt vendored Normal file
View File

@@ -0,0 +1 @@
cmake

8
dependencies/python/run_time.txt vendored Normal file
View File

@@ -0,0 +1,8 @@
click
pyyaml
pyinstaller
matplotlib
jinja2<3.0.0
pandas
install
XlsxWriter

View File

@@ -1,4 +0,0 @@
cmake
click
pyyaml
pyinstaller

81
dependencies/tool.py vendored Normal file
View File

@@ -0,0 +1,81 @@
# Copyright 2021 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import yaml
from typing import Dict, List
class Tool(object):
def __init__(self, name, repo, commit, build_script="make && make install", in_install=True, in_container=True):
self.name = name
self.repo = repo
self.commit = commit
self.build_script = build_script
self.in_install = in_install
self.in_container = in_container
@property
def repo_pretty(self):
gh_prefix = "https://github.com/"
repo = self.repo
if repo is not None and repo.startswith(gh_prefix):
return repo[len(gh_prefix):]
return repo
@property
def version_string(self) -> str:
return f"{self.repo or 'None'}:{self.commit or 'None'}"
def __repr__(self) -> str:
return f"<Tool {self.name} (using {self.repo_pretty or 'None'}@{self.commit or 'None'})>"
@staticmethod
def from_metadata_yaml(metadata_yaml: str) -> Dict[str, 'Tool']:
final_dict = {}
tool_list = yaml.load(metadata_yaml, Loader=yaml.SafeLoader)
for tool in tool_list:
final_dict[tool['name']] = Tool(
name=tool['name'],
repo=tool['repo'],
commit=tool['commit'],
build_script=tool['build'],
in_container=tool.get('in_container') or True,
in_install=tool.get('in_install') or True
)
return final_dict
def main():
import os
import argparse
parser = argparse.ArgumentParser(description="Get Tool Info")
parser.add_argument("--docker-args", action="store_true")
parser.add_argument("--field", "-f")
parser.add_argument("tool")
tools = Tool.from_metadata_yaml(open(os.path.join(os.path.dirname(__file__), "tool_metadata.yml")).read())
args = parser.parse_args()
tool = tools[args.tool]
if args.docker_args:
print(f"--build-arg {tool.name.upper()}_REPO={tool.repo} --build-arg {tool.name.upper()}_COMMIT={tool.commit}", end="")
elif args.field:
field = tool.__dict__[args.field]
print(field, end="")
else:
print("Either --field or --docker-args is required.")
exit(os.EX_USAGE)
if __name__ == "__main__":
main()

View File

@@ -1,159 +0,0 @@
# Copyright 2021 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from typing import Dict
class Tool(object):
map: Dict[str, 'Tool'] = {}
def __init__(self, name, repo=None, commit=None, install_command="make && make install", skip=False, clone_depth=None):
self.name = name
self.repo = repo
self.commit = commit
self.install_command = install_command
self.skip = skip
self.clone_depth = str(clone_depth) if clone_depth is not None else None
Tool.map[self.name] = self
@property
def repo_pretty(self):
gh_prefix = "https://github.com/"
repo = self.repo
if repo is not None and repo.startswith(gh_prefix):
return repo[len(gh_prefix):]
return repo
@property
def version_string(self):
return f"{self.repo or 'None'}:{self.commit or 'None'}"
def __repr__(self) -> str:
return f"<Tool {self.name} (using {self.repo_pretty or 'None'}@{self.commit or 'None'})>"
Tool(
"antmicro_yosys",
install_command="\
make PREFIX=$PREFIX/antmicro config-gcc &&\
make PREFIX=$PREFIX/antmicro -j$(nproc) &&\
make PREFIX=$PREFIX/antmicro install\
",
skip=True
)
Tool(
"cugr",
install_command="\
xxd -i src/flute/POST9.dat > src/flute/POST9.c &&\
xxd -i src/flute/POWV9.dat > src/flute/POWV9.c &&\
rm -rf build/ &&\
mkdir -p build/ &&\
cd build &&\
cmake ../src &&\
make -j$(nproc) &&\
cp iccad19gr $PREFIX/bin/cugr\
"
)
Tool(
"cvc",
install_command="\
autoreconf -i &&\
autoconf &&\
./configure --disable-nls --prefix=$PREFIX &&\
make install\
"
)
Tool(
"drcu",
install_command="\
rm -rf build/ &&\
mkdir -p build/ &&\
cd build &&\
cmake ../src &&\
make -j$(nproc) &&\
cp ispd19dr $PREFIX/bin/drcu\
"
)
Tool(
"magic",
install_command="\
./configure --prefix=$PREFIX &&\
make -j$(nproc) &&\
make install\
"
)
Tool(
"netgen",
install_command="\
./configure --prefix=$PREFIX &&\
make -j$(nproc) &&\
make install\
"
)
Tool(
"openphysyn",
install_command="\
mkdir -p ./build &&\
cd ./build &&\
cmake .. &&\
make -DCMAKE_BUILD_TYPE=release -j$(nproc)&&\
cp Psn $PREFIX/bin/Psn\
",
skip=True
)
Tool(
"openroad_app",
install_command="\
mkdir -p ./build &&\
cd ./build &&\
cmake -DCMAKE_INSTALL_PREFIX=$PREFIX/bin .. &&\
make -j$(nproc)\
",
skip=True
)
Tool(
"padring",
install_command="\
bash ./bootstrap.sh &&\
cd build &&\
ninja &&\
cp padring $PREFIX/bin\
"
)
Tool(
"qflow", # We just want vlog_to_verilog though
install_command="\
./configure &&\
cd src &&\
make -j$(nproc) vlog2Verilog &&\
cp vlog2Verilog $PREFIX/bin\
"
)
Tool(
"yosys",
install_command="\
make PREFIX=$PREFIX config-gcc &&\
make PREFIX=$PREFIX -j$(nproc) &&\
make PREFIX=$PREFIX install\
"
)

86
dependencies/tool_metadata.yml vendored Normal file
View File

@@ -0,0 +1,86 @@
- name: cugr
repo: https://github.com/ax3ghazy/cu-gr
commit: 1632b4b450cbd3e5b6bdc9bf92c96cadde6a01b9
build: |
xxd -i src/flute/POST9.dat > src/flute/POST9.c
xxd -i src/flute/POWV9.dat > src/flute/POWV9.c
rm -rf build/
mkdir -p build/
cd build
cmake ../src
make -j$(nproc)
cp iccad19gr $PREFIX/bin/cugr
- name: cvc
repo: https://github.com/d-m-bailey/cvc
commit: 38c74b0857ecf8f05a1bfde81d197b5a3d33a531
build: |
autoreconf -i
autoconf
./configure --disable-nls --prefix=$PREFIX
make install
- name: drcu
repo: https://github.com/cuhk-eda/dr-cu
commit: 427b4a4f03bb98d8a78b1712fe9e52cfb83a8347
build: |
rm -rf build/
mkdir -p build/
cd build
cmake ../src
make -j$(nproc)
cp ispd19dr $PREFIX/bin/drcu
- name: magic
repo: https://github.com/rtimothyedwards/magic
commit: 958d6f16701c1ee25e27440381b5c2c37b5fee7c
build: |
./configure --prefix=$PREFIX
make -j$(nproc)
make install
- name: netgen
repo: https://github.com/rtimothyedwards/netgen
commit: 738c1f7b3705bca2f1cc66fbc1cfb20f12d49a06
build: |
./configure --prefix=$PREFIX
make -j$(nproc)
make install
- name: padring
repo: https://github.com/ax3ghazy/padring
commit: a88faf5a4faef75ff241276599fef81c3653cb70
build: |
bash ./bootstrap.sh
cd build
ninja
cp padring $PREFIX/bin
- name: qflow
repo: https://github.com/RTimothyEdwards/qflow
commit: a550469b63e910ede6e3022e2886bca96462c540
build: |
# Note we only grab the vlog2verilog tool.
./configure
cd src
make -j$(nproc) vlog2Verilog
cp vlog2Verilog $PREFIX/bin
- name: yosys
repo: https://github.com/YosysHQ/yosys
commit: d061b0e41a2023b5e72794563b94d6a9b5ab41a1
build: |
make PREFIX=$PREFIX config-gcc
make PREFIX=$PREFIX -j$(nproc)
make PREFIX=$PREFIX install
- name: openroad_app
repo: https://github.com/The-OpenROAD-Project/OpenROAD
commit: 4d4d7205fd0292dbf3fae55fad9109b3f0bd5786
build: mkdir -p ./build cd ./build cmake -DCMAKE_INSTALL_PREFIX=$PREFIX/bin .. make
-j$(nproc)
in_install: false
- name: open_pdks
repo: https://github.com/rtimothyedwards/open_pdks
commit: 1d93a6bd9d6e481acfdf88f26aa3bb0600303d98
build: ''
in_install: false
in_container: false
- name: sky130
repo: https://github.com/google/skywater-pdk
commit: 00bdbcf4a3aa922cc1f4a0d0cd8b80dbd73149d3
build: ''
in_install: false
in_container: false

50
dependencies/ubuntu-20.04/run_time.txt vendored Normal file
View File

@@ -0,0 +1,50 @@
https://www.klayout.org/downloads/Ubuntu-20/klayout_0.27.3-1_amd64.deb
xvfb
autoconf
autopoint
bison
bzip2
libcairo-dev
clang
csh
curl
flex
gawk
gcc
gdb
gettext
git
graphviz
help2man
libeigen3-dev
libsm-dev
libx11-dev
libffi-dev
libgomp1
libjpeg9-dev
libxml2-dev
libxslt-dev
libffi-dev
libspdlog-dev
make
ncurses-dev
ninja-build
patch
libpcre2-dev
python3
python3-pip
python3.6-dev
python3.6-tk
libreadline-dev
strace
swig
tcl-dev
tk-dev
tcllib
tclx8.4-dev
texinfo
neovim
wget
xdot
zlib1g

View File

@@ -4,7 +4,7 @@ DOCKERFILE_PATH ?= ./Dockerfile
IMAGE_NAME ?= efabless/openlane:current
#ROOT = sudo
TOOLS = klayout cugr drcu yosys antmicro_yosys magic openroad_app padring netgen vlogtoverilog openphysyn cvc
TOOLS = klayout cugr drcu yosys magic openroad_app padring netgen vlogtoverilog cvc
TOOL_BUILD_TARGETS = $(foreach tool,$(TOOLS),build-$(tool))
TOOL_EXPORT_TARGETS_PHONY = $(foreach tool,$(TOOLS),export-$(tool))
@@ -16,7 +16,7 @@ build-all: $(TOOL_BUILD_TARGETS) export-all
$(TOOL_BUILD_TARGETS): build-% : ./docker/%/Dockerfile
mkdir -p logs/docker
docker build $(DOCKER_BUILD_OPTS) -t $* docker/$* | tee logs/docker/$*.build.txt
docker build $(DOCKER_BUILD_OPTS) $(shell python3 ../dependencies/tool.py --docker-args $*) -t $* docker/$* | tee logs/docker/$*.build.txt
${MAKE} export-$*
# ==============================================================================

View File

@@ -39,7 +39,7 @@ make build-<tool>
The following are the available tools:
```bash
klayout cugr drcu yosys magic openroad_app padring netgen vlogtoverilog openphysyn cvc
klayout cugr drcu yosys magic openroad_app padring netgen vlogtoverilog cvc
```
### Rebuilding

View File

@@ -1,81 +0,0 @@
# Copyright 2020 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# syntax = docker/dockerfile:1.0-experimental
FROM centos:centos7 as build
RUN yum groupinstall -y "Development Tools"
RUN yum -y install centos-release-scl && \
yum -y install curl libffi-devel readline-devel tcl tcl-devel graphviz xdot
RUN yum -y install bison flex gawk git zlib-devel
# Install dev and runtime dependencies
RUN yum -y install devtoolset-8 devtoolset-8-libatomic-devel
ENV CC=/opt/rh/devtoolset-8/root/usr/bin/gcc \
CPP=/opt/rh/devtoolset-8/root/usr/bin/cpp \
CXX=/opt/rh/devtoolset-8/root/usr/bin/g++ \
PATH=/opt/rh/devtoolset-8/root/usr/bin:$PATH \
LD_LIBRARY_PATH=/opt/rh/devtoolset-8/root/usr/lib64:/opt/rh/devtoolset-8/root/usr/lib:/opt/rh/devtoolset-8/root/usr/lib64/dyninst:/opt/rh/devtoolset-8/root/usr/lib/dyninst:/opt/rh/devtoolset-8/root/usr/lib64:/opt/rh/devtoolset-8/root/usr/lib:$LD_LIBRARY_PATH
RUN yum install -y https://repo.ius.io/ius-release-el7.rpm
RUN yum install -y python36u python36u-pip
RUN alternatives --install /usr/bin/python3 python3 /usr/bin/python3.6 60
#ENV CC=/opt/rh/devtoolset-6/root/usr/bin/gcc \
#CPP=/opt/rh/devtoolset-6/root/usr/bin/cpp \
#CXX="/opt/rh/devtoolset-6/root/usr/bin/g++" \
#PATH=/opt/rh/devtoolset-6/root/usr/bin:$PATH \
#LD_LIBRARY_PATH=/opt/rh/devtoolset-6/root/usr/lib64:/opt/rh/devtoolset-6/root/usr/lib:/opt/rh/devtoolset-6/root/usr/lib64/dyninst:/opt/rh/devtoolset-6/root/usr/lib/dyninst:/opt/rh/devtoolset-6/root/usr/lib64:/opt/rh/devtoolset-6/root/usr/lib:$LD_LIBRARY_PATH
#RUN yum install -y clang
# https://github.com/YosysHQ/yosys/issues/332
RUN yum install -y wget autoconf && \
wget https://ftp.gnu.org/gnu/bison/bison-3.0.1.tar.gz && \
tar -xvzf bison-3.0.1.tar.gz && \
cd bison-3.0.1 && \
./configure && \
make -j$(nproc) && \
make install
# download public key for github.com
# RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
# git clone yosys
ARG ANTMICRO_YOSYS_REPO=https://github.com/antmicro/yosys
ARG ANTMICRO_YOSYS_COMMIT=fe58e937ef87fdb157dd89c365bb6a570fe616ea
RUN git clone ${ANTMICRO_YOSYS_REPO} yosys && \
cd yosys && \
git checkout ${ANTMICRO_YOSYS_COMMIT}
# build yosys
WORKDIR yosys
RUN make PREFIX=/build/antmicro config-gcc \
&& make PREFIX=/build/antmicro -j$(nproc) \
&& make PREFIX=/build/antmicro install
RUN mkdir -p /build/version
RUN date +"Build Timestamp: %Y-%m-%d_%H-%M-%S" > /build/version/yosys.version
RUN git rev-parse HEAD >> /build/version/yosys.version
RUN tar -czf /build.tar.gz /build

View File

@@ -1,89 +0,0 @@
# Copyright 2020 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# syntax = docker/dockerfile:1.0-experimental
FROM centos:centos7 AS build
# Install Development Environment
RUN yum groupinstall -y "Development Tools"
RUN yum install -y wget git
RUN yum -y install centos-release-scl && \
yum -y install devtoolset-8 \
devtoolset-8-libatomic-devel tcl-devel tcl tk libstdc++ tk-devel pcre-devel \
python36u python36u-libs python36u-devel python36u-pip && \
yum clean -y all && \
rm -rf /var/lib/apt/lists/*
ENV CC=/opt/rh/devtoolset-8/root/usr/bin/gcc \
CPP=/opt/rh/devtoolset-8/root/usr/bin/cpp \
CXX="/opt/rh/devtoolset-8/root/usr/bin/g++ -lrt" \
PATH=/opt/rh/devtoolset-8/root/usr/bin:$PATH \
LD_LIBRARY_PATH=/opt/rh/devtoolset-8/root/usr/lib64:/opt/rh/devtoolset-8/root/usr/lib:/opt/rh/devtoolset-8/root/usr/lib64/dyninst:/opt/rh/devtoolset-8/root/usr/lib/dyninst:/opt/rh/devtoolset-8/root/usr/lib64:/opt/rh/devtoolset-8/root/usr/lib:$LD_LIBRARY_PATH
# Install CMake
RUN wget https://cmake.org/files/v3.14/cmake-3.14.0-Linux-x86_64.sh && \
chmod +x cmake-3.14.0-Linux-x86_64.sh && \
./cmake-3.14.0-Linux-x86_64.sh --skip-license --prefix=/usr/local && rm -rf cmake-3.14.0-Linux-x86_64.sh \
&& yum clean -y all
# Install dev and runtime dependencies
RUN yum install -y tcl-devel tcl tk libstdc++ tk-devel pcre-devel
# Install epel repo
RUN wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm && \
yum install -y epel-release-latest-7.noarch.rpm && rm -rf epel-release-latest-7.noarch.rpm \
&& yum clean -y all
RUN yum install -y https://repo.ius.io/ius-release-el7.rpm
# Install SWIG
RUN yum remove -y swig \
&& wget https://github.com/swig/swig/archive/rel-4.0.1.tar.gz \
&& tar xfz rel-4.0.1.tar.gz \
&& rm -rf rel-4.0.1.tar.gz \
&& cd swig-rel-4.0.1 \
&& ./autogen.sh && ./configure --prefix=/usr && make -j $(nproc) && make install \
&& cd .. \
&& rm -rf swig-rel-4.0.1
# Installing boost for build dependency
RUN wget https://dl.bintray.com/boostorg/release/1.68.0/source/boost_1_68_0.tar.bz2 && \
tar -xf boost_1_68_0.tar.bz2 && \
cd boost_1_68_0 && \
./bootstrap.sh -with-libraries=program_options,log,filesystem && \
./b2 -j$(nproc) install
ARG OPENPHYSYN_REPO=https://github.com/scale-lab/OpenPhySyn
ARG OPENPHYSYN_COMMIT=6bb80c5f9312a302b7c29cf1a4ddb93ace47d122
RUN git clone --recursive ${OPENPHYSYN_REPO} && \
cd OpenPhySyn && \
git checkout ${OPENPHYSYN_COMMIT}
# Build
WORKDIR OpenPhySyn
RUN mkdir build && mkdir /build
RUN cd build && cmake .. -DCMAKE_BUILD_TYPE=release && make -j 4 && make install
RUN mkdir /build/bin && cp build/Psn /build/bin/
RUN mkdir -p /build/version
RUN date +"Build Timestamp: %Y-%m-%d_%H-%M-%S" > /build/version/openphysyn.version
RUN git rev-parse HEAD >> /build/version/openphysyn.version
RUN tar -czf /build.tar.gz /build

Binary file not shown.

View File

@@ -42,7 +42,7 @@
**Note**: You can use different directories for sky130-source and local-path. However, in the instructions we are using $PDK_ROOT to facilitate the installation process
**WARNING**: Please, don't move `sk130A` from the installed directory because the generated .mag files contain absolute paths. Moving it will result in producing an invalid GDS.
**WARNING**: Please, don't move `sky130A` from the installed directory because the generated .mag files contain absolute paths. Moving it will result in producing an invalid GDS.
- To set the STD_CELL_LIBRARY (the default value is set to sky130_fd_sc_hd)
- Open [configuration/general.tcl](../configuration/general.tcl)

View File

@@ -183,7 +183,6 @@ Most of the following commands' implementation exists in this [file][7]
| `add_macro_placement <macro_name> <x_coordinate> <y_coordinate> [<orientation>]` | | Writes a configuration file to be processed by `manual_macro_placement` by setting the initial placement of the macro `<macro_name>` to location (`<x_coordinate>`,`<y_coordinate>`) on the chip with the option of specifying the `<orientation>` as well. The line written will be appened to this configuration file `/run_path/tmp/macro_placements.cfg`. |
| `manual_macro_placement [f]` | | Uses the configuration file generated by `add_macro_placement` (`/run_path/tmp/macro_placements.cfg`) to manually initialize the placement of the macros to the locations determined in the file. It works on the currently processed design and it overwrites the `CURRENT_DEF`. if `f` is passed as the first argument, the placement will be fixed and final, and the placement tools will not be allowed to change it.|
| `basic_macro_placement` | | Runs basic macro placement on the chip level using the openroad app, and it writes into `::env(CURRENT_DEF).macro_placement.def`. |
| `run_openPhySyn` | | Runs OpenPhySyn timing optimizations: capacitance_violations, transition_violations, fanout_violations, and negative_slack_violations. |
| `run_resizer_design` | | Runs resizer design optimizations to insert buffers on nets to repair max slew, max capacitance, max fanout violations, and on long wires to reduce RC delay in the wire. It also resizes cells. |
| `run_resizer_timing` | | Runs resizer timing optimizations which repairs setup and hold violations. |
| `run_placement`| | Runs global placement (`global_placement_or` or `random_global_placement` based on the value of `PL_RANDOM_GLB_PLACEMENT`), then applies the optional optimizations `repair_wire_length` followed by `run_openPhySyn` if enabled, then runs the detailed placement (`detailed_placement_or`). |

View File

@@ -118,14 +118,6 @@ The only optimization we use from resizer is the wire length optimization which
However, you can enable that by setting `PL_RESIZER_OVERBUFFER` to `1` and then determine the maximum wire length by setting this value `MAX_WIRE_LENGTH`.
#### OpenPhySyn optimizations:
The timing OpenPhySyn optimizations are enabled by default and you can control that using this flag `PL_OPENPHYSYN_OPTIMIZATIONS`.
You can also control resizing and pin swapping using these flags: `PSN_ENABLE_RESIZING` and `PSN_ENABLE_PIN_SWAP`.
You can read more about those configurations [here][0].
### Detailed Placement:
The only value to consider here is the `CELL_PAD` which is usually selected for each (PDK,STD_CELL_LIBRARY) and should mostly be left as is. However, typically for the skywater libraries the value should be 4~6.

36
get_tag.py Normal file
View File

@@ -0,0 +1,36 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright 2020 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
import subprocess
tag = None
try:
tag = subprocess.check_output(["git", "describe", "--tags", "--abbrev=0"]).decode("utf8").strip()
except Exception as e:
pass
if tag is None:
try:
tag = open("./resolved_version").read()
except:
print("Please input the version of OpenLane you'd like to pull: ", file=sys.stderr)
tag = input()
with open("./resolved_version", "w") as f:
f.write(tag)
print(tag, end="")

View File

@@ -29,7 +29,7 @@ import subprocess
from os.path import join, abspath, dirname, exists
from typing import Tuple, Union, List
from dependencies.tool_metadata import Tool
from dependencies.tool import Tool
openlane_dir = dirname(abspath(__file__))
is_root = os.geteuid() == 0
@@ -112,34 +112,8 @@ def download(url, ext):
target.close()
return path
def compile_tool_data():
dockerfiles = glob.glob(join(openlane_dir, "docker_build", "**", "Dockerfile"), recursive=True)
docker_lines = "\n".join([open(x).read() for x in dockerfiles]).split("\n")
for line in docker_lines:
repo_rx = r"ARG\s+(\w+)_REPO\s*=\s*([^\s]+)"
commit_rx = r"ARG\s+(\w+)_COMMIT\s*=\s*([^\s]+)"
repo_match = re.match(repo_rx, line)
commit_match = re.match(commit_rx, line)
if repo_match:
name = repo_match[1].lower(); repo = repo_match[2]
tool = Tool.map.get(name)
if tool is None:
print(f"Tool {name} not found, skipping...")
continue
tool.repo = repo
if commit_match:
name = commit_match[1].lower(); commit = commit_match[2]
tool = Tool.map.get(name)
if tool is None:
print(f"Tool {name} not found, skipping...")
continue
tool.commit = commit
def run_installer():
tools = Tool.from_metadata_yaml(open("./dependencies/tool_metadata.yml").read())
if input_options("RISK_ACKNOWLEDGED", "I affirm that I have read LOCAL_INSTALL.md and agree to the outlined risks.", ["n", "y"]) != "y":
return
@@ -160,7 +134,7 @@ OpenLane Local Installer ALPHA
This version of OpenLane was tested with this version of OpenRoad:
{Tool.map["openroad_app"].version_string}
{tools["openroad_app"].version_string}
""")
os_pick = input_options("OS", "Which UNIX/Unix-like OS are you using?", ["ubuntu-20.04", "centos7", "other"])
@@ -168,11 +142,10 @@ OpenLane Local Installer ALPHA
gcc_bin = os.getenv("CC") or "gcc"
gxx_bin = os.getenv("CXX") or "g++"
try:
if not os_pick == "centos7":
if not os_pick == "centos7": # The reason we ignore centos7 is that we're going to just use devtoolset-8 anyway.
gcc_ver_output = subprocess.run([gcc_bin, "--version"], stdout=subprocess.PIPE)
gx_ver_output = subprocess.run([gxx_bin, "--version"], stdout=subprocess.PIPE)
if "clang" in gcc_ver_output.stdout.decode("utf-8") + gx_ver_output.stdout.decode("utf-8"):
# The reason we ignore centos7 is that we're going to just use devtoolset-8 anyway.
print(f"""
We've detected that you're using Clang as your default C or C++ compiler.
Unfortunately, Clang is not compatible with some of the tools being
@@ -203,13 +176,19 @@ OpenLane Local Installer ALPHA
pip_action = input_options("PIP_DEPS", "Install PIP dependencies?", ["no", "system", "user"])
if pip_action != "no":
python_directory = join(openlane_dir, "dependencies", "python")
requirements_files = [os.path.join(python_directory, file) for file in os.listdir(python_directory)]
final_list = []
for file in requirements_files:
final_list.append("-r")
final_list.append(file)
sh(
"python3",
"-m",
"pip",
"install",
"-r",
join(openlane_dir, "dependencies", "requirements.txt"),
*final_list,
root=pip_action == "system"
)
@@ -217,12 +196,18 @@ OpenLane Local Installer ALPHA
if os_pick != "other":
install_packages = input_options("INSTALL_PACKAGES", "Do you want to install packages for development?", ["no", "yes"])
if install_packages != "no":
def cat_all(dir):
result = ""
for file in os.listdir(dir):
result += open(join(dir, file)).read()
result += "\n"
return result
if os_pick == "centos7":
yum_packages = open(join(openlane_dir, 'dependencies', 'centos7.txt')).read().strip().split("\n")
yum_packages = cat_all(join(openlane_dir, 'dependencies', 'centos7')).strip().split("\n")
sh("yum", "install", "-y", *yum_packages)
if os_pick == "ubuntu-20.04":
raw = open(join(openlane_dir, 'dependencies', 'ubuntu20.04.txt')).read().strip().split("\n")
raw = cat_all(join(openlane_dir, 'dependencies', 'ubuntu-20.04')).strip().split("\n")
apt_packages = []
apt_debs = []
@@ -274,8 +259,8 @@ OpenLane Local Installer ALPHA
for folder in ["repos", "versions"]:
sh("mkdir", "-p", folder)
for tool in Tool.map.values():
if tool.skip:
for tool in tools.values():
if not tool.in_install:
continue
installed_version = ""
version_path = f"versions/{tool.name}"
@@ -301,7 +286,7 @@ OpenLane Local Installer ALPHA
sh("git", "submodule", "update", "--init")
sh("git", "checkout", tool.commit)
subprocess.run([
"bash", "-c", tool.install_command
"bash", "-c", tool.build_script
], env=run_env, check=True)
with open(version_path, "w") as f:
@@ -311,7 +296,6 @@ OpenLane Local Installer ALPHA
f.write("""#!/bin/bash
OL_DIR="$(dirname "$(test -L "$0" && readlink "$0" || echo "$0")")"
export NO_DIAMOND_SEARCH_HEIGHT=1
export PATH=$OL_DIR/bin:$PATH
FLOW_TCL=${FLOW_TCL:-$OL_DIR/flow.tcl}
@@ -337,9 +321,9 @@ def main():
help="List the tools and exit."
)
args = parser.parse_args()
compile_tool_data()
if args.list_tools:
for tool in Tool.map.values():
tools = Tool.from_metadata_yaml(open("./dependencies/tool_metadata.yml").read())
for tool in tools.values():
print(f"{tool.name}: {tool.version_string}")
else:
run_installer()

View File

@@ -33,7 +33,7 @@
| `vias` | The number of vias in the final design. Extracted from tritonRoute logs. |
| `wns` | Worst Negative Slack. Reported after Synthesis. Extracted from OpenSTA. |
| `pl_wns` | Worst Negative Slack. Reported after global placement and before optimizations using estimate parasitics. Extracted from RePlAce/OpenSTA. If the report wasn't found, the value from the previous STA report is used. |
| `opt_wns` | Worst Negative Slack. Reported after OpenPhySyn optimizations. Extracted from OpenSTA. If the report wasn't found, the value from the previous STA report is used. |
| `opt_wns` | Worst Negative Slack. Extracted from OpenSTA. If the report wasn't found, the value from the previous STA report is used. |
| `fastroute_tns` | Worst Negative Slack. Reported after global routing using estimate parasitics. Extracted from FastRoute/OpenSTA. If the report wasn't found, the value from the previous STA report is used. |
| `spef_wns` | Worst Negative Slack. Reported after routing and spef extraction. Extracted from OpenSTA. If the report wasn't found, the value from the previous STA report is used. |
| `tns` | Total Negative Slack. Reported after Synthesis. Extracted from OpenSTA. |

View File

@@ -1,75 +0,0 @@
#Psn ; # or ./build/Psn if not installed in the global path
#BSD 3-Clause License
#Copyright (c) 2019, SCALE Lab, Brown University
#All rights reserved.
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
#* Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#* Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#* Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
#IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
#FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
#DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
#SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
#CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
#OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
#OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import_lib $::env(LIB_OPT)
import_lef $::env(MERGED_LEF_UNPADDED)
import_def $::env(CURRENT_DEF)
read_sdc $::env(BASE_SDC_FILE)
set_wire_rc $::env(WIRE_RC_LAYER)
puts "=============== Initial Reports ============="
report_checks
report_check_types -max_slew -max_capacitance -violators
puts "Capacitance violations: [llength [capacitance_violations]]"
puts "Transition violations: [llength [transition_violations]]"
report_wns
report_tns
puts "Initial area: [expr round([design_area] * 10E12) ] um2"
puts "OpenPhySyn timing repair:"
set opts ""
if { $::env(PSN_ENABLE_RESIZING) == 0 } {
set opts "$opts -resize_disabled"
}
if { $::env(PSN_ENABLE_PIN_SWAP) == 0 } {
set opts "$opts -pin_swap_disabled"
}
repair_timing -capacitance_violations -transition_violations -fanout_violations -negative_slack_violations $opts
puts "=============== Final Reports ============="
report_checks
report_checks > $::env(openphysyn_report_file_tag)_allchecks.rpt
report_check_types -max_slew -max_capacitance -violators
report_check_types -max_slew -max_capacitance -violators > $::env(openphysyn_report_file_tag)_violators.rpt
puts "Capacitance violations: [llength [capacitance_violations]]"
puts "Transition violations: [llength [transition_violations]]"
report_wns
report_wns > $::env(openphysyn_report_file_tag)_wns.rpt
report_tns
report_tns > $::env(openphysyn_report_file_tag)_tns.rpt
puts "Final area: [expr round([design_area] * 10E12) ] um2"
puts "Export optimized design"
export_def $::env(SAVE_DEF)
exit 0

View File

@@ -26,18 +26,12 @@ routed_runtime_rpt=${path}/reports/routed_runtime.txt
total_runtime_rpt=${path}/reports/total_runtime.txt
wns_rpt=$(python3 $3/get_file_name.py -p ${path}/reports/synthesis/ -o opensta_wns.rpt 2>&1)
pl_wns_rpt=$(python3 $3/get_file_name.py -p ${path}/reports/placement/ -o replace.log 2>&1)
opt_wns_rpt=$(python3 $3/get_file_name.py -p ${path}/reports/synthesis/ -o opensta_post_openphysyn_wns.rpt 2>&1)
if ! [ -f $opt_wns_rpt ]; then
opt_wns_rpt=$(python3 $3/get_file_name.py -p ${path}/reports/synthesis/ -o opensta_post_resizer_timing_wns.rpt 2>&1)
fi
opt_wns_rpt=$(python3 $3/get_file_name.py -p ${path}/reports/synthesis/ -o opensta_post_resizer_timing_wns.rpt 2>&1)
fr_wns_rpt=$(python3 $3/get_file_name.py -p ${path}/logs/routing/ -o fastroute.log 2>&1)
spef_wns_rpt=$(python3 $3/get_file_name.py -p ${path}/reports/synthesis/ -o opensta_spef_wns.rpt 2>&1)
tns_rpt=$(python3 $3/get_file_name.py -p ${path}/reports/synthesis/ -o opensta_tns.rpt 2>&1)
pl_tns_rpt=$(python3 $3/get_file_name.py -p ${path}/reports/placement/ -o replace.log 2>&1)
opt_tns_rpt=$(python3 $3/get_file_name.py -p ${path}/reports/synthesis/ -o opensta_post_openphysyn_tns.rpt 2>&1)
if ! [ -f $opt_tns_rpt ]; then
opt_tns_rpt=$(python3 $3/get_file_name.py -p ${path}/reports/synthesis/ -o opensta_post_resizer_timing_tns.rpt 2>&1)
fi
opt_tns_rpt=$(python3 $3/get_file_name.py -p ${path}/reports/synthesis/ -o opensta_post_resizer_timing_tns.rpt 2>&1)
fr_tns_rpt=$(python3 $3/get_file_name.py -p ${path}/reports/routing/ -o fastroute.log 2>&1)
spef_tns_rpt=$(python3 $3/get_file_name.py -p ${path}/reports/synthesis/ -o opensta_spef_tns.rpt 2>&1)
HPWL_rpt=$(python3 $3/get_file_name.py -p ${path}/logs/placement/ -o replace.log 2>&1)
@@ -180,7 +174,7 @@ if ! [[ $wns ]]; then wns=-1; fi
pl_wns=$(grep "wns" $pl_wns_rpt -s | tail -1 |sed -r 's/wns //')
if ! [[ $pl_wns ]]; then pl_wns=$wns; fi
#Extracting Info from OpenPhySyn
#Extracting Info from OpenSTA
opt_wns=$(grep "wns" $opt_wns_rpt -s | tail -1 |sed -r 's/wns //')
if ! [[ $opt_wns ]]; then opt_wns=$pl_wns; fi
@@ -200,7 +194,7 @@ if ! [[ $tns ]]; then tns=-1; fi
pl_tns=$(grep "tns" $pl_tns_rpt -s | tail -1 |sed -r 's/tns //')
if ! [[ $pl_tns ]]; then pl_tns=$tns; fi
#Extracting Info from OpenPhySyn
#Extracting Info from OpenSTA
opt_tns=$(grep "tns" $opt_tns_rpt -s | tail -1 |sed -r 's/tns //')
if ! [[ $opt_tns ]]; then opt_tns=$pl_tns; fi

View File

@@ -442,7 +442,6 @@ proc prep {args} {
{pdn floorplan/pdn}
{tapcell floorplan/tapcell}
{replaceio placement/replace}
{openphysyn placement/openphysyn}
{resizer placement/resizer}
{opendp placement/opendp}
{addspacers routing/addspacers}

View File

@@ -28,7 +28,6 @@ detailed_placement_or
basic_macro_placement
run_placement
repair_wire_length
run_openPhySyn
init_design
global_routing_or
global_routing

View File

@@ -151,52 +151,11 @@ proc run_placement {args} {
set ::env(PL_TARGET_DENSITY) $old_pl_target_density
}
run_openPhySyn
run_resizer_design
detailed_placement_or
scrot_klayout -layout $::env(CURRENT_DEF)
}
proc run_openPhySyn {args} {
if { $::env(PL_OPENPHYSYN_OPTIMIZATIONS) == 1} {
puts_info "Running OpenPhySyn Timing Optimizations..."
TIMER::timer_start
if { ! [info exists ::env(LIB_OPT)]} {
set ::env(LIB_OPT) $::env(TMP_DIR)/opt.lib
trim_lib -input $::env(LIB_SLOWEST) -output $::env(LIB_OPT) -drc_exclude_only
}
set report_tag_saver $::env(openphysyn_report_file_tag)
set ::env(openphysyn_report_file_tag) [index_file $::env(openphysyn_report_file_tag)]
set ::env(SAVE_DEF) [index_file $::env(openphysyn_tmp_file_tag).def 0]
try_catch Psn $::env(SCRIPTS_DIR)/openPhySyn.tcl |& tee $::env(TERMINAL_OUTPUT) [index_file $::env(openphysyn_log_file_tag).log 0]
set_def $::env(SAVE_DEF)
set ::env(openphysyn_report_file_tag) $report_tag_saver
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" >> [index_file $::env(openphysyn_log_file_tag)_runtime.txt 0]
write_verilog $::env(yosys_result_file_tag)_optimized.v
set_netlist $::env(yosys_result_file_tag)_optimized.v
if { $::env(LEC_ENABLE) && [file exists $::env(PREV_NETLIST)] } {
logic_equiv_check -rhs $::env(PREV_NETLIST) -lhs $::env(CURRENT_NETLIST)
}
set report_tag_holder $::env(opensta_report_file_tag)
set log_tag_holder $::env(opensta_log_file_tag)
set ::env(opensta_report_file_tag) $::env(opensta_report_file_tag)_post_openphysyn
set ::env(opensta_log_file_tag) $::env(opensta_log_file_tag)_post_openphysyn
run_sta
set ::env(opensta_report_file_tag) $report_tag_holder
set ::env(opensta_log_file_tag) $log_tag_holder
} else {
puts_info "Skipping OpenPhySyn Timing Optimizations."
}
}
proc run_resizer_timing {args} {
if { $::env(PL_RESIZER_TIMING_OPTIMIZATIONS) == 1} {
puts_info "Running Resizer Timing Optimizations..."