Skip to content

Commit

Permalink
Rewrite the Report Generation Infrastructure (The-OpenROAD-Project#608)
Browse files Browse the repository at this point in the history
* `report.sh` was rewritten in python and folded into `report.py`
    * 'E404' reverted- sorry @kareefardi, a lot of code just expects a number.
    * `report.py` was pretty much rewritten, for that matter.
* wns/tns reporting fixed

---

Also significant fixes made with the help of @Manarabdelaty 
* s44 pdn fix: weird substitution issue that somehow only spuriously surfaces
* manual_macro_placement_test pdn fix: FP_PDN_CHECK_NODES set to 0 (Warnings treated as errors by OpenLane, LVS still passes so we are golden)
  • Loading branch information
donn authored Sep 16, 2021
1 parent 8580c24 commit 2faaeda
Show file tree
Hide file tree
Showing 16 changed files with 692 additions and 204 deletions.
16 changes: 10 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2020 Efabless Corporation
# Copyright 2020-2021 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -176,9 +176,8 @@ regression_test: regression
regression:
cd $(OPENLANE_DIR) && \
$(ENV_COMMAND) sh -c "\
python3 run_designs.py --delete\
python3 run_designs.py\
--defaultTestSet\
--tarList logs reports\
--htmlExtract\
--tag $(REGRESSION_TAG)\
--threads $(THREADS)\
Expand All @@ -197,7 +196,7 @@ extended_test_set: test_design_list
test_design_list:
cd $(OPENLANE_DIR) && \
$(ENV_COMMAND) sh -c "\
python3 run_designs.py --delete\
python3 run_designs.py\
--designs $(DESIGN_LIST)\
--tag $(DLTAG)\
--threads $(THREADS)\
Expand All @@ -213,6 +212,11 @@ test:
echo "Basic test passed" || \
echo "Basic test failed"

.PHONY: clean_runs
.PHONY: clean_all clean_runs clean_results
clean_all: clean_runs clean_results

clean_runs:
@rm -rf ./designs/*/runs && echo "Runs cleaned successfully." || echo "Failed to delete runs."
@rm -rf ./designs/*/runs && echo "Runs cleaned successfully." || echo "Failed to delete runs."

clean_results:
@{ find regression_results -mindepth 1 -maxdepth 1 -type d | grep -v benchmark | xargs rm -rf ; } && echo "Results cleaned successfully." || echo "Failed to delete results."
14 changes: 12 additions & 2 deletions designs/manual_macro_placement_test/config.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,19 @@
set ::env(DESIGN_NAME) manual_macro_placement_test

set ::env(FP_CORE_UTIL) 35

set ::env(FP_PDN_VOFFSET) 0
set ::env(FP_PDN_VPITCH) 30

set ::env(MACRO_PLACEMENT_CFG) $::env(OPENLANE_ROOT)/designs/$::env(DESIGN_NAME)/macro_placement.cfg
# OpenROAD reports unconnected nodes as a warning.
# OpenLane typically treats unconnected node warnings
# as a critical issue, and simply quits.
#
# We'll be leaving it up to the designer's discretion to
# enable/disable this: if LVS passes you're probably fine
# with this option being turned off.
set ::env(FP_PDN_CHECK_NODES) 0

set ::env(MACRO_PLACEMENT_CFG) $::env(DESIGN_DIR)/macro_placement.cfg


set ::env(PL_TARGET_DENSITY) 0.35
Expand All @@ -19,6 +27,8 @@ set ::env(CLOCK_TREE_SYNTH) 0

set ::env(DIODE_INSERTION_STRATEGY) 0

set ::env(GLB_RESIZER_TIMING_OPTIMIZATIONS) 0

# Change if needed
set ::env(VERILOG_FILES) [glob $::env(DESIGN_DIR)/src/*.v]
set ::env(EXTRA_LEFS) [glob $::env(DESIGN_DIR)/macros/lef/*.lef]
Expand Down
2 changes: 1 addition & 1 deletion designs/s44/config.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ set ::env(DESIGN_NAME) lut_s44

# Design config
set ::env(CLOCK_PERIOD) 30
set ::env(VERILOG_FILES) [glob $::env(OPENLANE_ROOT)/designs/s44/src/*.v]
set ::env(VERILOG_FILES) [glob $::env(DESIGN_DIR)/src/*.v]
set ::env(CLOCK_PORT) "config_clk"
set ::env(CLOCK_NET) $::env(CLOCK_PORT)
# Synthesis config
Expand Down
4 changes: 3 additions & 1 deletion designs/s44/pdn.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ set pdngen::global_connections {
}
}

pdngen::specify_grid stdcell {
set stdcell {
name grid
rails {
met1 {width $::env(FP_PDN_RAIL_WIDTH) pitch $::env(PLACE_SITE_HEIGHT) offset $::env(FP_PDN_RAIL_OFFSET)}
Expand All @@ -25,6 +25,8 @@ pdngen::specify_grid stdcell {
connect {{met1 met4}}
pins {met4}
}
pdngen::specify_grid stdcell [subst $stdcell]
set pdngen::voltage_domains { CORE { primary_power VPWR primary_ground VGND } }

set ::halo 0

Expand Down
6 changes: 3 additions & 3 deletions generate_reports.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2020 Efabless Corporation
# Copyright 2020-2021 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -28,7 +28,7 @@

parser.add_argument("--design", "-d", required=True, help="Design Path")

parser.add_argument("--design_name", "-dn", required=True, help="Design Name")
parser.add_argument("--design_name", "-n", required=True, help="Design Name")

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

Expand All @@ -43,7 +43,7 @@
)

parser.add_argument(
"--runtime_summary", "-rs", required=True, help="Output Runtime Summary Reports"
"--runtime_summary", "-s", required=True, help="Output Runtime Summary Reports"
)

args = parser.parse_args()
Expand Down
4 changes: 2 additions & 2 deletions run_designs.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ def run_design(designs_queue):
report = Report(design, tag, design_name, params).get_report()
report_log.info(report)

with open(run_path + "final_report.txt", "w") as report_file:
with open(run_path + "report.csv", "w") as report_file:
report_file.write(Report.get_header() + "," + ConfigHandler.get_header())
report_file.write("\n")
report_file.write(report)
Expand All @@ -356,7 +356,7 @@ def run_design(designs_queue):
design=design,
run_path=run_path,
)
subprocess.check_output(design_benchmark_comp_cmd.split())
subprocess.check_output(design_benchmark_comp_cmd.split(), stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
error_msg = e.stderr.decode(sys.getfilesystemencoding())
log.error(
Expand Down
15 changes: 9 additions & 6 deletions scripts/openroad/or_cts.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -80,21 +80,24 @@ if {[info exists ::env(CLOCK_PORT)]} {
read_liberty -max $::env(LIB_SLOWEST)
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
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
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
puts "min_max_report_end"
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
puts "check_report_end"

report_wns > $::env(cts_report_file_tag)_wns.rpt
report_tns > $::env(cts_report_file_tag)_tns.rpt
puts "clock_skew_report"
report_clock_skew > $::env(cts_report_file_tag)_clock_skew.rpt
puts "clock_skew_report_end"
puts "wns_report"
report_wns
puts "wns_report_end"
puts "tns_report"
report_tns
puts "tns_report_end"
}
} else {
puts "\[WARN\]: No CLOCK_PORT found. Skipping STA..."
Expand Down
15 changes: 9 additions & 6 deletions scripts/openroad/or_groute.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -86,18 +86,21 @@ if {[info exists ::env(CLOCK_PORT)]} {
set_wire_rc -layer $::env(WIRE_RC_LAYER)
estimate_parasitics -global_routing

puts "check_report"
report_checks -fields {capacitance slew input_pins nets fanout} -group_count 100 -slack_max -0.01 > $::env(fastroute_report_file_tag).rpt
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(fastroute_report_file_tag).timing.rpt
puts "timing_report_end"
puts "min_max_report"
report_checks -fields {capacitance slew input_pins nets fanout} -path_delay min_max > $::env(fastroute_report_file_tag).min_max.rpt
puts "min_max_report_end"
puts "check_report"
report_checks -fields {capacitance slew input_pins nets fanout} -group_count 100 -slack_max -0.01 > $::env(fastroute_report_file_tag).rpt
puts "check_report_end"

report_wns > $::env(fastroute_report_file_tag)_wns.rpt
report_tns > $::env(fastroute_report_file_tag)_tns.rpt
puts "wns_report"
report_wns
puts "wns_report_end"
puts "tns_report"
report_tns
puts "tns_report_end"

}
} else {
Expand Down
15 changes: 9 additions & 6 deletions scripts/openroad/or_replace.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,21 @@ if {[info exists ::env(CLOCK_PORT)]} {
set_wire_rc -layer $::env(WIRE_RC_LAYER)
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
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
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
puts "min_max_report_end"
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
puts "check_report_end"

report_wns > $::env(replaceio_report_file_tag)_wns.rpt
report_tns > $::env(replaceio_report_file_tag)_tns.rpt
puts "wns_report"
report_wns
puts "wns_report_end"
puts "tns_report"
report_tns
puts "tns_report_end"
}
} else {
puts "\[WARN\]: No CLOCK_PORT found. Skipping STA..."
Expand Down
50 changes: 38 additions & 12 deletions scripts/report/get_file_name.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2020 Efabless Corporation
# Copyright 2020-2021 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -14,19 +14,44 @@

# 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 argparse
import os
import sys
import argparse

def get_name(pathname, output_file, partial_match=False):
pathname = str(pathname)
output_file = str(output_file)

def get_name(run_path, output_file, include_only=False):
try:
neededfile=[]
if not include_only:
neededfile = sorted([(int(f.split('-',1)[0]),f.split('-',1)[1]) for f in os.listdir(run_path) if os.path.isfile(os.path.join(run_path, f)) and len(f.split('-',1)) > 1 and f.split('-',1)[1] == output_file], reverse=True)[0]
else:
neededfile = sorted([(int(f.split('-',1)[0]),f.split('-',1)[1]) for f in os.listdir(run_path) if os.path.isfile(os.path.join(run_path, f)) and len(f.split('-',1)) > 1 and str(output_file) in str(f.split('-',1)[1])], reverse=True)[0]
return str(run_path)+'/'+str(neededfile[0])+'-'+str(neededfile[1])
except Exception:
return str(run_path)+'/'+str(output_file)
candidates = []
for file in os.listdir(pathname):
if not os.path.isfile(os.path.join(pathname, file)):
continue # Directory

file_components = file.split("-", 1)

if len(file_components) <= 1:
continue

step_index, name = file_components
step_index = int(step_index)

if partial_match:
if output_file not in name:
continue
else:
if output_file != name:
continue

candidates.append((step_index, name))

candidates.sort(key= lambda x: x[0], reverse=True)

file = f"{candidates[0][0]}-{candidates[0][1]}"

return os.path.join(pathname, file)
except Exception as e:
return os.path.join(pathname, output_file)

if __name__ == "__main__":
parser = argparse.ArgumentParser(
Expand All @@ -38,7 +63,8 @@ def get_name(run_path, output_file, include_only=False):
parser.add_argument('--output_file', '-o', required=True,
help='File name to search for, i.e. 1.X 2.X 3.X, then the script will return <path>/3.X')

parser.add_argument('--include_only', '-io',action='store_true', default=False,
# This whole thing is a contrived way to say "partial match"
parser.add_argument('--include_only', '-I',action='store_true', default=False,
help="If enabled the matching is done for inclusion, i.e. the passed output_file is a string that is included in the file name to be matched. -o exam will return matches like: exam.txt and example.txl.")

args = parser.parse_args()
Expand Down
Loading

0 comments on commit 2faaeda

Please sign in to comment.