Sky130 Enhancements (#1240)

+ Add feature to match PDK names using Python `fnmatch`, allowing wildcards in `config.json` `pdk::` statements
~ open_pdks -> `e8294524e5f67c533c5d0c3afa0bcc5b2a5fa066`
- Remove "dependencies" field from tool_metadata.yml
- Removed sky130 version from tool_metadata.yml, tracked through the open_pdks "sky130.json" file instead
- Removed CVC scripts, placed in the PDK
This commit is contained in:
Mohamed Gaber
2022-07-29 16:03:10 +02:00
committed by GitHub
parent 4f63c8ca19
commit 4476a58407
28 changed files with 53 additions and 291 deletions

17
dependencies/tool.py vendored
View File

@@ -32,7 +32,6 @@ class Tool(object):
default_branch=None,
in_install=True,
in_container=True,
dependencies=[],
pdk=False,
):
self.name = name
@@ -42,7 +41,6 @@ class Tool(object):
self.default_branch = default_branch
self.in_install = in_install
self.in_container = in_container
self.dependencies = dependencies
self.pdk = pdk
def __repr__(self) -> str:
@@ -92,7 +90,6 @@ class Tool(object):
in_install=tool["in_install"]
if tool.get("in_install") is not None
else True,
dependencies=tool.get("dependencies") or [],
pdk=tool.get("pdk") or False,
)
return final_dict
@@ -142,20 +139,6 @@ def main():
print(tool.get_docker_tag(for_os=args.docker_tag_for_os, arch=args.docker_arch))
elif args.docker_args:
arg_list = tool.docker_args
# 1. Dependents
dependents = []
for dependent in Tool.by_name.values():
if tool.name in dependent.dependencies:
dependents.append(dependent)
for dependent in dependents:
arg_list += dependent.docker_args
# 2. Dependencies
for dependency_name in tool.dependencies:
dependency = Tool.by_name[dependency_name]
arg_list += dependency.docker_args
print(" ".join(arg_list), end="")
elif args.field:
field = tool.__dict__[args.field]

View File

@@ -54,30 +54,21 @@
- name: klayout
repo: https://github.com/KLayout/klayout
commit: 428d0fe8c941faece4eceebc54170cc04d916c03
build: ''
build: ""
in_install: false
- name: openroad_app
repo: https://github.com/The-OpenROAD-Project/OpenROAD
commit: e036ecfaca4bc0efe88a54085efcf0f562c48a6b
build: ''
build: ""
in_install: false
- name: git
repo: https://github.com/git/git
commit: e9d7761bb94f20acc98824275e317fa82436c25d
build: ''
build: ""
in_install: false
- name: open_pdks
repo: https://github.com/efabless/open_pdks
commit: 41c0908b47130d5675ff8484255b43f66463a7d6
build: ''
commit: e8294524e5f67c533c5d0c3afa0bcc5b2a5fa066
build: ""
in_install: false
pdk: true
dependencies:
- sky130
- magic
- name: sky130
repo: https://github.com/google/skywater-pdk
commit: f70d8ca46961ff92719d8870a18a076370b85f6c
build: ''
in_install: false
in_container: false

View File

@@ -5,7 +5,7 @@
"CLOCK_NET": "clk",
"FP_CORE_UTIL": 35,
"CLOCK_PERIOD": 17,
"pdk::sky130A": {
"pdk::sky130*": {
"SYNTH_MAX_FANOUT": 6
}
}

View File

