More Usability Tweaks (#984)

+ `-verbose` flag added with multiple levels, replacing `-disable_output` (which is now the default behavior)
+ New command `puts_verbose` added, to be used for extra pieces of information
+ ./flow.tcl header now includes version, copyright and licensing information
+ Added `-last_run` flag allowing you to quickly resume the last run (useful with -interactive)
+ Added `open_in_klayout` command that lets you open the CURRENT_DEF in Klayout
~ `env.py issue-survey` now detects whether it's running inside the container and warns accordingly
~ RUN_KLAYOUT, RUN_KLAYOUT_DRC, RUN_MAGIC_DRC, RUN_LVS now only control noninteractive flows
~ Full git hash added to containers
~ Various Documentation Updates
~ Changed verbosity of various output messages
- Removed `-disable_output` (now the default behavior)
- Removed OpenLane ASCII art
- Removed various "chatty" messages, including things succeeding (shut up unless something fails)
This commit is contained in:
Donn
2022-03-14 12:09:15 +02:00
committed by GitHub
parent 5f20beb792
commit 00da77e58c
28 changed files with 738 additions and 535 deletions

View File

@@ -4,4 +4,5 @@ exclude =
.git,
__pycache__,
scripts/klayout,
docker/tar
docker/tar,
install/

View File

@@ -1,19 +1,31 @@
# How to Contribute
We'd love to accept your patches and contributions to this project. There are
just a few small guidelines you need to follow.
## Submission and Testing Process
# Branching
For various reasons, it's recommended to call working branches, even in your forks, something else other than `master` or `main`, as those two branch names do have some special behavior associated with them.
- Submit a Pull Request to the [master](https://github.com/The-OpenROAD-Project/openlane/tree/master) branch only. Check [Code Reviews](#code_reviews) for more details.
- Our CI that would test your PR once submitted, yet it would be nice for you to run a couple of tests from your end to shorten the cycle of reviews. For that purpose, you can use:
- `make fastest_test_set`: to run the same test set that the basic CI uses, which will be used to evaluate your Pull Request.
- [This](./regression_results/README.md) for custom test sets. (check the `-b` flag).
- `make test`: tests the flow against one design `$TEST_DESIGN`. The default is `spm`.
# Testing and Code Standards
Before you submit your changes, it's prudent to perform some kind of smoke test. `make test` tests a simple spm design to ensure nothing has gone horribly wrong.
## Code reviews
You will also need to ensure that your Python code passes linting with two tools: `black` and `flake8`. The commands are simply `black .` and `flake8 .`. Please fix all warnings.
All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
information on using pull requests.
Try to write all major code in Python. Writing some Tcl is usually a necessity because this project's backbone is unfortunately written in Tcl, but just keep the Tcl to as close to a Python shim as possible.
Please do not write new shell scripts.
# Submissions
Make your changes and then submit them as a pull requests to the `master` branch.
Consult [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more information on using pull requests.
## The Approval Process
For a PR to be merged, there are two requirements:
- There are two automated checks, one for linting and the other for functionality. Both must pass.
- An OpenLane team member must inspect and approve the PR.
# Licensing and Copyright
Please add you (or your employer's) copyright headers to any files to which you have made major edits.
Please note all code contributions must have the same license as OpenLane, i.e., the Apache License, version 2.0.

View File

@@ -133,7 +133,7 @@ issue_regression_all:
.PHONY: test
test:
cd $(OPENLANE_DIR) && \
$(ENV_COMMAND) sh -c "./flow.tcl -design $(TEST_DESIGN) -tag openlane_test -disable_output -overwrite"
$(ENV_COMMAND) sh -c "./flow.tcl -design $(TEST_DESIGN) -tag openlane_test -overwrite"
@[ -f $(OPENLANE_DIR)/designs/$(TEST_DESIGN)/runs/openlane_test/results/finishing/$(TEST_DESIGN).gds ] && \
echo "Basic test passed" || \
echo "Basic test failed"

View File

@@ -33,15 +33,17 @@ This documentation is also available at [ReadTheDocs](https://openlane.readthedo
# Prerequisites
At a minimum:
- Docker 19.03.12+
- GNU Make
- Python 3.6+ with PIP
- Click, Pyyaml: `python3 -m pip install pyyaml click>=7`
- Python 3.6 with PIP
- Click 7.0+, Pyyaml: `python3 -m pip install pyyaml click>=7`
For building Sky130 PDK you also need:
- Git 2.35+: `git --version`
To build the Sky130 PDK you also need:
- Git 2.35+
## Containerless Install
## Using the Docker Image
- Docker 19.03.12+
## Containerless/Local Installations
Please see [here](./docs/source/local_installs.md).
# Setting Up OpenLane

View File

@@ -88,7 +88,8 @@ FORCE:
openlane: merge
merge: run_base_image ./tar/build ./tar/openlane ../dependencies/tool_metadata.yml
cat ../dependencies/tool_metadata.yml > ./tar/tool_metadata.yml
printf "$(shell git rev-parse --short=7 HEAD)" > ./tar/git_version
printf "$(shell git rev-parse HEAD)" > ./tar/git_version
printf "$(shell git rev-parse --short=7 HEAD)" > ./tar/git_version_short
mkdir -p logs/tar
$(BUILD_COMMAND)\
--build-arg CACHE_INVALIDATOR=$(shell date +%s)\

View File

@@ -39,6 +39,7 @@ ADD ./tool_metadata.yml /tool_metadata.yml
## Copy Version
ADD ./git_version /git_version
ADD ./git_version_short /git_version_short
## Artifacts
COPY ./build /build

View File

@@ -1,4 +1,5 @@
/*.tar.gz
/*.yml
/*.txt
/git_version
/git_version
/git_version_short

View File

@@ -2,6 +2,6 @@
# Source global definitions
alias ll='ls -lAFh';
export OL_GIT_VERSION=$(cat /git_version);
export OL_GIT_VERSION=$(cat /git_version_short);
export PS1="\[\033[1;31m\]OpenLane Container ($OL_GIT_VERSION)\[\033[0m\]:\[\033[4;32m\]\w\[\033[0m\]$ ";

View File

@@ -2,5 +2,6 @@
/*.yml
/*.txt
/git_version
/git_version_short
/build
/openlane

View File

@@ -39,7 +39,8 @@ Most of the following commands' implementation exists in this [file][0]
| | `[-src <verilog_source>]` | Sets the verilog source code file(s) in case of using `-init_design_config`. The default is that the source code files are under <code>design_path/src/</code>, where the design path is the one passed to <code>-design</code>. <br> Optional flag. |
| | `[-config_tag <config_tag>]` | Specifies the design's configuration file for running the flow. <br> For example, to run the flow using <code>designs/spm/config2.tcl</code> <br> Use run <code>./flow.tcl -design spm -config_tag config2.tcl</code> <br> By default <code>config.tcl</code> is used. <br> Optional flag. |
| | `[-config_file <config_file>]` | Specifies the design's configuration file for running the flow. <br> For example, to run the flow using <code>/spm/config2.tcl</code> <br> Use run <code>./flow.tcl -design /spm -config_file /spm/config2.tcl</code> <br> By default <code>config.tcl</code> is used. <br> Optional flag. |
| | `[-disable_output]` | Disables outputing to the terminal. <br> Optional flag.|
| | `[-verbose <level>]` | Sets a verbose output level. 0 disables verbose information and tool outputs. 1 enables verbose information but disables tool outputs. 2 and greater outputs everything. More verbose levels may be added over time, so if you want absolutely all output, set it to something like 99.|
| | `[-disable_output]` | **Removed: Default Behavior** Disables outputing to the terminal. <br> Optional flag.|
| `padframe_gen` | | Generates the padframe for a design based on the files and configurations under `padframe_folder`. Also, it generates a padframe.cfg if it's not present. The padframe.cfg is a file that describes the order of the pads and their relative location on the chip.|
| | `-folder <padframe_folder>` | specifies the `<padframe_folder>` for the padframe generator. The folder should contain the following: `./mag/<mag files>`, `./verilog/<verilog files>`, and optionally `./mag/padframe.cfg`|
| `save_views` | | Saves the views of a given `run_tag` into the specifies `path`(s).|
@@ -281,6 +282,9 @@ Most of the following commands' implementation exists in this [file][17]
| | `[-layout2 <gds_file>]` | The input GDS file, the default is the klayout generated GDS-II under `<run_path>/results/klayout/<design_name>.gds`. |
| | `[-output_gds <gds_file>]` | The output GDS file with the xor result, the default under `<run_path>/results/klayout/<design_name>.xor.gds`. |
| | `[-output_xml <xml_file>]` | The output XML file with the xor result, the default under `<run_path>/results/klayout/<design_name>.xor.xml`. |
| `open_in_klayout` | | Opens a design in the Klayout GUI with MERGED_LEF for the cell/macro definitions. Useful as it works around Klayout's LEF import peculiarities. |
| | `[-layout <def_file>]` | The input DEF file, the default is `::env(CURRENT_DEF)`. |
## LVS Commands
Most of the following commands' implementation exists in this [file][5]

View File

@@ -10,7 +10,7 @@ When working with a proprietary PDK, also inspect the folder and ensure no propr
If you're using OpenLane 2021.12.17_05.07.41 or later, chances are, `or_issue.py` was automatically run for you if OpenROAD failed. You'll find a message in the log that says something along the lines of: `Reproducible packaged: Please tarball and upload <PATH> if you're going to submit an issue.` The path will be under the current run_path, i.e., ./designs/<design>/runs/<run_tag>/openroad_issue_reproducible. You can then tarball/zip and upload that file.
## Running or_issue.py manually
You'll have to extract three key elements from the logs:
You'll have to extract three key elements from the **verbose** logs (i.e. ./flow.tcl must be run with `-verbose`):
* The Script Where The Failure Occurred -> script
* The Final Layout Before The Failure Occurred -> input
* The Run Path -> run_path

38
env.py
View File

@@ -129,20 +129,32 @@ def issue_survey():
"""
% (os_info.container_info.engine, container_version, container_message)
)
elif os.path.exists(
"/git_version"
): # i.e. if running inside the OpenLane container
print("Alert: Running in container.", file=alerts)
final_report = (
textwrap.dedent(
"""\
WARNING: issue-survey appears to be running inside the OpenLane
container.
This makes it difficult to rule out issues with your
environment.
Unless instructed specifically to do so, please run this command
outside the OpenLane container.
---\n
"""
)
+ final_report
)
else:
try:
subprocess.check_output(
["systemd-detect-virt", "-c"]
) # Check if running inside container
if not os.path.exists("/openlane"):
raise Exception()
alert = "Alert: Running in container."
final_report += "%s\n" % alert
print(alert, file=alerts)
except Exception:
alert = "Critical Alert: No Docker or Docker-compatible container engine was found: {e}."
final_report += "%s\n" % alert
print(alert, file=alerts)
alert = (
"Critical Alert: No Docker or Docker-compatible container engine was found."
)
final_report += "%s\n" % alert
print(alert, file=alerts)
if python_ok:
from dependencies.get_tag import get_tag

View File

@@ -89,8 +89,12 @@ proc run_drc_step {{ drc_enabled 1 }} {
set ::env(CURRENT_DEF) $::env(DRC_CURRENT_DEF)
}
if { $drc_enabled } {
run_magic_drc
run_klayout_drc
if { $::env(RUN_MAGIC_DRC) } {
run_magic_drc
}
if {$::env(RUN_KLAYOUT_DRC)} {
run_klayout_drc
}
}
}
@@ -112,6 +116,15 @@ proc run_eco_step {args} {
}
}
proc run_klayout_step {args} {
if {$::env(RUN_KLAYOUT)} {
run_klayout
}
if {$::env(RUN_KLAYOUT_XOR)} {
run_klayout_gds_xor
}
}
proc save_final_views {args} {
set options {
{-save_path optional}
@@ -177,8 +190,8 @@ proc run_non_interactive_mode {args} {
# signal trap SIGINT save_state;
if { [info exists flags_map(-gui)] } {
or_gui
return
or_gui
return
}
if { [info exists arg_values(-override_env)] } {
set env_overrides [split $arg_values(-override_env) ',']
@@ -204,8 +217,7 @@ proc run_non_interactive_mode {args} {
"eco" {run_eco_step ""} \
"diode_insertion" {run_diode_insertion_2_5_step ""} \
"gds_magic" {run_magic ""} \
"gds_drc_klayout" {run_klayout ""} \
"gds_xor_klayout" {run_klayout_gds_xor ""} \
"gds_klayout" {run_klayout_step ""} \
"lvs" "run_lvs_step $LVS_ENABLED" \
"drc" "run_drc_step $DRC_ENABLED" \
"antenna_check" "run_antenna_check_step $ANTENNACHECK_ENABLED" \
@@ -388,30 +400,20 @@ set flags {-interactive -it -drc -lvs -synth_explore -run_hooks}
parse_key_args "flow.tcl" argv arg_values $options flags_map $flags -no_consume
puts_info {
___ ____ ___ ____ _ ____ ____ ___
/ \ | \ / _]| \ | | / || \ / _]
| | | o ) [_ | _ || | | o || _ | / [_
| O | | _/ _]| | || |___ | || | || _]
| | | | | [_ | | || || _ || | || [_
\___/ |__| |_____||__|__||_____||__|__||__|__||_____|
}
if {[catch {exec cat $::env(OPENLANE_ROOT)/installed_version} ::env(OPENLANE_VERSION)]} {
if {[catch {exec git --git-dir $::env(OPENLANE_ROOT)/.git describe --tags} ::env(OPENLANE_VERSION)]} {
# if no tags yet
if {[catch {exec git --git-dir $::env(OPENLANE_ROOT)/.git log --pretty=format:'%h' -n 1} ::env(OPENLANE_VERSION)]} {
if {[catch {exec cat $::env(OPENLANE_ROOT)/install/installed_version} ::env(OPENLANE_VERSION)]} {
if {[catch {exec git --git-dir $::env(OPENLANE_ROOT)/.git rev-parse HEAD} ::env(OPENLANE_VERSION)]} {
if {[catch {exec cat /git_version} ::env(OPENLANE_VERSION)]} {
set ::env(OPENLANE_VERSION) "N/A"
}
}
}
puts_info "Version: $::env(OPENLANE_VERSION)"
puts "OpenLane $::env(OPENLANE_VERSION)"
puts "All rights reserved. (c) 2020-2022 Efabless Corporation and contributors."
puts "Available under the Apache License, version 2.0. See the LICENSE file for more details."
puts ""
if { [info exists flags_map(-interactive)] || [info exists flags_map(-it)] } {
puts_info "Running interactively"
puts_info "Note, that post_run_hooks.tcl will not be sourced automatically"
if { [info exists arg_values(-file)] } {
run_file [file normalize $arg_values(-file)] {*}$argv
} else {
@@ -425,7 +427,5 @@ if { [info exists flags_map(-interactive)] || [info exists flags_map(-it)] } {
prep {*}$argv
run_synth_exploration
} else {
puts_info "Running non-interactively"
run_non_interactive_mode {*}$argv
}

View File

@@ -1,5 +1,4 @@
# Variables information
# Datapoint Definitions
***NOTE:** The value `-1`, if not meaningful, indicates that the report/log from which the information is extracted wasn't found (the stage responsible for it was skipped or failed).
## Default Printed Information Variables

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Copyright 2020 Efabless Corporation
# Copyright 2020-2022 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -249,7 +249,7 @@ def cli(
"-overwrite",
"-no_save",
"-run_hooks",
] + ([] if show_log_output else ["-disable_output"])
] + (["-verbose", "99"] if show_log_output else [])
skip_rm_from_rems = False
try:
if show_log_output:

View File

@@ -0,0 +1,66 @@
# Copyright 2020-2022 Efabless Corporation
# Copyright 2021 The American University in Cairo and the Cloud V Project
#
# 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 pya
app = pya.Application.instance()
try:
win = app.main_window()
layout = os.getenv("LAYOUT")
if layout is None:
raise Exception("LAYOUT environment variable is not set.")
pdk_root = os.getenv("PDK_ROOT")
if pdk_root is None:
raise Exception("PDK_ROOT environment variable is not set.")
pdk_name = os.getenv("PDK")
if pdk_name is None:
raise Exception("PDK environment variable is not set.")
# Relative to the layout path, ':' delimited. If not provided, all LEFs
# in the same folder as the layout will be loaded.
explicitly_listed_lefs_raw = os.getenv("EXPLICITLY_LISTED_LEFS")
use_explicitly_listed_lefs = explicitly_listed_lefs_raw is not None
tech_file_path = os.path.join(
pdk_root, pdk_name, "libs.tech", "klayout", f"{pdk_name}.lyt"
)
tech = pya.Technology()
tech.load(tech_file_path)
layout_options = tech.load_layout_options
layout_options.keep_other_cells = True
layout_options = tech.load_layout_options
layout_options.lefdef_config.macro_resolution_mode = 1
if use_explicitly_listed_lefs:
explicitly_listed_lefs = explicitly_listed_lefs_raw.split(":")
layout_options.lefdef_config.read_lef_with_def = False
layout_options.lefdef_config.lef_files = explicitly_listed_lefs
cell_view = win.load_layout(layout, layout_options, 0)
except Exception as e:
print(e, file=sys.stderr)
app.exit(-1)

View File

@@ -0,0 +1,61 @@
#!/usr/bin/env python3
# Copyright 2020-2022 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 click
import subprocess
@click.command("open_design")
@click.option(
"-l",
"--input-lef",
default=os.getenv("MERGED_LEF"),
help="Input merged technology/cells LEF file",
)
@click.option(
"-P",
"--pdk-root",
default=os.getenv("PDK_ROOT"),
required=not os.getenv("PDK_ROOT"),
help="PDK Root",
)
@click.option("-p", "--pdk", default="sky130A", help="Name of the PDK")
@click.argument("input_def")
def open_design(input_lef, pdk_root, pdk, input_def):
"""
Opens a design in Klayout.
"""
dir = os.path.dirname(__file__)
klayout_script_path = os.path.join(dir, "open_design.py")
env = os.environ.copy()
env["EXPLICITLY_LISTED_LEFS"] = input_lef
env["PDK_ROOT"] = pdk_root
env["PDK"] = pdk
env["LAYOUT"] = input_def
subprocess.check_call(
[
"klayout",
"-rm",
klayout_script_path,
],
env=env,
)
if __name__ == "__main__":
open_design()

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env python3
# Copyright 2022 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 click
@click.command("most_recent_run")
@click.argument("runs_directory")
def main(runs_directory):
max_time = 0
latest_run_name = None
if not os.path.isdir(runs_directory):
print(f"No runs found at '{runs_directory}'.", file=sys.stderr)
exit(os.EX_NOINPUT)
for run in os.listdir(runs_directory):
run_folder_path = os.path.join(runs_directory, run)
if not os.path.isdir(run_folder_path):
continue
time = os.stat(run_folder_path).st_mtime
if time > max_time:
latest_run_name = run
if latest_run_name is not None:
print(latest_run_name, end="")
else:
print(f"No runs found at '{runs_directory}'.", file=sys.stderr)
exit(os.EX_NOINPUT)
if __name__ == "__main__":
main()

View File

@@ -1,4 +1,4 @@
# Copyright 2020-2021 Efabless Corporation
# Copyright 2020-2022 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -41,7 +41,7 @@ proc set_netlist {netlist args} {
set netlist_relative [relpath . $netlist]
puts_info "Changing netlist to '$netlist_relative'..."
puts_verbose "Changing netlist to '$netlist_relative'..."
set ::env(PREV_NETLIST) $::env(CURRENT_NETLIST)
set ::env(CURRENT_NETLIST) $netlist
@@ -59,7 +59,7 @@ proc set_netlist {netlist args} {
proc set_def {def} {
set def_relative [relpath . $def]
puts_info "Changing layout to '$def_relative'..."
puts_verbose "Changing layout to '$def_relative'..."
set ::env(CURRENT_DEF) $def
set replace [string map {/ \\/} $def]
exec sed -i -e "s/\\(set ::env(CURRENT_DEF)\\).*/\\1 $replace/" "$::env(GLB_CFG_FILE)"
@@ -67,21 +67,21 @@ proc set_def {def} {
proc set_guide {guide} {
set guide_relative [relpath . $guide]
puts_info "Changing guide to '$guide_relative'..."
puts_verbose "Changing guide to '$guide_relative'..."
set ::env(CURRENT_GUIDE) $guide
set replace [string map {/ \\/} $guide]
exec sed -i -e "s/\\(set ::env(CURRENT_GUIDE)\\).*/\\1 $replace/" "$::env(GLB_CFG_FILE)"
}
proc prep_lefs {args} {
puts_info "Preparing LEF Files"
puts_info "Extracting the number of available metal layers from $::env(TECH_LEF)"
puts_info "Preparing LEF Files..."
puts_verbose "Extracting the number of available metal layers from $::env(TECH_LEF)"
set ::env(TECH_METAL_LAYERS) [exec python3 $::env(SCRIPTS_DIR)/extract_metal_layers.py $::env(TECH_LEF)]
set ::env(MAX_METAL_LAYER) [llength $::env(TECH_METAL_LAYERS)]
puts_info "The available metal layers ($::env(MAX_METAL_LAYER)) are $::env(TECH_METAL_LAYERS)"
puts_info "Merging LEF Files..."
puts_verbose "The available metal layers ($::env(MAX_METAL_LAYER)) are $::env(TECH_METAL_LAYERS)"
puts_verbose "Merging LEF Files..."
try_catch $::env(SCRIPTS_DIR)/mergeLef.py -i $::env(TECH_LEF) $::env(CELLS_LEF) -o $::env(TMP_DIR)/merged_unpadded.lef |& tee $::env(TERMINAL_OUTPUT)
@@ -91,13 +91,13 @@ proc prep_lefs {args} {
if { [info exist ::env(EXTRA_LEFS)] } {
try_catch $::env(SCRIPTS_DIR)/mergeLef.py -i $::env(MERGED_LEF_UNPADDED) {*}$::env(EXTRA_LEFS) -o $::env(MERGED_LEF_UNPADDED) |& tee $::env(TERMINAL_OUTPUT)
puts_info "Merging the following extra LEFs: $::env(EXTRA_LEFS)"
puts_verbose "Merging the following extra LEFs: $::env(EXTRA_LEFS)"
}
# merge optimization library lef if it is different from the STD_CELL_LIBRARY
if { [info exist ::env(STD_CELL_LIBRARY_OPT)] && $::env(STD_CELL_LIBRARY_OPT) != $::env(STD_CELL_LIBRARY) } {
try_catch $::env(SCRIPTS_DIR)/mergeLef.py -i $::env(MERGED_LEF_UNPADDED) $::env(TECH_LEF_OPT) {*}$::env(CELLS_LEF_OPT) -o $::env(MERGED_LEF_UNPADDED) |& tee $::env(TERMINAL_OUTPUT)
puts_info "Merging the optimization library LEFs: $::env(TECH_LEF_OPT) $::env(CELLS_LEF_OPT)"
puts_verbose "Merging the optimization library LEFs: $::env(TECH_LEF_OPT) $::env(CELLS_LEF_OPT)"
}
file copy -force $::env(CELLS_LEF_UNPADDED) $::env(TMP_DIR)/merged.lef
@@ -106,7 +106,7 @@ proc prep_lefs {args} {
if { [info exists ::env(USE_GPIO_ROUTING_LEF)] && $::env(USE_GPIO_ROUTING_LEF)} {
set ::env(GPIO_PADS_LEF) $::env(GPIO_PADS_LEF_CORE_SIDE)
}
puts_info "Merging the following GPIO LEF views: $::env(GPIO_PADS_LEF)"
puts_verbose "Merging the following GPIO LEF views: $::env(GPIO_PADS_LEF)"
file copy $::env(CELLS_LEF) $::env(CELLS_LEF).old
try_catch $::env(SCRIPTS_DIR)/mergeLef.py -i $::env(CELLS_LEF).old {*}$::env(GPIO_PADS_LEF) -o $::env(CELLS_LEF)
@@ -125,7 +125,7 @@ proc prep_lefs {args} {
}
proc gen_exclude_list {args} {
puts_info "Generating Exclude List..."
puts_verbose "Generating cell exclude list..."
set options {
{-lib required}
{-drc_exclude_list optional}
@@ -163,7 +163,7 @@ proc gen_exclude_list {args} {
}
if { [file exists $arg_values(-output)] && [info exists flags_map(-create_dont_use_list)] } {
puts_info "Creating ::env(DONT_USE_CELLS)..."
puts_verbose "Creating ::env(DONT_USE_CELLS)..."
set fp [open "$arg_values(-output)" r]
set x [read $fp]
set y [split $x]
@@ -175,7 +175,7 @@ proc gen_exclude_list {args} {
}
proc trim_lib {args} {
puts_info "Trimming Liberty..."
puts_verbose "Trimming Liberty..."
set options {
{-input optional}
{-output optional}
@@ -248,12 +248,13 @@ proc prep {args} {
{-run_path optional}
{-src optional}
{-override_env optional}
{-verbose optional}
}
set flags {
-init_design_config
-disable_output
-overwrite
-last_run
}
set args_copy $args
@@ -293,19 +294,30 @@ proc prep {args} {
exit 0
}
if { ! [info exists flags_map(-disable_output)] } {
set_if_unset arg_values(-verbose) "0"
set ::env(OPENLANE_VERBOSE) $arg_values(-verbose)
set ::env(TERMINAL_OUTPUT) "/dev/null"
if { $::env(OPENLANE_VERBOSE) >= 2 } {
set ::env(TERMINAL_OUTPUT) ">&@stdout"
} else {
set ::env(TERMINAL_OUTPUT) "/dev/null"
}
set ::env(datetime) [clock format [clock seconds] -format %Y.%m.%d_%H.%M.%S ]
if { [lsearch -exact $args_copy -tag ] >= 0} {
set tag "$arg_values(-tag)"
} else {
set tag "RUN_$::env(datetime)"
set ::env(START_TIME) [clock format [clock seconds] -format %Y.%m.%d_%H.%M.%S ]
if { [info exists flags_map(-last_run)] } {
if { [info exists arg_values(-tag)] } {
puts_err "Cannot specify a tag with -last_run set."
return -code error
}
set arg_values(-tag) [exec python3 ./scripts/most_recent_run.py $::env(DESIGN_DIR)/runs]
}
set_if_unset arg_values(-tag) "RUN_$::env(START_TIME)"
set tag $arg_values(-tag)
set ::env(CONFIGS) [glob $::env(OPENLANE_ROOT)/configuration/*.tcl]
if { [info exists arg_values(-config_file)] } {
@@ -431,7 +443,7 @@ proc prep {args} {
puts_warn "Removing exisiting run $::env(RUN_DIR)"
after 1000
file delete -force $::env(RUN_DIR)
} else {
} elseif { ![info exists flags_map(-last_run)] } {
puts_warn "A run for $::env(DESIGN_NAME) with tag '$tag' already exists. Pass -overwrite option to overwrite it"
puts_info "Now you can run commands that pick up where '$tag' left off"
after 1000
@@ -490,7 +502,7 @@ proc prep {args} {
set density $::env(PL_TARGET_DENSITY)
# Fill config file
puts_info "Storing configs into config.tcl ..."
puts_verbose "Storing configs into config.tcl ..."
exec echo "# Run configs" > $::env(GLB_CFG_FILE)
set_log ::env(PDK_ROOT) $::env(PDK_ROOT) $::env(GLB_CFG_FILE) 1
foreach index [lsort [array names ::env]] {
@@ -633,7 +645,6 @@ proc prep {args} {
}
}
puts_info "Preparation complete"
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "openlane design prep"
return -code ok

View File

@@ -31,8 +31,6 @@ proc check_synthesis_failure {args} {
if { ! $checker } {
puts_err "Synthesis failed"
flow_fail
} else {
puts_info "Synthesis was successful"
}
}
@@ -168,8 +166,6 @@ proc check_cts_clock_nets {args} {
puts_err $error
puts_err "TritonCTS failed to find clock nets and/or sinks in the design; check whether the synthesized netlist contains flip-flops."
flow_fail
} else {
puts_info "Clock Tree Synthesis was successful"
}
}
@@ -180,8 +176,6 @@ proc check_replace_divergence {args} {
puts_err "Global placement failed"
puts_err $error
flow_fail
} else {
puts_info "Global placement was successful"
}
}
@@ -192,8 +186,6 @@ proc check_macro_placer_num_solns {args} {
puts_err "Macro placement failed"
puts_err "$error; you may need to adjust the HALO"
flow_fail
} else {
puts_info "Macro placement was successful"
}
}
@@ -239,10 +231,8 @@ proc quit_on_lvs_error {args} {
set checker [catch {exec grep -E -o "Total errors = 0" $arg_values(-log)} error]
if { $checker != 0 } {
puts_err "There are LVS errors in the design according to Netgen LVS."
puts_err "There are LVS errors in the design.."
flow_fail
} else {
puts_info "No LVS mismatches."
}
}
}
@@ -259,8 +249,6 @@ proc quit_on_illegal_overlaps {args} {
puts_err "There are illegal overlaps (e.g., routes over obstructions) in your design."
puts_err "See $arg_values(-log) for more."
flow_fail
} else {
puts_info "No illegal overlaps detected during extraction."
}
}
}
@@ -275,8 +263,6 @@ proc quit_on_unconnected_pdn_nodes {args} {
offsets/pitches to power all standard cell rails (or other PDN stripes) \
in your design."
flow_fail
} else {
puts_info "PDN generation was successful."
}
}

View File

@@ -36,8 +36,8 @@ proc init_floorplan_or {args} {
}
proc init_floorplan {args} {
puts_info "Running Initial Floorplanning..."
increment_index
puts_info "Running Initial Floorplanning..."
TIMER::timer_start
set ::env(SAVE_DEF) [index_file $::env(floorplan_tmpfiles)/initial_fp.def]
set ::env(SAVE_SDC) [index_file $::env(floorplan_tmpfiles)/initial_fp.sdc]
@@ -61,8 +61,8 @@ proc init_floorplan {args} {
set core_width [expr {[lindex $::env(CORE_AREA) 2] - [lindex $::env(CORE_AREA) 0]}]
set core_height [expr {[lindex $::env(CORE_AREA) 3] - [lindex $::env(CORE_AREA) 1]}]
puts_info "Core area width: $core_width"
puts_info "Core area height: $core_height"
puts_verbose "Core area width: $core_width"
puts_verbose "Core area height: $core_height"
if { $::env(FP_PDN_AUTO_ADJUST) } {
if { $core_width <= [expr {$::env(FP_PDN_VOFFSET) + $::env(FP_PDN_VPITCH)}] ||\
@@ -77,11 +77,12 @@ proc init_floorplan {args} {
}
}
puts_info "Final Vertical PDN Offset: $::env(FP_PDN_VOFFSET)"
puts_info "Final Horizontal PDN Offset: $::env(FP_PDN_HOFFSET)"
puts_info "Final Vertical PDN Pitch: $::env(FP_PDN_VPITCH)"
puts_info "Final Horizontal PDN Pitch: $::env(FP_PDN_HPITCH)"
puts_verbose "Final Vertical PDN Offset: $::env(FP_PDN_VOFFSET)"
puts_verbose "Final Horizontal PDN Offset: $::env(FP_PDN_HOFFSET)"
puts_verbose "Final Vertical PDN Pitch: $::env(FP_PDN_VPITCH)"
puts_verbose "Final Horizontal PDN Pitch: $::env(FP_PDN_HPITCH)"
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "floorplan initialization - openroad"
@@ -301,9 +302,7 @@ proc run_power_grid_generation {args} {
set ::env(GND_NETS) $::env(GND_PIN)
}
puts_info "Power planning the following nets"
puts_info "Power: $::env(VDD_NETS)"
puts_info "Ground: $::env(GND_NETS)"
puts_info "Power planning with power {$::env(VDD_NETS)} and ground {$::env(GND_NETS)}..."
if { [llength $::env(VDD_NETS)] != [llength $::env(GND_NETS)] } {
puts_err "VDD_NETS and GND_NETS must be of equal lengths"
@@ -368,73 +367,72 @@ proc run_power_grid_generation {args} {
set ::env(FP_PDN_CORE_RING_VOFFSET)\
[expr $::env(FP_PDN_CORE_RING_VOFFSET)\
+2*($::env(FP_PDN_CORE_RING_VWIDTH)\
+max($::env(FP_PDN_CORE_RING_VSPACING), $::env(FP_PDN_CORE_RING_HSPACING)))]
set ::env(FP_PDN_CORE_RING_HOFFSET) \
[expr $::env(FP_PDN_CORE_RING_HOFFSET)\
+2*($::env(FP_PDN_CORE_RING_HWIDTH)+\
max($::env(FP_PDN_CORE_RING_VSPACING), $::env(FP_PDN_CORE_RING_HSPACING)))]
}
set ::env(FP_PDN_ENABLE_RAILS) 1
}
+2*($::env(FP_PDN_CORE_RING_VWIDTH)\
+max($::env(FP_PDN_CORE_RING_VSPACING), $::env(FP_PDN_CORE_RING_HSPACING)))]
set ::env(FP_PDN_CORE_RING_HOFFSET) \
[expr $::env(FP_PDN_CORE_RING_HOFFSET)\
+2*($::env(FP_PDN_CORE_RING_HWIDTH)+\
max($::env(FP_PDN_CORE_RING_VSPACING), $::env(FP_PDN_CORE_RING_HSPACING)))]
}
set ::env(FP_PDN_ENABLE_RAILS) 1
}
proc run_floorplan {args} {
puts_info "Running Floorplanning..."
# |----------------------------------------------------|
# |---------------- 2. FLOORPLAN ------------------|
# |----------------------------------------------------|
#
# intial fp
init_floorplan
proc run_floorplan {args} {
# |----------------------------------------------------|
# |---------------- 2. FLOORPLAN ------------------|
# |----------------------------------------------------|
#
# intial fp
init_floorplan
# check for deprecated io variables
if { [info exists ::env(FP_IO_HMETAL)]} {
set ::env(FP_IO_HLAYER) [lindex $::env(TECH_METAL_LAYERS) [expr {$::env(FP_IO_HMETAL) - 1}]]
puts_warn "You're using FP_IO_HMETAL in your configuration, which is a deprecated variable that will be removed in the future."
puts_warn "We recommend you update your configuration as follows:"
puts_warn "\tset ::env(FP_IO_HLAYER) {$::env(FP_IO_HLAYER)}"
}
if { [info exists ::env(FP_IO_VMETAL)]} {
set ::env(FP_IO_VLAYER) [lindex $::env(TECH_METAL_LAYERS) [expr {$::env(FP_IO_VMETAL) - 1}]]
puts_warn "You're using FP_IO_VMETAL in your configuration, which is a deprecated variable that will be removed in the future."
puts_warn "We recommend you update your configuration as follows:"
puts_warn "\tset ::env(FP_IO_VLAYER) {$::env(FP_IO_VLAYER)}"
}
# place io
if { [info exists ::env(FP_PIN_ORDER_CFG)] } {
place_io_ol
} else {
if { [info exists ::env(FP_CONTEXT_DEF)] && [info exists ::env(FP_CONTEXT_LEF)] } {
place_io
global_placement_or
place_contextualized_io \
-lef $::env(FP_CONTEXT_LEF) \
-def $::env(FP_CONTEXT_DEF)
} else {
place_io
}
}
apply_def_template
if { [info exist ::env(EXTRA_LEFS)] } {
if { [info exist ::env(MACRO_PLACEMENT_CFG)] } {
file copy -force $::env(MACRO_PLACEMENT_CFG) $::env(placement_tmpfiles)/macro_placement.cfg
manual_macro_placement f
} else {
global_placement_or
basic_macro_placement
}
}
tap_decap_or
scrot_klayout -layout $::env(CURRENT_DEF) -log $::env(floorplan_logs)/screenshot.log
run_power_grid_generation
# check for deprecated io variables
if { [info exists ::env(FP_IO_HMETAL)]} {
set ::env(FP_IO_HLAYER) [lindex $::env(TECH_METAL_LAYERS) [expr {$::env(FP_IO_HMETAL) - 1}]]
puts_warn "You're using FP_IO_HMETAL in your configuration, which is a deprecated variable that will be removed in the future."
puts_warn "We recommend you update your configuration as follows:"
puts_warn "\tset ::env(FP_IO_HLAYER) {$::env(FP_IO_HLAYER)}"
}
package provide openlane 0.9
if { [info exists ::env(FP_IO_VMETAL)]} {
set ::env(FP_IO_VLAYER) [lindex $::env(TECH_METAL_LAYERS) [expr {$::env(FP_IO_VMETAL) - 1}]]
puts_warn "You're using FP_IO_VMETAL in your configuration, which is a deprecated variable that will be removed in the future."
puts_warn "We recommend you update your configuration as follows:"
puts_warn "\tset ::env(FP_IO_VLAYER) {$::env(FP_IO_VLAYER)}"
}
# place io
if { [info exists ::env(FP_PIN_ORDER_CFG)] } {
place_io_ol
} else {
if { [info exists ::env(FP_CONTEXT_DEF)] && [info exists ::env(FP_CONTEXT_LEF)] } {
place_io
global_placement_or
place_contextualized_io \
-lef $::env(FP_CONTEXT_LEF) \
-def $::env(FP_CONTEXT_DEF)
} else {
place_io
}
}
apply_def_template
if { [info exist ::env(EXTRA_LEFS)] } {
if { [info exist ::env(MACRO_PLACEMENT_CFG)] } {
file copy -force $::env(MACRO_PLACEMENT_CFG) $::env(placement_tmpfiles)/macro_placement.cfg
manual_macro_placement f
} else {
global_placement_or
basic_macro_placement
}
}
tap_decap_or
scrot_klayout -layout $::env(CURRENT_DEF) $::env(floorplan_logs)/screenshot.log
run_power_grid_generation
}
package provide openlane 0.9

View File

@@ -1,4 +1,4 @@
# Copyright 2020-2021 Efabless Corporation
# Copyright 2020-2022 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -13,64 +13,58 @@
# limitations under the License.
proc run_klayout {args} {
if {$::env(RUN_KLAYOUT)} {
TIMER::timer_start
set ::env(CURRENT_STAGE) finishing
puts_info "Generting GDS II with Klayout..."
if {[ info exists ::env(KLAYOUT_TECH)] } {
increment_index
puts_info "Streaming out GDS II..."
set gds_files_in ""
if { [info exist ::env(EXTRA_GDS_FILES)] } {
set gds_files_in $::env(EXTRA_GDS_FILES)
}
if { $::env(STD_CELL_LIBRARY_OPT) != $::env(STD_CELL_LIBRARY) } {
set cells_gds "$::env(GDS_FILES) $::env(GDS_FILES_OPT)"
} else {
set cells_gds $::env(GDS_FILES)
}
set klayout_out $::env(finishing_results)/$::env(DESIGN_NAME).klayout.gds
try_catch klayout -b\
-rm $::env(SCRIPTS_DIR)/klayout/def2gds.py\
-rd out_gds=$klayout_out\
-rd tech_file=$::env(KLAYOUT_TECH)\
-rd design_name=$::env(DESIGN_NAME)\
-rd in_def=$::env(CURRENT_DEF)\
-rd "in_gds=$cells_gds $gds_files_in"\
-rd "config_file="\
-rd "seal_gds="\
-rd lef_file=$::env(MERGED_LEF)\
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/gdsii-klayout.log]
if { $::env(PRIMARY_SIGNOFF_TOOL) == "klayout" } {
set ::env(CURRENT_GDS) $::env(finishing_results)/$::env(DESIGN_NAME).gds
file copy -force $klayout_out $::env(CURRENT_GDS)
}
if {[info exists ::env(KLAYOUT_PROPERTIES)]} {
file copy -force $::env(KLAYOUT_PROPERTIES) $::env(finishing_results)/$::env(DESIGN_NAME).lyp
} else {
puts_warn "::env(KLAYOUT_PROPERTIES) is not defined. So, it won't be copied to the run directory."
}
puts_info "Back-up GDS-II streamed out."
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "gdsii - klayout"
scrot_klayout -layout $::env(finishing_results)/$::env(DESIGN_NAME).gds -log $::env(finishing_logs)/screenshot.klayout.log
if { [info exists ::env(KLAYOUT_DRC_KLAYOUT_GDS)] && $::env(KLAYOUT_DRC_KLAYOUT_GDS) } {
set conf_save $::env(RUN_KLAYOUT_DRC)
set ::env(RUN_KLAYOUT_DRC) 1
run_klayout_drc -gds $::env(finishing_results)/$::env(DESIGN_NAME).gds -stage klayout
set ::env(RUN_KLAYOUT_DRC) $conf_save
}
} elseif { $::env(PRIMARY_SIGNOFF_TOOL) != "klayout" } {
puts_warn "::env(KLAYOUT_TECH) is not defined for the current PDK. So, GDS-II streaming out using Klayout will be skipped."
puts_warn "This warning can be turned off by setting ::env(RUN_KLAYOUT) to 0, or defining a tech file."
} else {
puts_err "::env(KLAYOUT_TECH) is not defined for the current PDK, however Klayout is set as the primary signoff tool. This is a critical error."
flow_fail
TIMER::timer_start
set ::env(CURRENT_STAGE) finishing
if {[ info exists ::env(KLAYOUT_TECH)] } {
increment_index
puts_info "Streaming out GDS-II with Klayout..."
set gds_files_in ""
if { [info exist ::env(EXTRA_GDS_FILES)] } {
set gds_files_in $::env(EXTRA_GDS_FILES)
}
if { $::env(STD_CELL_LIBRARY_OPT) != $::env(STD_CELL_LIBRARY) } {
set cells_gds "$::env(GDS_FILES) $::env(GDS_FILES_OPT)"
} else {
set cells_gds $::env(GDS_FILES)
}
set klayout_out $::env(finishing_results)/$::env(DESIGN_NAME).klayout.gds
try_catch klayout -b\
-rm $::env(SCRIPTS_DIR)/klayout/def2gds.py\
-rd out_gds=$klayout_out\
-rd tech_file=$::env(KLAYOUT_TECH)\
-rd design_name=$::env(DESIGN_NAME)\
-rd in_def=$::env(CURRENT_DEF)\
-rd "in_gds=$cells_gds $gds_files_in"\
-rd "config_file="\
-rd "seal_gds="\
-rd lef_file=$::env(MERGED_LEF)\
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/gdsii-klayout.log]
if {[info exists ::env(KLAYOUT_PROPERTIES)]} {
file copy -force $::env(KLAYOUT_PROPERTIES) $::env(finishing_results)/$::env(DESIGN_NAME).lyp
} else {
puts_warn "::env(KLAYOUT_PROPERTIES) is not defined. So, it won't be copied to the run directory."
}
if { $::env(PRIMARY_SIGNOFF_TOOL) == "klayout" } {
set ::env(CURRENT_GDS) $::env(finishing_results)/$::env(DESIGN_NAME).gds
file copy -force $klayout_out $::env(CURRENT_GDS)
}
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "gdsii - klayout"
scrot_klayout -layout $::env(finishing_results)/$::env(DESIGN_NAME).gds -log $::env(finishing_logs)/screenshot.klayout.log
} elseif { $::env(PRIMARY_SIGNOFF_TOOL) != "klayout" } {
puts_warn "::env(KLAYOUT_TECH) is not defined for the current PDK. So, GDS-II streaming out using Klayout will be skipped."
puts_warn "This warning can be turned off by setting ::env(RUN_KLAYOUT) to 0, or defining a tech file."
} else {
puts_err "::env(KLAYOUT_TECH) is not defined for the current PDK, however Klayout is set as the primary signoff tool. This is a critical error."
flow_fail
}
}
proc scrot_klayout {args} {
@@ -103,85 +97,91 @@ proc scrot_klayout {args} {
}
proc run_klayout_drc {args} {
if {$::env(RUN_KLAYOUT_DRC)} {
TIMER::timer_start
TIMER::timer_start
if {[ info exists ::env(KLAYOUT_DRC_TECH_SCRIPT)] && [file exists $::env(KLAYOUT_DRC_TECH_SCRIPT)]} {
increment_index
puts_info "Running DRC on the layout using Klayout..."
if {[ info exists ::env(KLAYOUT_DRC_TECH_SCRIPT)] } {
increment_index
set options {
{-gds optional}
{-stage optional}
}
parse_key_args "run_klayout_drc" args arg_values $options
if {[info exists ::env(CURRENT_GDS)]} {
set_if_unset arg_values(-gds) $::env(CURRENT_GDS)
}
set_if_unset arg_values(-stage) magic
try_catch bash $::env(SCRIPTS_DIR)/klayout/run_drc.sh $::env(KLAYOUT_DRC_TECH_SCRIPT) $arg_values(-gds) $arg_values(-gds).lydrc |& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/$arg_values(-stage).drc.log]
file copy -force $arg_values(-gds).lydrc [index_file $::env(finishing_reports)/$arg_values(-stage).lydrc]
puts_info "Klayout DRC Complete"
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "drc - klayout"
} elseif { $::env(PRIMARY_SIGNOFF_TOOL) != "klayout" } {
puts_warn "::env(KLAYOUT_DRC_TECH_SCRIPT) is not defined for the current PDK. So, GDS-II streaming out using Klayout will be skipped."
puts_warn "This warning can be turned off by setting ::env(RUN_KLAYOUT_DRC) to 0, or designating a tech file."
} else {
puts_err "::env(KLAYOUT_DRC_TECH_SCRIPT) is not defined for the current PDK, however Klayout is set as the primary signoff tool. This is a critical error."
flow_fail
set options {
{-gds optional}
{-stage optional}
}
parse_key_args "run_klayout_drc" args arg_values $options
if {[info exists ::env(CURRENT_GDS)]} {
set_if_unset arg_values(-gds) $::env(CURRENT_GDS)
}
set_if_unset arg_values(-stage) magic
try_catch bash $::env(SCRIPTS_DIR)/klayout/run_drc.sh $::env(KLAYOUT_DRC_TECH_SCRIPT) $arg_values(-gds) $arg_values(-gds).lydrc |& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/$arg_values(-stage).drc.log]
file copy -force $arg_values(-gds).lydrc [index_file $::env(finishing_reports)/$arg_values(-stage).lydrc]
puts_info "Klayout DRC Complete"
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "drc - klayout"
} elseif { $::env(PRIMARY_SIGNOFF_TOOL) != "klayout" } {
puts_warn "::env(KLAYOUT_DRC_TECH_SCRIPT) is not defined or doesn't exist for the current PDK. So, GDS-II streaming out using Klayout will be skipped."
puts_warn "This warning can be turned off by setting ::env(RUN_KLAYOUT_DRC) to 0, or designating a tech file."
} else {
puts_err "::env(KLAYOUT_DRC_TECH_SCRIPT) is not defined or doesn't exist for the current PDK, however Klayout is set as the primary signoff tool. This is a critical error."
flow_fail
}
}
proc run_klayout_gds_xor {args} {
if {$::env(RUN_KLAYOUT_XOR)} {
increment_index
index_file $::env(finishing_logs)/xor.log
TIMER::timer_start
puts_info "Running XOR on the layouts using Klayout..."
set options {
{-layout1 optional}
{-layout2 optional}
{-output_xml optional}
{-output_gds optional}
}
parse_key_args "run_klayout_gds_xor" args arg_values $options
set_if_unset arg_values(-layout1) $::env(finishing_results)/$::env(DESIGN_NAME).gds
set_if_unset arg_values(-layout2) $::env(finishing_results)/$::env(DESIGN_NAME).klayout.gds
set_if_unset arg_values(-output_xml) $::env(finishing_reports)/$::env(DESIGN_NAME).xor.xml
set_if_unset arg_values(-output_gds) $::env(finishing_reports)/$::env(DESIGN_NAME).xor.gds
if { [file exists $arg_values(-layout1)]} {
if { [file exists $arg_values(-layout2)] } {
if { $::env(KLAYOUT_XOR_GDS) } {
try_catch bash $::env(SCRIPTS_DIR)/klayout/xor.sh \
$arg_values(-layout1) $arg_values(-layout2) $::env(DESIGN_NAME) \
$arg_values(-output_gds) \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/xor.log]
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/parse_klayout_xor_log.py \
-l [index_file $::env(finishing_logs)/xor.log] \
-o [index_file $::env(finishing_reports)/xor.rpt]
scrot_klayout -layout $arg_values(-output_gds) -log $::env(finishing_logs)/screenshot.klayout.xor.log
}
increment_index
index_file $::env(finishing_logs)/xor.log
TIMER::timer_start
puts_info "Running XOR on the layouts using Klayout..."
set options {
{-layout1 optional}
{-layout2 optional}
{-output_xml optional}
{-output_gds optional}
}
parse_key_args "run_klayout_gds_xor" args arg_values $options
set_if_unset arg_values(-layout1) $::env(finishing_results)/$::env(DESIGN_NAME).gds
set_if_unset arg_values(-layout2) $::env(finishing_results)/$::env(DESIGN_NAME).klayout.gds
set_if_unset arg_values(-output_xml) $::env(finishing_reports)/$::env(DESIGN_NAME).xor.xml
set_if_unset arg_values(-output_gds) $::env(finishing_reports)/$::env(DESIGN_NAME).xor.gds
if { [file exists $arg_values(-layout1)]} {
if { [file exists $arg_values(-layout2)] } {
if { $::env(KLAYOUT_XOR_GDS) } {
try_catch bash $::env(SCRIPTS_DIR)/klayout/xor.sh \
$arg_values(-layout1) $arg_values(-layout2) $::env(DESIGN_NAME) \
$arg_values(-output_gds) \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/xor.log]
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/parse_klayout_xor_log.py \
-l [index_file $::env(finishing_logs)/xor.log] \
-o [index_file $::env(finishing_reports)/xor.rpt]
scrot_klayout -layout $arg_values(-output_gds) -log $::env(finishing_logs)/screenshot.klayout.xor.log
}
if { $::env(KLAYOUT_XOR_XML) } {
try_catch bash $::env(SCRIPTS_DIR)/klayout/xor.sh \
$arg_values(-layout1) $arg_values(-layout2) $::env(DESIGN_NAME) \
$arg_values(-output_xml) \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/xor.log]
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/parse_klayout_xor_log.py \
-l [index_file $::env(finishing_logs)/xor.log] \
-o [index_file $::env(finishing_reports)/xor.rpt]
}
puts_info "Klayout XOR Complete"
} else {
puts_warn "$arg_values(-layout2) wasn't found. Skipping GDS XOR."
if { $::env(KLAYOUT_XOR_XML) } {
try_catch bash $::env(SCRIPTS_DIR)/klayout/xor.sh \
$arg_values(-layout1) $arg_values(-layout2) $::env(DESIGN_NAME) \
$arg_values(-output_xml) \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/xor.log]
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/parse_klayout_xor_log.py \
-l [index_file $::env(finishing_logs)/xor.log] \
-o [index_file $::env(finishing_reports)/xor.rpt]
}
} else {
puts_warn "$arg_values(-layout1) wasn't found. Skipping GDS XOR."
puts_warn "$arg_values(-layout2) wasn't found. Skipping GDS XOR."
}
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "xor - klayout"
} else {
puts_warn "$arg_values(-layout1) wasn't found. Skipping GDS XOR."
}
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "xor - klayout"
}
proc open_in_klayout {args} {
set options {
{-layout optional}
}
parse_key_args "open_in_klayout" args arg_values $options
set_if_unset arg_values(-layout) $::env(CURRENT_DEF)
try_catch python3 $::env(SCRIPTS_DIR)/klayout/open_design_cmd.py\
$arg_values(-layout)
}
package provide openlane 0.9

View File

@@ -32,10 +32,10 @@ proc verilog_to_verilogPower {args} {
set lef $arg_values(-lef)
try_catch $bin \
-v $power \
-g $gnd \
-l $lef \
$in |& tee $out
-v $power \
-g $gnd \
-l $lef \
$in |& tee $out
}
# WORKS ON DEF FILES
@@ -71,13 +71,13 @@ proc write_powered_verilog {args} {
}
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/write_powered_def.py \
-d $arg_values(-def) \
-l $arg_values(-lef) \
--power-port $arg_values(-power) \
--ground-port $arg_values(-ground) \
--powered-netlist $arg_values(-powered_netlist) \
-o $arg_values(-output_def) \
|& tee $::env(TERMINAL_OUTPUT) [index_file $arg_values(-def_log)]
-d $arg_values(-def) \
-l $arg_values(-lef) \
--power-port $arg_values(-power) \
--ground-port $arg_values(-ground) \
--powered-netlist $arg_values(-powered_netlist) \
-o $arg_values(-output_def) \
|& tee $::env(TERMINAL_OUTPUT) [index_file $arg_values(-def_log)]
write_verilog $arg_values(-output_verilog) -def $arg_values(-output_def) -log [index_file $arg_values(-log)] -canonical
TIMER::timer_stop
@@ -87,93 +87,91 @@ proc write_powered_verilog {args} {
# "layout": a spice netlist
# "schematic": a verilog netlist
proc run_lvs {{layout "$::env(EXT_NETLIST)"}} {
if { $::env(RUN_LVS) } {
# LEF LVS output to lvs.lef.log, design.lvs.lef.log, design.lvs.lef.json, design.lvs.lef.log
# GDS LVS output to lvs.gds.log, design.lvs.gds.log, design.lvs.gds.json, design.lvs.gds.log
# GDS LVS uses STD_CELL_LIBRARY spice and
# if defined, additional LVS_EXTRA_STD_CELL_LIBRARY spice and LVS_EXTRA_GATE_LEVEL_VERILOG files
# Write Netlist
if { $::env(LVS_INSERT_POWER_PINS) } {
set powered_netlist_name [index_file $::env(finishing_tmpfiles)/powered_netlist.v]
set powered_def_name [index_file $::env(finishing_tmpfiles)/powered_def.def]
write_powered_verilog\
-output_verilog $powered_netlist_name\
-output_def $powered_def_name\
-log $::env(finishing_logs)/write_verilog.log\
-def_log $::env(finishing_logs)/write_powered_def.log
# LEF LVS output to lvs.lef.log, design.lvs.lef.log, design.lvs.lef.json, design.lvs.lef.log
# GDS LVS output to lvs.gds.log, design.lvs.gds.log, design.lvs.gds.json, design.lvs.gds.log
# GDS LVS uses STD_CELL_LIBRARY spice and
# if defined, additional LVS_EXTRA_STD_CELL_LIBRARY spice and LVS_EXTRA_GATE_LEVEL_VERILOG files
# Write Netlist
if { $::env(LVS_INSERT_POWER_PINS) } {
set powered_netlist_name [index_file $::env(finishing_tmpfiles)/powered_netlist.v]
set powered_def_name [index_file $::env(finishing_tmpfiles)/powered_def.def]
write_powered_verilog\
-output_verilog $powered_netlist_name\
-output_def $powered_def_name\
-log $::env(finishing_logs)/write_verilog.log\
-def_log $::env(finishing_logs)/write_powered_def.log
set_netlist $powered_netlist_name
set_netlist $powered_netlist_name
if { $::env(LEC_ENABLE) } {
logic_equiv_check -rhs $::env(PREV_NETLIST) -lhs $::env(CURRENT_NETLIST)
}
if { $::env(LEC_ENABLE) } {
logic_equiv_check -rhs $::env(PREV_NETLIST) -lhs $::env(CURRENT_NETLIST)
}
increment_index
TIMER::timer_start
if { [info exist ::env(MAGIC_EXT_USE_GDS)] && $::env(MAGIC_EXT_USE_GDS) } {
set extract_type gds
puts_info "Running GDS LVS..."
} else {
set extract_type lef
puts_info "Running LEF LVS..."
}
set schematic $::env(CURRENT_NETLIST)
set layout [subst $layout]
set setup_file $::env(NETGEN_SETUP_FILE)
set module_name $::env(DESIGN_NAME)
#writes setup_file_*_lvs to tmp directory.
set lvs_file_path [index_file $::env(finishing_tmpfiles)/setup_file.$extract_type.lvs]
set lvs_file [open $lvs_file_path w]
if { "$extract_type" == "gds" } {
if { [info exist ::env(LVS_EXTRA_STD_CELL_LIBRARY)] } {
set libs_in $::env(LVS_EXTRA_STD_CELL_LIBRARY)
foreach lib_file $libs_in {
puts $lvs_file "puts \"Reading spice netlist file $lib_file\""
puts $lvs_file "readnet spice $lib_file 1"
}
} else {
if { [info exist ::env(STD_CELL_LIBRARY)] } {
set std_cell_source $::env(PDK_ROOT)/$::env(PDK)/libs.ref/$::env(STD_CELL_LIBRARY)/spice/$::env(STD_CELL_LIBRARY).spice
} else {
set std_cell_source $::env(PDK_ROOT)/$::env(PDK)/libs.ref/sky130_fd_sc_hd/spice/sky130_fd_sc_hd.spice
}
puts $lvs_file "puts \"Reading spice netlist file $std_cell_source\""
puts $lvs_file "readnet spice $std_cell_source 1"
}
if { [info exist ::env(LVS_EXTRA_GATE_LEVEL_VERILOG)] } {
set libs_in $::env(LVS_EXTRA_GATE_LEVEL_VERILOG)
foreach lib_file $libs_in {
puts $lvs_file "puts \"Reading verilog netlist file $lib_file\""
puts $lvs_file "readnet verilog $lib_file 1"
}
}
}
set extraction_prefix [index_file $::env(finishing_logs)/$::env(DESIGN_NAME).$extract_type]
puts $lvs_file "lvs {$layout $module_name} {$schematic $module_name} $setup_file $extraction_prefix.log -json"
close $lvs_file
puts_info "$layout against $schematic"
try_catch netgen -batch source $lvs_file_path \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/$extract_type.log]
set count_lvs_log [index_file $::env(finishing_logs)/$::env(DESIGN_NAME).lvs.$extract_type.log]
exec python3 $::env(SCRIPTS_DIR)/count_lvs.py \
-f $extraction_prefix.json \
|& tee $::env(TERMINAL_OUTPUT) $count_lvs_log
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "lvs - netgen"
quit_on_lvs_error -log $count_lvs_log
}
increment_index
TIMER::timer_start
if { [info exist ::env(MAGIC_EXT_USE_GDS)] && $::env(MAGIC_EXT_USE_GDS) } {
set extract_type gds
puts_info "Running GDS LVS..."
} else {
set extract_type lef
puts_info "Running LEF LVS..."
}
set schematic $::env(CURRENT_NETLIST)
set layout [subst $layout]
set setup_file $::env(NETGEN_SETUP_FILE)
set module_name $::env(DESIGN_NAME)
#writes setup_file_*_lvs to tmp directory.
set lvs_file_path [index_file $::env(finishing_tmpfiles)/setup_file.$extract_type.lvs]
set lvs_file [open $lvs_file_path w]
if { "$extract_type" == "gds" } {
if { [info exist ::env(LVS_EXTRA_STD_CELL_LIBRARY)] } {
set libs_in $::env(LVS_EXTRA_STD_CELL_LIBRARY)
foreach lib_file $libs_in {
puts $lvs_file "puts \"Reading spice netlist file $lib_file\""
puts $lvs_file "readnet spice $lib_file 1"
}
} else {
if { [info exist ::env(STD_CELL_LIBRARY)] } {
set std_cell_source $::env(PDK_ROOT)/$::env(PDK)/libs.ref/$::env(STD_CELL_LIBRARY)/spice/$::env(STD_CELL_LIBRARY).spice
} else {
set std_cell_source $::env(PDK_ROOT)/$::env(PDK)/libs.ref/sky130_fd_sc_hd/spice/sky130_fd_sc_hd.spice
}
puts $lvs_file "puts \"Reading spice netlist file $std_cell_source\""
puts $lvs_file "readnet spice $std_cell_source 1"
}
if { [info exist ::env(LVS_EXTRA_GATE_LEVEL_VERILOG)] } {
set libs_in $::env(LVS_EXTRA_GATE_LEVEL_VERILOG)
foreach lib_file $libs_in {
puts $lvs_file "puts \"Reading verilog netlist file $lib_file\""
puts $lvs_file "readnet verilog $lib_file 1"
}
}
}
set extraction_prefix [index_file $::env(finishing_logs)/$::env(DESIGN_NAME).$extract_type]
puts $lvs_file "lvs {$layout $module_name} {$schematic $module_name} $setup_file $extraction_prefix.log -json"
close $lvs_file
puts_verbose "$layout against $schematic"
try_catch netgen -batch source $lvs_file_path \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/$extract_type.log]
set count_lvs_log [index_file $::env(finishing_logs)/$::env(DESIGN_NAME).lvs.$extract_type.log]
exec python3 $::env(SCRIPTS_DIR)/count_lvs.py \
-f $extraction_prefix.json \
|& tee $::env(TERMINAL_OUTPUT) $count_lvs_log
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "lvs - netgen"
quit_on_lvs_error -log $count_lvs_log
}
proc run_netgen {args} {

View File

@@ -20,7 +20,7 @@ proc run_magic {args} {
# |----------------------------------------------------|
# |---------------- 6. TAPE-OUT ---------------------|
# |----------------------------------------------------|
puts_info "Streaming out GDS II..."
puts_info "Streaming out GDS-II with Magic..."
set ::env(CURRENT_STAGE) finishing
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)"
# the following MAGTYPE better be mag for clean GDS generation
@@ -29,14 +29,14 @@ proc run_magic {args} {
set ::env(MAGTYPE) mag
# Generate GDS and MAG views
set ::env(MAGIC_GDS) $::env(finishing_results)/$::env(DESIGN_NAME).magic.gds
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$::env(SCRIPTS_DIR)/magic/mag_gds.tcl \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/gdsii.log]
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$::env(SCRIPTS_DIR)/magic/mag_gds.tcl \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/gdsii.log]
if { $::env(PRIMARY_SIGNOFF_TOOL) == "magic" } {
set ::env(CURRENT_GDS) $::env(finishing_results)/$::env(DESIGN_NAME).gds
@@ -72,22 +72,22 @@ proc run_magic {args} {
# Generate LEF view
set ::env(MAGTYPE) maglef
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$::env(SCRIPTS_DIR)/magic/lef.tcl \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/lef.log]
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$::env(SCRIPTS_DIR)/magic/lef.tcl \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/lef.log]
if { $::env(MAGIC_GENERATE_MAGLEF) } {
# Generate MAGLEF view
set ::env(MAGTYPE) maglef
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$::env(SCRIPTS_DIR)/magic/maglef.tcl \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/maglef.log]
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$::env(SCRIPTS_DIR)/magic/maglef.tcl \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/maglef.log]
# By default, copy the GDS properties into the maglef/ view
copy_gds_properties $::env(finishing_tmpfiles)/gds_ptrs.mag $::env(finishing_results)/$::env(DESIGN_NAME).lef.mag
}
@@ -99,52 +99,51 @@ proc run_magic {args} {
proc run_magic_drc {args} {
if { $::env(RUN_MAGIC_DRC) } {
increment_index
TIMER::timer_start
puts_info "Running Magic DRC..."
increment_index
TIMER::timer_start
puts_info "Running Magic DRC..."
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)"
set ::env(drc_prefix) $::env(finishing_reports)/drc
# Has to be maglef for DRC Checking
set ::env(MAGTYPE) maglef
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)"
set ::env(drc_prefix) $::env(finishing_reports)/drc
# Has to be maglef for DRC Checking
set ::env(MAGTYPE) maglef
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$::env(SCRIPTS_DIR)/magic/drc.tcl \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/drc.log]
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$::env(SCRIPTS_DIR)/magic/drc.tcl \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/drc.log]
puts_info "Converting Magic DRC Violations to Magic Readable Format..."
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_tcl.py \
-i $::env(drc_prefix).rpt \
-o $::env(drc_prefix).tcl
puts_info "Converting Magic DRC Violations to Magic Readable Format..."
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_tcl.py \
-i $::env(drc_prefix).rpt \
-o $::env(drc_prefix).tcl
puts_info "Converting Magic DRC Violations to Klayout XML Database..."
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_tr_drc.py \
-i $::env(drc_prefix).rpt \
-o $::env(drc_prefix).tr
puts_info "Converting Magic DRC Violations to Klayout XML Database..."
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_tr_drc.py \
-i $::env(drc_prefix).rpt \
-o $::env(drc_prefix).tr
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/tr_drc_to_klayout_drc.py \
-i $::env(drc_prefix).tr \
-o $::env(drc_prefix).klayout.xml \
--design-name $::env(DESIGN_NAME)
puts_info "Converting TritonRoute DRC Violations to Klayout XML Database..."
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/tr_drc_to_klayout_drc.py \
-i $::env(drc_prefix).tr \
-o $::env(drc_prefix).klayout.xml \
--design-name $::env(DESIGN_NAME)
if { $::env(MAGIC_CONVERT_DRC_TO_RDB) == 1 } {
puts_info "Converting DRC Violations to RDB Format..."
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_rdb.py \
--magic_drc_in $::env(drc_prefix).rpt \
--rdb_out $::env(drc_prefix).rdb
puts_info "Converted DRC Violations to RDB Format"
}
file copy -force $::env(MAGIC_MAGICRC) $::env(finishing_results)/.magicrc
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "drc - magic"
if { $::env(MAGIC_CONVERT_DRC_TO_RDB) == 1 } {
puts_info "Converting DRC Violations to RDB Format..."
try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/magic_drc_to_rdb.py \
--magic_drc_in $::env(drc_prefix).rpt \
--rdb_out $::env(drc_prefix).rdb
}
quit_on_magic_drc -log $::env(drc_prefix).tr
}
file copy -force $::env(MAGIC_MAGICRC) $::env(finishing_results)/.magicrc
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "drc - magic"
quit_on_magic_drc -log $::env(drc_prefix).tr
}
proc run_magic_spice_export {args} {
@@ -165,7 +164,7 @@ proc run_magic_spice_export {args} {
set ::env(EXT_NETLIST) $::env(finishing_results)/$::env(DESIGN_NAME).$extract_type
set magic_export $::env(finishing_tmpfiles)/$extract_type.tcl
set commands \
"
"
if { \[info exist ::env(MAGIC_EXT_USE_GDS)\] && \$::env(MAGIC_EXT_USE_GDS) } {
gds read \$::env(CURRENT_GDS)
} else {
@@ -196,42 +195,42 @@ ext2spice -o $::env(EXT_NETLIST) $::env(DESIGN_NAME).ext
feedback save $::env(magic_extract_prefix)$extract_type.feedback.txt
# exec cp $::env(DESIGN_NAME).spice $::env(finishing_results)/$::env(DESIGN_NAME).spice
"
set magic_export_file [open $magic_export w]
puts $magic_export_file $commands
close $magic_export_file
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)/"
# the following MAGTYPE has to be maglef for the purpose of LVS
# otherwise underlying device circuits would be considered
set ::env(MAGTYPE) maglef
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$magic_export \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/$extract_type.log]
set magic_export_file [open $magic_export w]
puts $magic_export_file $commands
close $magic_export_file
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)/"
# the following MAGTYPE has to be maglef for the purpose of LVS
# otherwise underlying device circuits would be considered
set ::env(MAGTYPE) maglef
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$magic_export \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/$extract_type.log]
if { $extract_type == "spice" } {
file copy -force $::env(finishing_results)/$::env(DESIGN_NAME).spice $::env(finishing_results)/$::env(DESIGN_NAME).lef.spice
}
file rename -force {*}[glob $::env(finishing_results)/*.ext] $::env(finishing_tmpfiles)
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "$extract_type extraction - magic"
if { $extract_type == "spice" } {
file copy -force $::env(finishing_results)/$::env(DESIGN_NAME).spice $::env(finishing_results)/$::env(DESIGN_NAME).lef.spice
}
file rename -force {*}[glob $::env(finishing_results)/*.ext] $::env(finishing_tmpfiles)
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "$extract_type extraction - magic"
quit_on_illegal_overlaps -log [index_file $::env(finishing_logs)/ext2$extract_type.feedback.txt]
quit_on_illegal_overlaps -log [index_file $::env(finishing_logs)/ext2$extract_type.feedback.txt]
}
proc export_magic_view {args} {
TIMER::timer_start
set options {
{-def required}
{-output required}
{-def required}
{-output required}
}
set flags {}
parse_key_args "export_magic_views" args arg_values $options flags_map $flags
set script_dir $::env(finishing_tmpfiles)/magic_mag_save.tcl
set commands \
"
"
lef read $::env(TECH_LEF)
if { \[info exist ::env(EXTRA_LEFS)\] } {
set lefs_in \$::env(EXTRA_LEFS)
@@ -243,19 +242,19 @@ def read $arg_values(-def)
save $arg_values(-output)
puts \"\[INFO\]: Done exporting $arg_values(-output)\"
"
set stream [open $script_dir w]
puts $stream $commands
close $stream
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)/"
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$script_dir \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/save_mag.log]
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "mag export - magic"
set stream [open $script_dir w]
puts $stream $commands
close $stream
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)/"
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$script_dir \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(finishing_logs)/save_mag.log]
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "mag export - magic"
}
proc run_magic_antenna_check {args} {
@@ -265,7 +264,7 @@ proc run_magic_antenna_check {args} {
set feedback_file [index_file $::env(finishing_logs)/ext2spice.antenna.feedback.txt]
set magic_export $::env(finishing_tmpfiles)/magic_antenna.tcl
set commands \
"
"
lef read \$::env(TECH_LEF)
if { \[info exist ::env(EXTRA_LEFS)\] } {
set lefs_in \$::env(EXTRA_LEFS)
@@ -296,30 +295,30 @@ if { ! \[file exists \$::env(DESIGN_NAME).ext\] } {
antennacheck debug
antennacheck
"
set magic_export_file [open $magic_export w]
puts $magic_export_file $commands
close $magic_export_file
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)/"
# the following MAGTYPE has to be mag; antennacheck needs to know
# about the underlying devices, layers, etc.
set ::env(MAGTYPE) mag
set magic_export_file [open $magic_export w]
puts $magic_export_file $commands
close $magic_export_file
set ::env(PDKPATH) "$::env(PDK_ROOT)/$::env(PDK)/"
# the following MAGTYPE has to be mag; antennacheck needs to know
# about the underlying devices, layers, etc.
set ::env(MAGTYPE) mag
set antenna_log [index_file $::env(finishing_logs)/antenna.log]
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$magic_export \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) $antenna_log
set antenna_log [index_file $::env(finishing_logs)/antenna.log]
try_catch magic \
-noconsole \
-dnull \
-rcfile $::env(MAGIC_MAGICRC) \
$magic_export \
</dev/null \
|& tee $::env(TERMINAL_OUTPUT) $antenna_log
# process the log
try_catch awk "/Cell:/ {print \$2}" $antenna_log > $antenna_log
# process the log
try_catch awk "/Cell:/ {print \$2}" $antenna_log > $antenna_log
set ::env(ANTENNA_CHECKER_LOG) $antenna_log
set ::env(ANTENNA_CHECKER_LOG) $antenna_log
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "antenna check - magic"
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "antenna check - magic"
}

View File

@@ -131,7 +131,6 @@ proc basic_macro_placement {args} {
}
proc run_placement {args} {
puts_info "Running Placement..."
# |----------------------------------------------------|
# |---------------- 3. PLACEMENT ------------------|
# |----------------------------------------------------|

View File

@@ -148,8 +148,6 @@ proc global_routing {args} {
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "global routing - $tool"
puts_info "Current Def is $::env(CURRENT_DEF)"
puts_info "Current Guide is $::env(CURRENT_GUIDE)"
}
proc detailed_routing_tritonroute {args} {
@@ -413,14 +411,12 @@ proc run_routing {args} {
file mkdir $sdf_path
file mkdir $arc_def_path
}
if { $::env(ECO_ENABLE) == 1 && $::env(ECO_ITER) != 0 } {
if { $::env(ECO_ENABLE) == 1 && $::env(ECO_ITER) != 0 } {
set ::env(CURRENT_DEF) $::env(eco_results)/def/eco_$::env(ECO_ITER).def
set ::env(CURRENT_NETLIST) $::env(eco_results)/net/eco_$::env(ECO_ITER).v
}
set ::env(ROUTING_CURRENT_DEF) $::env(CURRENT_DEF)
puts "Current DEF: $::env(CURRENT_DEF)"
puts "Routing Current DEF: $::env(ROUTING_CURRENT_DEF)"
# |----------------------------------------------------|
# |---------------- 5. ROUTING ----------------------|
# |----------------------------------------------------|

View File

@@ -165,11 +165,11 @@ proc verilog_elaborate {args} {
proc yosys_rewrite_verilog {filename} {
if { !$::env(LEC_ENABLE) } {
puts_info "Skipping Verilog rewrite (logic equivalency checks are disabled)..."
puts_verbose "Skipping Verilog rewrite (logic equivalency checks are disabled)..."
return
}
if { $::env(YOSYS_REWRITE_VERILOG) } {
puts_info "Skipping Verilog rewrite."
if { !$::env(YOSYS_REWRITE_VERILOG) } {
puts_verbose "Skipping Verilog rewrite."
return
}

View File

@@ -1,4 +1,4 @@
# Copyright 2020-2021 Efabless Corporation
# Copyright 2020-2022 Efabless Corporation
# ECO Flow Copyright 2021 The University of Michigan
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -200,7 +200,7 @@ proc run_openroad_script {args} {
set script_relative [relpath . $script]
puts_info "Executing OpenROAD with script '$script_relative'..."
puts_verbose "Executing OpenROAD with script '$script_relative'..."
set exit_code [catch {exec {*}$args |& tee $::env(TERMINAL_OUTPUT) $arg_values(-indexed_log)} error_msg]
@@ -241,8 +241,8 @@ proc run_openroad_script {args} {
}
proc increment_index {args} {
puts_info "Incremented step index to $::env(CURRENT_INDEX)."
set ::env(CURRENT_INDEX) [expr 1 + $::env(CURRENT_INDEX)]
puts "\[STEP $::env(CURRENT_INDEX)\]"
}
proc index_file {args} {
@@ -277,8 +277,8 @@ proc flow_fail {args} {
proc calc_total_runtime {args} {
## Calculate Total Runtime
if {[info exists ::env(timer_start)] && [info exists ::env(datetime)]} {
puts_info "Calculating Runtime From the Start..."
if {[info exists ::env(timer_start)] && [info exists ::env(START_TIME)]} {
puts_verbose "Calculating runtime..."
set ::env(timer_end) [clock seconds]
set options {
{-report optional}
@@ -345,6 +345,16 @@ proc puts_info {txt} {
}
}
proc puts_verbose {txt} {
if { $::env(OPENLANE_VERBOSE) } {
set message "\[INFO\]: $txt"
puts "[color_text 6 "$message"]"
if { [info exists ::env(RUN_DIR)] } {
exec echo $message >> $::env(RUN_DIR)/openlane.log
}
}
}
proc show_warnings {msg} {
if { [info exists ::env(RUN_DIR)] && [file exists $::env(RUN_DIR)/warnings.log] } {
puts_info $msg