Skip to content

Commit

Permalink
Quit on timing violations at the typical corner (The-OpenROAD-Project…
Browse files Browse the repository at this point in the history
…#659)

* Report clock skew in or_sta.tcl

* Error on timing violations at the typical corner and warn on timing violations at the typical corner

* Reset or_sta.tcl

* Timing Report Fixes + Only warnings on slew by default

~ Tweaks to PDK version verification (broken on some platforms)
~ Resizer default value changes
~ Tweaks to report generation, report.sh removed
~ Run folders now use a full timestamp
- Empty timing reports no longer generated

* Warn on max slew violations

* Fix odd 'exceptional failure' issue

Co-authored-by: Mohamed Gaber <me@donn.website>
  • Loading branch information
Manarabdelaty and donn authored Oct 21, 2021
1 parent 23b9177 commit 4e158a7
Show file tree
Hide file tree
Showing 21 changed files with 205 additions and 562 deletions.
1 change: 0 additions & 1 deletion configuration/checkers.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ set ::env(CHECK_UNMAPPED_CELLS) 1
# Static timing analysis
set ::env(QUIT_ON_TIMING_VIOLATIONS) 1
set ::env(QUIT_ON_HOLD_SETUP_VIOLATIONS) 1
set ::env(QUIT_ON_SLEW_VIOLATIONS) 1
set ::env(QUIT_ON_NEGATIVE_WNS) 1

# Floor Planning
Expand Down
4 changes: 2 additions & 2 deletions configuration/placement.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ set ::env(PL_RESIZER_BUFFER_INPUT_PORTS) 1
set ::env(PL_RESIZER_BUFFER_OUTPUT_PORTS) 1
set ::env(PL_RESIZER_MAX_SLEW_MARGIN) 1
set ::env(PL_RESIZER_MAX_CAP_MARGIN) 10
set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.2
set ::env(PL_RESIZER_SETUP_SLACK_MARGIN) 0.2
set ::env(PL_RESIZER_HOLD_SLACK_MARGIN) 0.1
set ::env(PL_RESIZER_SETUP_SLACK_MARGIN) 0.05
set ::env(PL_RESIZER_HOLD_MAX_BUFFER_PERCENT) 50
set ::env(PL_RESIZER_SETUP_MAX_BUFFER_PERCENT) 50
32 changes: 20 additions & 12 deletions dependencies/verify_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ def verify_versions(no_tools: bool = False, report_file=sys.stderr):
manifest_dict = { element['name']: element for element in manifest }
mismatches = False

manifest_names_by_SOURCES_name = {
"open_pdks": "open_pdks",
"skywater": "sky130"
}
pdk_manifest_names = set(manifest_names_by_SOURCES_name.values())

try:
# 2. Check if the Sky130 PDK is compatible with Flow Scripts
if not os.getenv("PDK_ROOT"):
Expand All @@ -60,11 +66,6 @@ def verify_versions(no_tools: bool = False, report_file=sys.stderr):
except FileNotFoundError:
raise Exception("Could not find SOURCES file for the installed sky130A PDK.")

manifest_names = {
"open_pdks": "open_pdks",
"skywater": "sky130"
}

sources_str = sources_str.strip()

sources_lines = list(filter(lambda x: x, sources_str.split("\n")))
Expand All @@ -75,12 +76,14 @@ def verify_versions(no_tools: bool = False, report_file=sys.stderr):
# Format:
# -ne {tool}
# {commit}
sources_lines = []

entries = len(sources_lines) // 2
name_rx = re.compile(r"\-ne\s+([\w\-]+)")

new_sources_lines = []

for entry in range(entries):
print(entry * 2, entry * 2 + 1)
name_line = sources_lines[entry * 2]
commit_line = sources_lines[entry * 2 + 1]

Expand All @@ -91,18 +94,19 @@ def verify_versions(no_tools: bool = False, report_file=sys.stderr):
name = name_data[1]
commit = commit_line.strip()

sources_lines.append(f"{name} {commit}")

new_sources_lines.append(f"{name} {commit}")

sources_lines = new_sources_lines

name_rx = re.compile(r"([\w\-]+)\s+(\w+)")
for line in sources_lines:
match = name_rx.match(line)
if match is None:
raise Exception(f"Malformed sky130A SOURCES file: {line} did not match regex.")

name = match[1]
commit = match[2]

manifest_name = manifest_names.get(name)
manifest_name = manifest_names_by_SOURCES_name.get(name)
if manifest_name is None:
continue
manifest_commit = manifest_dict[manifest_name]["commit"]
Expand All @@ -111,6 +115,8 @@ def verify_versions(no_tools: bool = False, report_file=sys.stderr):
mismatches = True
print(f"The version of {manifest_name} installed does not match the one required by the OpenLane flow scripts (installed: {commit}, expected: {manifest_commit})", file=report_file)
print(f"You may want to re-install the PDK by invoking `make pdk`.", file=report_file)

pdk_manifest_names.add(manifest_name)
except Exception as e:
print("Failed to compare PDKS", file=report_file)
print(e, file=report_file)
Expand Down Expand Up @@ -142,8 +148,8 @@ def verify_versions(no_tools: bool = False, report_file=sys.stderr):
except FileNotFoundError:
raise Exception("Container manifest not found. What this likely means is that the container is severely out of date.")

tool_set_flow = set([element['name'] for element in manifest])
tool_set_container = set([element['name'] for element in environment_manifest])
tool_set_flow = set([element['name'] for element in manifest]) - pdk_manifest_names
tool_set_container = set([element['name'] for element in environment_manifest]) - pdk_manifest_names

unmatched_tools_flow = tool_set_flow - tool_set_container
for tool in unmatched_tools_flow:
Expand All @@ -161,6 +167,8 @@ def verify_versions(no_tools: bool = False, report_file=sys.stderr):
mismatches = True

for tool in environment_manifest:
if tool["name"] in pdk_manifest_names:
continue # PDK Stuff Already Checked
flow_script_counterpart = manifest_dict.get(tool["name"])
if flow_script_counterpart is None:
continue
Expand Down
4 changes: 0 additions & 4 deletions designs/APU/config.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ set ::env(CLOCK_NET) $::env(CLOCK_PORT)

set ::env(FP_PDN_IRDROP) 1

# Disable timing checks temporarily till the design configurations are updated
# to tackle the timing violations
set ::env(QUIT_ON_TIMING_VIOLATIONS) 0

set filename $::env(DESIGN_DIR)/$::env(PDK)_$::env(STD_CELL_LIBRARY)_config.tcl
if { [file exists $filename] == 1} {
source $filename
Expand Down
2 changes: 0 additions & 2 deletions designs/des/config.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ set ::env(VERILOG_FILES) [glob ./designs/des/src/*.v]
set ::env(CLOCK_PERIOD) "2.000"
set ::env(CLOCK_PORT) "clk"



set ::env(CLOCK_NET) $::env(CLOCK_PORT)

set filename $::env(OPENLANE_ROOT)/designs/$::env(DESIGN_NAME)/$::env(PDK)_$::env(STD_CELL_LIBRARY)_config.tcl
Expand Down
4 changes: 0 additions & 4 deletions designs/usb_cdc_core/config.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ set ::env(CLOCK_PORT) "clk_i"

set ::env(CLOCK_NET) $::env(CLOCK_PORT)

# Disable timing checks temporarily till the design configurations are updated
# to tackle the timing violations
set ::env(QUIT_ON_TIMING_VIOLATIONS) 0

set filename $::env(OPENLANE_ROOT)/designs/$::env(DESIGN_NAME)/$::env(PDK)_$::env(STD_CELL_LIBRARY)_config.tcl
if { [file exists $filename] == 1} {
source $filename
Expand Down
4 changes: 0 additions & 4 deletions designs/wbqspiflash/config.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ set ::env(CLOCK_PORT) "i_clk"

set ::env(CLOCK_NET) $::env(CLOCK_PORT)

# Disable timing checks temporarily till the design configurations are updated
# to tackle the timing violations
set ::env(QUIT_ON_TIMING_VIOLATIONS) 0

set filename $::env(OPENLANE_ROOT)/designs/$::env(DESIGN_NAME)/$::env(PDK)_$::env(STD_CELL_LIBRARY)_config.tcl
if { [file exists $filename] == 1} {
source $filename
Expand Down
4 changes: 0 additions & 4 deletions designs/xtea/config.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ set ::env(CLOCK_PORT) "clock"
set ::env(CLOCK_NET) "clock"
set ::env(CLOCK_NET) $::env(CLOCK_PORT)

# Disable timing checks temporarily till the design configurations are updated
# to tackle the timing violations
set ::env(QUIT_ON_TIMING_VIOLATIONS) 0

set filename $::env(OPENLANE_ROOT)/designs/$::env(DESIGN_NAME)/$::env(PDK)_$::env(STD_CELL_LIBRARY)_config.tcl
if { [file exists $filename] == 1} {
source $filename
Expand Down
28 changes: 13 additions & 15 deletions scripts/compare_regression_design.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse
import subprocess
import csv
import pandas as pd
import os
import argparse

parser = argparse.ArgumentParser(
description="compare one design from a regression result to a benchmark result")
Expand Down Expand Up @@ -91,8 +88,8 @@ def parseCSV(csv_file):
return design_out

def criticalMistmatch(benchmark, regression_result):
if len(benchmark) == 0 or len(regression_result) == 0:
return False, "Nothing to compare with"
if len(benchmark):
return False, "The design is not benchmarked"
for stat in critical_statistics:
if compare_vals(benchmark[stat],regression_result[stat],stat):
continue
Expand All @@ -103,13 +100,14 @@ def criticalMistmatch(benchmark, regression_result):
return True, "The results of " +stat+" mismatched with the benchmark"
return False, "The test passed"

def compareStatus(benchmark,regression_result):
if len(benchmark) == 0 or len(regression_result) == 0:
return False, "Nothing to compare with"
elif "fail" in str(benchmark["flow_status"]):
return False, "The test passed"
def compareStatus(benchmark, regression_result):
if len(benchmark) == 0:
return False, "The design is not benchmarked"
elif "fail" in str(regression_result["flow_status"]):
return True, "The flow didn't complete for the user design after magic drc."
if "fail" in str(benchmark["flow_status"]):
return False, "The OpenLane flow failed, but the benchmark never saw it succeed"
else:
return True, "The OpenLane flow failed outright, check the logs"
else:
return False, "The test passed"

Expand All @@ -124,17 +122,17 @@ def missingResultingFiles(design):
benchmark = parseCSV(benchmark_file)
regression_result = parseCSV(regression_results_file)

testFail, reasonWhy = criticalMistmatch(benchmark,regression_result)
testFail, reasonWhy = compareStatus(benchmark, regression_result)

report = str(design)
if testFail:
report += ",FAILED,"+reasonWhy+"\n"
else:
testFail, reasonWhy = missingResultingFiles(regression_result)
testFail, reasonWhy = criticalMistmatch(benchmark, regression_result)
if testFail:
report += ",FAILED,"+reasonWhy+"\n"
else:
testFail, reasonWhy = compareStatus(benchmark,regression_result)
testFail, reasonWhy = missingResultingFiles(regression_result)
if testFail:
report += ",FAILED,"+reasonWhy+"\n"
else:
Expand Down
6 changes: 3 additions & 3 deletions scripts/generate_reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,18 @@

parser.add_argument("--tag", "-t", required=True, help="Run Tag")

parser.add_argument("--run_path", "-r", default=None, help="Run Path")
parser.add_argument("--run_path", "-r", default=None, help="Run Path [Optional, otherwise derived from tag")

parser.add_argument(
"--output_file", "-o", required=True, help="Output Final Summary Report"
)

parser.add_argument(
"--man_report", "-m", required=True, help="Output Manufacturability Reports"
"--man_report", "-m", default="/dev/null", help="Output Manufacturability Reports"
)

parser.add_argument(
"--runtime_summary", "-s", required=True, help="Output Runtime Summary Reports"
"--runtime_summary", "-s", default="/dev/null", help="Output Runtime Summary Reports"
)

args = parser.parse_args()
Expand Down
9 changes: 4 additions & 5 deletions scripts/io_place.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
...
"""

import os
import re
import sys
import argparse
Expand Down Expand Up @@ -249,11 +250,9 @@ def bus_keys(enum):
pin_name = bterm.getName()
if re.match(regex, pin_name) is not None:
if bterm in bterm_regex_map:
print("Warning: Multiple regexes matched", pin_name,
print("Error: Multiple regexes matched", pin_name,
". Those are", bterm_regex_map[bterm], "and", regex)
print("Only the first one is taken into consideration.")
continue
# sys.exit(1)
sys.exit(os.EX_DATA)
bterm_regex_map[bterm] = regex
pin_placement[side].append(bterm) # to maintain the order

Expand Down Expand Up @@ -338,5 +337,5 @@ def bus_keys(enum):
rect.moveTo(x, slot-H_WIDTH//2)
odb.dbBox_create(pin_bpin, H_LAYER, *rect.ll(), *rect.ur())

print("Writing", output_def_file_name)
print(f"Writing {output_def_file_name}...",)
odb.write_def(block_top, output_def_file_name)
8 changes: 4 additions & 4 deletions scripts/openroad/or_cts.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,16 @@ if {[info exists ::env(CLOCK_PORT)]} {
read_liberty -min $::env(LIB_FASTEST)

puts "check_report"
report_checks -fields {capacitance slew input_pins nets fanout} -group_count 100 -slack_max -0.01 > $::env(cts_report_file_tag).rpt
report_checks -fields {capacitance slew input_pins nets fanout} -group_count 100 -slack_max -0.01
puts "check_report_end"
puts "timing_report"
report_checks -fields {capacitance slew input_pins nets fanout} -unique -slack_max -0.0 -group_count 100 > $::env(cts_report_file_tag).timing.rpt
report_checks -fields {capacitance slew input_pins nets fanout} -unique -slack_max -0.0 -group_count 100
puts "timing_report_end"
puts "min_max_report"
report_checks -fields {capacitance slew input_pins nets fanout} -path_delay min_max > $::env(cts_report_file_tag).min_max.rpt
report_checks -fields {capacitance slew input_pins nets fanout} -path_delay min_max
puts "min_max_report_end"
puts "clock_skew_report"
report_clock_skew > $::env(cts_report_file_tag)_clock_skew.rpt
report_clock_skew
puts "clock_skew_report_end"
puts "wns_report"
report_wns
Expand Down
6 changes: 3 additions & 3 deletions scripts/openroad/or_replace.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ if {[info exists ::env(CLOCK_PORT)]} {
estimate_parasitics -placement

puts "check_report"
report_checks -fields {capacitance slew input_pins nets fanout} -group_count 100 -slack_max -0.01 > $::env(replaceio_report_file_tag).rpt
report_checks -fields {capacitance slew input_pins nets fanout} -group_count 100 -slack_max -0.01
puts "check_report_end"
puts "timing_report"
report_checks -fields {capacitance slew input_pins nets fanout} -unique -slack_max -0.0 -group_count 100 > $::env(replaceio_report_file_tag).timing.rpt
report_checks -fields {capacitance slew input_pins nets fanout} -unique -slack_max -0.0 -group_count 100
puts "timing_report_end"
puts "min_max_report"
report_checks -fields {capacitance slew input_pins nets fanout} -path_delay min_max > $::env(replaceio_report_file_tag).min_max.rpt
report_checks -fields {capacitance slew input_pins nets fanout} -path_delay min_max
puts "min_max_report_end"
puts "wns_report"
report_wns
Expand Down
17 changes: 11 additions & 6 deletions scripts/openroad/or_sta.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ if {[catch {read_lef $::env(MERGED_LEF_UNPADDED)} errmsg]} {

set_cmd_units -time ns -capacitance pF -current mA -voltage V -resistance kOhm -distance um

read_liberty -min $::env(LIB_FASTEST)
read_liberty -max $::env(LIB_SLOWEST)
if $::env(USE_TYPICAL_CORNER) {
read_liberty $::env(LIB_SYNTH_COMPLETE)
} else {
read_liberty -min $::env(LIB_FASTEST)
read_liberty -max $::env(LIB_SLOWEST)
}

read_verilog $::env(CURRENT_NETLIST)
link_design $::env(DESIGN_NAME)
if { [info exists ::env(CURRENT_SPEF)] } {
Expand All @@ -30,16 +35,16 @@ if { [info exists ::env(CURRENT_SPEF)] } {
read_sdc -echo $::env(CURRENT_SDC)

puts "check_report"
report_checks -fields {capacitance slew input_pins nets fanout} -group_count 1000 -slack_max -0.01 > $::env(opensta_report_file_tag).rpt
report_checks -fields {capacitance slew input_pins nets fanout} -group_count 1000 -slack_max -0.01
puts "check_report_end"
puts "timing_report"
report_checks -fields {capacitance slew input_pins nets fanout} -unique -slack_max -0.0 -group_count 1000 > $::env(opensta_report_file_tag).timing.rpt
report_checks -fields {capacitance slew input_pins nets fanout} -unique -slack_max -0.0 -group_count 1000
puts "timing_report_end"
puts "min_max_report"
report_checks -fields {capacitance slew input_pins nets fanout} -path_delay min_max -group_count 1000 > $::env(opensta_report_file_tag).min_max.rpt
report_checks -fields {capacitance slew input_pins nets fanout} -path_delay min_max -group_count 1000
puts "min_max_report_end"
puts "check_slew"
report_check_types -max_slew -max_capacitance -max_fanout -violators > $::env(opensta_report_file_tag).slew.rpt
report_check_types -max_slew -max_capacitance -max_fanout -violators
puts "check_slew_end"
puts "wns_report"
report_wns
Expand Down
2 changes: 0 additions & 2 deletions scripts/report/get_file_name.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# The only purpose of this file is to create a wrapper around report.py and config.py and make them usable by flow.tcl

import os
import sys
import argparse
Expand Down
Loading

0 comments on commit 4e158a7

Please sign in to comment.