@@ -5,7 +5,7 @@
"CLOCK_NET": "Clk",
"FP_SIZING": "absolute",
"DIE_AREA": "0 0 1000 1000",
"pdk::sky130A": {
"pdk::sky130*": {
"SYNTH_MAX_FANOUT": 6,
"CLOCK_PERIOD": 20,
"FP_CORE_UTIL": 18

View File

@@ -3,7 +3,7 @@
"VERILOG_FILES": "dir::src/PPU.v",
"CLOCK_PORT": "clk",
"CLOCK_NET": "clk",
"pdk::sky130A": {
"pdk::sky130*": {
"FP_CORE_UTIL": 20,
"SYNTH_MAX_FANOUT": 8,
"PL_TARGET_DENSITY": 0.25,

View File

@@ -4,7 +4,7 @@
"CLOCK_PORT": "clk",
"CLOCK_NET": "clk",
"FP_CORE_UTIL": 15,
"pdk::sky130A": {
"pdk::sky130*": {
"scl::sky130_fd_sc_hd": {
"SYNTH_MAX_FANOUT": 8,
"PL_TARGET_DENSITY": 0.25,

View File

@@ -5,7 +5,7 @@
"CLOCK_NET": "clk",
"DIODE_INSERTION_STRATEGY": 4,
"GLB_RESIZER_HOLD_MAX_BUFFER_PERCENT": 60,
"pdk::sky130A": {
"pdk::sky130*": {
"SYNTH_MAX_FANOUT": 6,
"FP_CORE_UTIL": 25,
"CLOCK_PERIOD": 21.28,

View File

@@ -5,7 +5,7 @@
"CLOCK_NET": "clk",
"FP_SIZING": "absolute",
"DIE_AREA": "0 0 1200 1200",
"pdk::sky130A": {
"pdk::sky130*": {
"FP_CORE_UTIL": 13,
"CLOCK_PERIOD": 65,
"scl::sky130_fd_sc_hd": {

View File

@@ -23,7 +23,7 @@
"RIGHT_MARGIN_MULT": 20
}
},
"pdk::sky130A": {
"pdk::sky130*": {
"scl::sky130_fd_sc_hd": {
"CLOCK_PERIOD": 10,
"FP_SIZING": "absolute",

View File

@@ -5,7 +5,7 @@
"CLOCK_NET": "clk",
"GLB_RESIZER_TIMING_OPTIMIZATIONS": true,
"CLOCK_PERIOD": 24,
"pdk::sky130A": {
"pdk::sky130*": {
"SYNTH_MAX_FANOUT": 6,
"FP_CORE_UTIL": 35,
"scl::sky130_fd_sc_ms": {

View File

@@ -4,7 +4,7 @@
"CLOCK_PORT": "clk",
"CLOCK_NET": "clk",
"GLB_RESIZER_TIMING_OPTIMIZATIONS": true,
"pdk::sky130A": {
"pdk::sky130*": {
"FP_CORE_UTIL": 20,
"SYNTH_MAX_FANOUT": 6,
"CLOCK_PERIOD": 36.73,

View File

@@ -8,7 +8,7 @@
"FP_PDN_VOFFSET": 7,
"FP_PDN_HOFFSET": 7,
"FP_PIN_ORDER_CFG": "dir::pin_order.cfg",
"pdk::sky130A": {
"pdk::sky130*": {
"FP_CORE_UTIL": 45,
"scl::sky130_fd_sc_hd": {
"CLOCK_PERIOD": 10

View File

@@ -4,7 +4,7 @@
"CLOCK_PORT": "clk_48",
"CLOCK_NET": "clk_48",
"FP_CORE_UTIL": 40,
"pdk::sky130A": {
"pdk::sky130*": {
"SYNTH_MAX_FANOUT": 6,
"CLOCK_PERIOD": 12.55,
"scl::sky130_fd_sc_hd": {

View File

@@ -3,7 +3,7 @@
"VERILOG_FILES": "dir::src/*.v",
"CLOCK_PORT": "clk_i",
"CLOCK_NET": "clk_i",
"pdk::sky130A": {
"pdk::sky130*": {
"CLOCK_PERIOD": 15.6,
"FP_CORE_UTIL": 45,
"SYNTH_MAX_FANOUT": 6,

View File

@@ -3,7 +3,7 @@
"VERILOG_FILES": "dir::src/*.v",
"CLOCK_PORT": "i_clk",
"CLOCK_NET": "i_clk",
"pdk::sky130A": {
"pdk::sky130*": {
"CLOCK_PERIOD": 18.86,
"SYNTH_MAX_FANOUT": 6,
"FP_CORE_UTIL": 40,

View File

@@ -5,7 +5,7 @@
"CLOCK_NET": "clk",
"FP_SIZING": "absolute",
"DIE_AREA": "0 0 700 700",
"pdk::sky130A": {
"pdk::sky130*": {
"CLOCK_PERIOD": 11.35,
"SYNTH_MAX_FANOUT": 6,
"scl::sky130_fd_sc_hd": {

View File

@@ -3,7 +3,7 @@
"VERILOG_FILES": "dir::src/zipdiv.v",
"CLOCK_PORT": "i_clk",
"CLOCK_NET": "i_clk",
"pdk::sky130A": {
"pdk::sky130*": {
"CLOCK_PERIOD": 20,
"SYNTH_MAX_FANOUT": 6,
"FP_CORE_UTIL": 40,

View File

@@ -82,7 +82,7 @@ $(TOOL_EXPORT_TARGETS): pull-% : FORCE
rm -rf ./tar/openlane
mkdir -p ./tar/openlane
for file in $(OPENLANE_SKELETON); do\
cp -r ../$$file ./tar/openlane/$$file ;\
$(PYTHON_BIN) ./utils.py copy-tree -i */runs/* ../$$file ./tar/openlane/$$file ;\
done
.PHONY: merge openlane

View File

@@ -1,104 +0,0 @@
# 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.
# WIP, probably will never make it to the image because it's taking forever to build
ARG RUN_BASE_IMAGE=
ARG BUILD_BASE_IMAGE=
FROM ${BUILD_BASE_IMAGE} AS builder
ARG SKY130_REPO
ARG SKY130_COMMIT
ENV PDK_ROOT /build/pdk
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8
ENV LC_CTYPE en_US.UTF-8
WORKDIR ${PDK_ROOT}
RUN git clone ${SKY130_REPO}
WORKDIR ${PDK_ROOT}/skywater-pdk
RUN git checkout main &&\
git submodule init &&\
git pull --no-recurse-submodules &&\
git checkout -qf ${SKY130_COMMIT}
RUN git submodule update --init libraries/sky130_fd_sc_hd/latest &&\
git submodule update --init libraries/sky130_fd_sc_hs/latest &&\
git submodule update --init libraries/sky130_fd_sc_hdll/latest &&\
git submodule update --init libraries/sky130_fd_sc_ms/latest &&\
git submodule update --init libraries/sky130_fd_sc_ls/latest &&\
git submodule update --init libraries/sky130_fd_sc_hvl/latest &&\
git submodule update --init libraries/sky130_fd_io/latest &&\
git submodule update --init libraries/sky130_fd_pr/latest
RUN python3 -m pip install -e scripts/python-skywater-pdk
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_hd/latest
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_hd/latest all
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_hd/latest all --ccsnoise
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_hdll/latest
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_hdll/latest all
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_hdll/latest all --ccsnoise
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_hs/latest
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_hs/latest all
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_hs/latest all --ccsnoise
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_hvl/latest
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_hvl/latest all
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_hvl/latest all --ccsnoise
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_ls/latest
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_ls/latest all
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_ls/latest all --ccsnoise
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_ms/latest all --leakage
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_ms/latest
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_ms/latest all
RUN python3 -m skywater_pdk.liberty libraries/sky130_fd_sc_ms/latest all --ccsnoise
ARG MAGIC_REPO
ARG MAGIC_COMMIT
WORKDIR /magic
RUN curl -L ${MAGIC_REPO}/tarball/${MAGIC_COMMIT} | tar -xzC . --strip-components=1 && \
./configure --prefix=/usr && \
make -j$(nproc) && \
make install
ARG OPEN_PDKS_REPO
ARG OPEN_PDKS_COMMIT
WORKDIR ${PDK_ROOT}
RUN git clone ${OPEN_PDKS_REPO}
WORKDIR ${PDK_ROOT}/open_pdks
RUN git checkout master &&\
git checkout -qf ${OPEN_PDKS_COMMIT}
RUN ./configure --enable-sky130-pdk=${PDK_ROOT}/skywater-pdk/libraries --enable-sram-sky130
WORKDIR ${PDK_ROOT}/open_pdks/sky130
RUN make alpha-repo xschem-repo sram-repo 2>&1 | tee /build/pdk_prereq.log
RUN make 2>&1 | tee /build/pdk.log
RUN make SHARED_PDKS_PATH=${PDK_ROOT} install
RUN printf "skywater-pdk ${SKY130_COMMIT}" > ${PDK_ROOT}/sky130A/SOURCES
RUN printf "magic ${MAGIC_COMMIT}" >> ${PDK_ROOT}/sky130A/SOURCES
RUN printf "open_pdks ${OPEN_PDKS_COMMIT}" >> ${PDK_ROOT}/sky130A/SOURCES
RUN rm -rf ${PDK_ROOT}/skywater-pdk
RUN rm -rf ${PDK_ROOT}/open_pdks
RUN tar -c /build | gzip -1 > /build.tar.gz
# ---
# pdk can't really be runnable, might as well shed a few layers
FROM centos:centos7 AS runnable
COPY --from=builder /build.tar.gz /build.tar.gz

View File

@@ -340,5 +340,24 @@ def fetch_submodules_from_tarballs(filter, repository, commit):
cli.add_command(fetch_submodules_from_tarballs)
@click.command()
@click.option("-i", "--ignoring", type=str, multiple=True)
@click.argument("sources", nargs=-1)
@click.argument("destination", nargs=1)
def copy_tree(ignoring, sources, destination):
patterns = shutil.ignore_patterns(*ignoring)
for source in list(sources):
if os.path.isfile(source):
shutil.copy(source, destination)
elif os.path.isdir(source):
shutil.copytree(source, destination, ignore=patterns)
else:
raise FileNotFoundError(source)
cli.add_command(copy_tree)
if __name__ == "__main__":
cli()

View File

@@ -80,6 +80,8 @@ The JSON configuration files support conditional execution based on PDK or stand
The value for this key would be a `dict` that is only evaluated if the PDK or SCL matches those in the key, i.e., for `pdk::sky130A` as shown above, this particular `dict` will be evaluated and its values used if and only if the PDK is set to `sky130A`, meanwhile with say, `asap7`, it will not be evaluated.
The match is evaluated using [`fnmatch`](https://docs.python.org/3.6/library/fnmatch.html), giving it limited wildcard support: meaning that `pdk::sky130*` would match both `sky130A` and `sky130B`.
Note that ***the order of declarations matter here***: as seen in the following example, despite a more specific value for a PDK existing, the unconditionally declared value later in the code would end up overwriting it:
```json

View File

@@ -19,6 +19,7 @@ import sys
import json
import glob
import click
import fnmatch
from enum import Enum
from io import TextIOWrapper
from typing import Any, Dict, List, Tuple, Union
@@ -262,12 +263,12 @@ def process_config_dict_recursive(config_in: Dict[str, Any], state: State):
if isinstance(value, dict):
withhold = True
if key.startswith(PDK_PREFIX):
pdk = key[len(PDK_PREFIX) :]
if pdk == state.vars[PDK_VAR]:
pdk_match = key[len(PDK_PREFIX) :]
if fnmatch.fnmatch(state.vars[PDK_VAR], pdk_match):
process_config_dict_recursive(value, state)
elif key.startswith(SCL_PREFIX):
scl = key[len(SCL_PREFIX) :]
if scl == state.vars[SCL_VAR]:
scl_match = key[len(SCL_PREFIX) :]
if fnmatch.fnmatch(state.vars[SCL_VAR], scl_match):
process_config_dict_recursive(value, state)
else:
raise InvalidConfig(

View File

@@ -1,16 +0,0 @@
/Black-box entry subcircuit/ { # remove black-box defintions
while ( $1 != ".ends" ) {
getline;
}
getline;
}
/^\*/ { # remove comments
next;
}
/^.ENDS .*/ { # remove name from ends lines
print $1;
next;
}
{
print $0;
}

View File

@@ -1,53 +0,0 @@
MN nfet_01v8 Vth=0.2 Vgs=1.8 Vds=1.8
MP pfet_01v8_hvt Vth=-0.2 Vgs=1.8 Vds=1.8
R short model=switch_on
D sky130_fd_pr__diode_pw2nd_05v5
D sky130_fd_pr__diode_pw2nd_11v0
D sky130_fd_pr__diode_pd2nw_05v5
D sky130_fd_pr__model__parasitic__diode_ps2dn
D sky130_fd_pr__model__parasitic__diode_ps2nw
D sky130_fd_pr__model__parasitic__diode_pw2dn
D condiode
#R sky130_fd_pr__res_generic_m1 R=l/w*0.125
#R sky130_fd_pr__res_generic_m2 R=l/w*0.125
#R sky130_fd_pr__res_generic_m3 R=l/w*0.047
#R sky130_fd_pr__res_generic_m4 R=l/w*0.047
#R sky130_fd_pr__res_generic_nd R=l/w*0.029
R sky130_fd_pr__res_generic_m1 R=l/w
R sky130_fd_pr__res_generic_m2 R=l/w
R sky130_fd_pr__res_generic_m3 R=l/w
R sky130_fd_pr__res_generic_m4 R=l/w
R sky130_fd_pr__res_generic_m5 R=l/w
R sky130_fd_pr__res_generic_nd R=l/w*120
R sky130_fd_pr__res_generic_nd__hv R=l/w*114
R sky130_fd_pr__res_generic_pd__hv R=l/w*191
R sky130_fd_pr__res_generic_po R=l/w*48
R sky130_fd_pr__res_xhigh_po R=l/w*2000
R sky130_fd_pr__res_high_po R=l/w*2000
MN sky130_fd_pr__nfet_01v8 Vth=0.2 Vgs=1.8 Vds=1.8
MN sky130_fd_pr__nfet_01v8_lvt Vth=0.1 Vgs=1.8 Vds=1.8
MN sky130_fd_pr__special_nfet_latch Vth=0.2 Vgs=1.8 Vds=1.8
MN sky130_fd_pr__nfet_03v3_nvt Vth=0.2 Vgs=3.3 Vds=3.3
MN sky130_fd_pr__esd_nfet_g5v0d10v5 Vth=0.2
MN sky130_fd_pr__nfet_05v0_nvt Vth=0.2
MN sky130_fd_pr__nfet_g5v0d10v5 Vth=0.2
MN sky130_fd_bs_flash__special_sonosfet_star Vth=0.2
MP sky130_fd_pr__pfet_01v8 Vth=-0.2 Vgs=1.8 Vds=1.8
MP sky130_fd_pr__pfet_01v8_lvt Vth=-0.1 Vgs=1.8 Vds=1.8
MP sky130_fd_pr__pfet_01v8_hvt Vth=-0.3 Vgs=1.8 Vds=1.8
MP sky130_fd_pr__special_pfet_pass Vth=-0.2 Vgs=1.8 Vds=1.8
MP sky130_fd_pr__pfet_g5v0d10v5 Vth=-0.2
C sky130_fd_pr__cap_mim_m3_1
C sky130_fd_pr__cap_mim_m3_2
C sky130_fd_pr__cap_var
Q sky130_fd_pr__pnp_05v5

View File

@@ -1,36 +0,0 @@
CVC_MODEL_FILE = $SCRIPTS_DIR/cvc/$PDK/cvc.$PDK.models
CVC_TOP = $DESIGN_NAME
CVC_MODE = $CVC_TOP
CVC_NETLIST = $signoff_tmpfiles/$DESIGN_NAME.cdl
CVC_POWER_FILE = $signoff_tmpfiles/$CVC_TOP.power
CVC_REPORT_FILE = $signoff_reports/$CVC_TOP.rpt
CVC_FUSE_FILE = ''
CVC_REPORT_TITLE = 'CVC $CVC_TOP'
CVC_CIRCUIT_ERROR_LIMIT = '100'
CVC_SEARCH_LIMIT = '100'
CVC_LEAK_LIMIT = '0.0002'
CVC_SOI = 'false'
CVC_SCRC = 'false'
CVC_VTH_GATES = 'false'
CVC_MIN_VTH_GATES = 'false'
CVC_IGNORE_VTH_FLOATING = 'false'
CVC_IGNORE_NO_LEAK_FLOATING = 'false'
CVC_LEAK_OVERVOLTAGE = 'true'
CVC_LOGIC_DIODES = 'false'
CVC_ANALOG_GATES = 'true'
CVC_BACKUP_RESULTS = 'false'
CVC_MOS_DIODE_ERROR_THRESHOLD = '0'
CVC_SHORT_ERROR_THRESHOLD = '0'
CVC_BIAS_ERROR_THRESHOLD = '0'
CVC_FORWARD_ERROR_THRESHOLD = '0'
CVC_FLOATING_ERROR_THRESHOLD = '0'
CVC_GATE_ERROR_THRESHOLD = '0'
CVC_LEAK?_ERROR_THRESHOLD = '0'
CVC_EXPECTED_ERROR_THRESHOLD = '0'
CVC_OVERVOLTAGE_ERROR_THRESHOLD = '0'
CVC_PARALLEL_CIRCUIT_PORT_LIMIT = '0'
CVC_CELL_ERROR_LIMIT_FILE = ''
CVC_CELL_CHECKSUM_FILE = ''
CVC_LARGE_CIRCUIT_SIZE = '10000000'
CVC_NET_CHECK_FILE = ''

View File

@@ -1,15 +0,0 @@
BEGIN { # Print power and standard_input definitions
printf "%s power 1.8\n", vdd;
printf "%s power 0.0\n", gnd;
printf "#define std_input min@%s max@%s\n", gnd, vdd;
}
$1 == "input" { # Print input nets
gsub(/;/, "");
if ( $2 == vdd || $2 == gnd ) { # ignore power nets
next;
}
if ( NF == 3 ) { # print buses as net[range]
$2 = $3 $2;
}
print $2, "input std_input";
}

View File

@@ -462,14 +462,6 @@ proc prep {args} {
source $pdk_config
source $scl_config
## Hack: Update CELL_PAD in OpenLane for now while we wait for Open_PDKs to be usable
if { [info exists ::env(CELL_PAD)] } {
puts_verbose "\[HACK\] Updating PDK cell padding values..."
set ::env(GPL_CELL_PADDING) {0}
set ::env(DPL_CELL_PADDING) $::env(CELL_PAD)
unset ::env(CELL_PAD)
}
# Re-source/re-override to make sure it overrides any configurations from the previous two sources
source $run_path/config_in.tcl
if { [info exists arg_values(-override_env)] } {

View File

@@ -19,6 +19,11 @@ proc run_lef_cvc {args} {
return
}
if { ![info exists ::env(CVC_SCRIPTS_DIR)] } {
puts_warn "This PDK does not support cvc, skipping..."
return
}
if { [info exists ::env(EXTRA_LEFS)] } {
puts_info "Your design contains macros, which is not supported by the current integration of CVC. So CVC won't run, however CVC is just a check so it's not critical to your design."
return
@@ -29,13 +34,6 @@ proc run_lef_cvc {args} {
return
}
set ::env(CVC_SCRIPTS_DIR) $::env(SCRIPTS_DIR)/cvc/$::env(PDK)
if { ![file exist $::env(CVC_SCRIPTS_DIR)/cvcrc.$::env(PDK)] } {
puts_warn "This PDK does not support cvc, skipping..."
return
}
set lef_spice $::env(signoff_results)/$::env(DESIGN_NAME).lef.spice
if { ![file exist $lef_spice] } {
puts_warn "No lefspice found, skipping CVC..."
@@ -69,7 +67,7 @@ proc run_lef_cvc {args} {
> $::env(signoff_tmpfiles)/$::env(DESIGN_NAME).cdl
# The main event
try_catch cvc $::env(CVC_SCRIPTS_DIR)/cvcrc.$::env(PDK) \
try_catch cvc $::env(CVC_SCRIPTS_DIR)/cvcrc \
|& tee $::env(TERMINAL_OUTPUT) [index_file $::env(signoff_logs)/erc_screen.log]
TIMER::timer_stop