Hierarchical Static Timing Analysis (#1675)

\+ Add `EXTRA_SPEFS`
\+ Use `VERILOG_FILES_BLACKBOX` in sta. Allow skipping a file by adding a comment `/// sta-blackbox`
\+ Detect blackboxed modules in typical-corner STA during sign off and warn the user about it
\+ Add `run_sta_script` used in multicorner sta
\+ Support sta in `or_issue.py`
\+ Support sta in `run_tcl_script`
\+ Check if regex defined in `FP_PDN_MACRO_HOOKS` has a match. Fixes https://github.com/The-OpenROAD-Project/OpenLane/issues/1599
\~ Wrap `set_global_connections` around a flag since it is not supported by opensta
\~ Run multicorner sta using standalone sta application for hierarchical
sta support
\~ Move `sta_multi_corner.tcl` to `scripts/openroad/sta/multi_corner.tcl`
\~ Don't delete target directory of `-save` for multicorner spef files
\~ Merge multi_corner sta and single corner into one script.
\~ Split `RUN_STANDALONE` embedded inside openroad steps, which calls sta after, to another sta step run after said openroad step
\- Remove `report_design_area` in `multi_corner.tcl` since it is not supported by standalone OpenSTA 
\- Remove `scripts/openroad/sta.tcl`
This commit is contained in:
Kareem Farid
2023-04-05 23:58:56 +02:00
committed by GitHub
parent e8650c2b2b
commit 8a4b1e7f06
25 changed files with 236 additions and 298 deletions

View File

@@ -35,6 +35,7 @@
*-------------------------------------------------------------
*/
/// sta-blackbox
module user_proj_example #(
parameter BITS = 32
)(

View File

@@ -13,6 +13,7 @@
// limitations under the License.
// SPDX-License-Identifier: Apache-2.0
/// sta-blackbox
`default_nettype none
/*
*-------------------------------------------------------------

View File

@@ -34,7 +34,7 @@ These variables are optional that can be specified in the design configuration f
|Variable|Description|
|-|-|
| `VERILOG_FILES_BLACKBOX` | Black-boxed, Verilog files where the implementation is ignored. Useful for pre-hardened macros you incorporate into your design, used during synthesis. |
| `VERILOG_FILES_BLACKBOX` | Black-boxed, Verilog files where the implementation is ignored. Useful for pre-hardened macros you incorporate into your design, used during synthesis and opensta. `/// sta-blackbox` can be added to a file in order skip that file while doing sta. This will blackbox all the modules definied inside that file. It is recommended to provide a gatelevel netlist whenever possible to do full sta. |
| `EXTRA_LEFS` | Specifies LEF files of pre-hardened macros used in the current design, used in placement and routing. |
| `EXTRA_LIBS` | Specifies LIB files of pre-hardened macros used in the current design, used during timing analysis. (Optional) |
| `EXTRA_GDS_FILES` | Specifies GDS files of pre-hardened macros used in the current design, used during tape-out. |
@@ -71,6 +71,7 @@ These variables are optional that can be specified in the design configuration f
| Variable | Description |
|-|-|
| `EXTRA_SPEFS` | Specifies min, nom, max spef files for modules(s). Variable should be provided as a json/tcl list or a space delimited tcl string. Note that a module name is provided not an instance name. A module may have multiple instances. Each module must have define 3 files, one for each corner. For example: `module1 min1 nom1 max1 module2 min2 nom2 max2`. A file can be used multiple time in case of absence of other corner files. For example: `module nom nom nom`. In this case, the nom file will be used in all corners of sta. At all times a module must specify 3 files. <br> (Default: NONE) |
| `STA_WRITE_LIB` | Controls whether a timing model is written using OpenROAD OpenSTA after static timing analysis. This is an option as it in its current state, the timing model generation (and the model itself) can be quite buggy. <br> (Default: `1`) |
### Floorplanning

View File

@@ -541,7 +541,7 @@ Startpoint: write_addr[1] (input port clocked by clk)
Endpoint: _3436_ (rising edge-triggered flip-flop clocked by clk)
Path Group: clk
Path Type: max
Corner: ss
Corner: Slowest
Fanout Cap Slew Delay Time Description
-----------------------------------------------------------------------------

View File

@@ -14,14 +14,46 @@
source $::env(SCRIPTS_DIR)/openroad/common/set_global_connections.tcl
proc read_netlist {args} {
puts "Reading netlist..."
proc is_blackbox {file_path blackbox_wildcard} {
set not_found [catch {
exec bash -c "grep '$blackbox_wildcard' \
$file_path"
}]
return [expr !$not_found]
}
if {[catch {read_verilog $::env(CURRENT_NETLIST)} errmsg]} {
proc read_netlist {args} {
sta::parse_key_args "read_netlists" args \
keys {}\
flags {-powered -all}
set netlist $::env(CURRENT_NETLIST)
if { [info exists flags(-powered)] } {
set netlist $::env(CURRENT_POWERED_NETLIST)
}
puts "Reading netlist $netlist ..."
if {[catch {read_verilog $netlist} errmsg]} {
puts stderr $errmsg
exit 1
}
if { [info exists flags(-all)] } {
set blackbox_wildcard {/// sta-blackbox}
if { [info exists ::env(VERILOG_FILES_BLACKBOX)] } {
foreach verilog_file $::env(VERILOG_FILES_BLACKBOX) {
if { [is_blackbox $verilog_file $blackbox_wildcard] } {
puts "Found $blackbox_wildcard in $verilog_file skipping..."
} elseif { [catch {read_verilog $verilog_file} err] } {
puts "Error while reading $verilog_file:"
puts "Make sure that this a gate-level netlist not an RTL file"
puts "Add $blackbox_wildcard to skip this file and blackbox the modules if needed."
puts $err
exit 1
}
}
}
}
link_design $::env(DESIGN_NAME)
if { [info exists ::env(CURRENT_SDC)] } {
@@ -35,49 +67,31 @@ proc read_netlist {args} {
proc read_libs {args} {
sta::parse_key_args "read_libs" args \
keys {-override}\
flags {-multi_corner}
keys {-typical -slowest -fastest}\
flags {-multi_corner_libs}
set libs $::env(LIB_SYNTH_COMPLETE)
if { [info exists keys(-override)] } {
set libs $keys(-override)
if { ![info exists keys(-typical)] } {
puts "read_libs -typical is required"
exit 1
}
if { [info exists keys(-slowest)] } {
set corner(Slowest) $keys(-slowest)
}
if { [info exists keys(-fastest)] } {
set corner(Fastest) $keys(-fastest)
}
set corner(Typical) $keys(-typical)
puts "define_corners [array name corner]"
define_corners {*}[array name corner]
if { [info exists flags(-multi_corner)] } {
# Note that the one defined first is the "default": meaning you
# shouldn't use -multi_corner for scripts that do not explicitly
# specify the corners for STA calls.
define_corners ss tt ff;
foreach lib $::env(LIB_SLOWEST) {
read_liberty -corner ss $lib
}
foreach lib $::env(LIB_TYPICAL) {
read_liberty -corner tt $lib
}
foreach lib $::env(LIB_FASTEST) {
read_liberty -corner ff $lib
}
foreach corner {ss tt ff} {
if { [info exists ::env(EXTRA_LIBS) ] } {
foreach lib $::env(EXTRA_LIBS) {
read_liberty -corner $corner $lib
}
}
}
} else {
foreach lib $libs {
read_liberty $lib
}
foreach corner_name [array name corner] {
puts "read_liberty -corner $corner_name $corner($corner_name)"
read_liberty -corner $corner_name $corner($corner_name)
if { [info exists ::env(EXTRA_LIBS) ] } {
foreach lib $::env(EXTRA_LIBS) {
read_liberty $lib
read_liberty -corner $corner_name $lib
}
}
}
}
@@ -106,11 +120,13 @@ proc read {args} {
set read_libs_args [list]
if { [info exists keys(-override_libs)]} {
lappend read_libs_args -override $keys(-override_libs)
lappend read_libs_args -typical $keys(-override_libs)
} else {
lappend read_libs_args -typical $::env(LIB_TYPICAL)
}
if { [info exists flags(-multi_corner_libs)] } {
lappend read_libs_args -multi_corner
lappend read_libs_args -fastest $::env(LIB_FASTEST) -slowest $::env(LIB_SLOWEST)
}
read_libs {*}$read_libs_args
@@ -129,9 +145,10 @@ proc write {args} {
# attempt to write a corresponding view to the specified location.
sta::parse_key_args "write" args \
keys {}\
flags {}
flags {-no_global_connect}
if { [info exists ::env(VDD_NET)] } {
if { [info exists ::env(VDD_NET)] \
&& ![info exist flags(-no_global_connect)] } {
puts "Setting global connections for newly added cells..."
set_global_connections
}
@@ -207,3 +224,37 @@ proc write {args} {
}
}
}
proc read_spefs {} {
set corners [sta::corners]
if { [info exists ::env(CURRENT_SPEF)] } {
foreach corner $corners {
read_spef -corner [$corner name] $::env(CURRENT_SPEF)
read_spef -corner [$corner name] $::env(CURRENT_SPEF)
read_spef -corner [$corner name] $::env(CURRENT_SPEF)
}
}
if { [info exists ::env(EXTRA_SPEFS)] } {
foreach {module_name spef_file_min spef_file_nom spef_file_max} \
"$::env(EXTRA_SPEFS)" {
set matched 0
foreach cell [get_cells *] {
if { "[get_property $cell ref_name]" eq "$module_name" && !$matched } {
puts "Matched [get_property $cell name] with $module_name"
set matched 1
foreach corner $corners {
read_spef -path [get_property $cell name] -corner [$corner name] $spef_file_min
read_spef -path [get_property $cell name] -corner [$corner name] $spef_file_nom
read_spef -path [get_property $cell name] -corner [$corner name] $spef_file_max
}
}
}
if { $matched != 1 } {
puts "Error: Module $module_name specified in EXTRA_SPEFS not found."
exit 1
}
}
}
}

View File

@@ -45,7 +45,18 @@ proc set_global_connections {} {
if { $power_pin == "" || $ground_pin == "" } {
puts "FP_PDN_MACRO_HOOKS missing power and ground pin names"
exit -1
exit 1
}
set matched 0
foreach cell [[ord::get_db_block] getInsts] {
if { [regexp "\^$instance_name" [$cell getName]] } {
set matched 1
}
}
if { $matched != 1 } {
puts "No regex match found for $instance_name defined in FP_PDN_MACRO_HOOKS"
exit 1
}
add_global_connection \
@@ -61,4 +72,4 @@ proc set_global_connections {} {
-ground
}
}
}
}

View File

@@ -81,11 +81,3 @@ puts "cts_report"
report_cts
puts "cts_report_end"
if {[info exists ::env(CLOCK_PORT)]} {
if { [info exists ::env(CTS_REPORT_TIMING)] && $::env(CTS_REPORT_TIMING) } {
set ::env(RUN_STANDALONE) 0
source $::env(SCRIPTS_DIR)/openroad/sta.tcl
}
} else {
puts "\[WARN\]: No CLOCK_PORT found. Skipping STA..."
}

View File

@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
read_libs -override "$::env(LIB_SYNTH_COMPLETE)"
read_libs -typical "$::env(LIB_SYNTH_COMPLETE)"
read_lef $::env(MERGED_LEF)
read_netlist
@@ -108,4 +108,4 @@ puts -nonewline $core_area_file $::env(CORE_AREA)
close $core_area_file
close $die_area_file
write
write

View File

@@ -78,9 +78,6 @@ if {[info exists ::env(CLOCK_PORT)]} {
# set rc values
source $::env(SCRIPTS_DIR)/openroad/common/set_rc.tcl
estimate_parasitics -placement
set ::env(RUN_STANDALONE) 0
source $::env(SCRIPTS_DIR)/openroad/sta.tcl
}
} else {
puts "\[WARN\]: No CLOCK_PORT found. Skipping STA..."

View File

@@ -48,9 +48,6 @@ if {[info exists ::env(CLOCK_PORT)]} {
source $::env(SCRIPTS_DIR)/openroad/common/set_rc.tcl
# estimate wire rc parasitics
estimate_parasitics -global_routing
set ::env(RUN_STANDALONE) 0
source $::env(SCRIPTS_DIR)/openroad/sta.tcl
}
} else {
puts "\[WARN\]: No CLOCK_PORT found. Skipping STA..."

View File

@@ -14,7 +14,7 @@
source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
read_lef $::env(RCX_LEF)
read_def $::env(RCX_DEF)
read_libs -override "$::env(RCX_LIB)"
read_libs -typical "$::env(RCX_LIB)"
set_propagated_clock [all_clocks]
@@ -31,4 +31,4 @@ extract_parasitics $rcx_flags\
-lef_res
puts "Writing result to $::env(SAVE_SPEF)..."
write
write

View File

@@ -76,5 +76,3 @@ write
# Run post design optimizations STA
estimate_parasitics -placement
set ::env(RUN_STANDALONE) 0
source $::env(SCRIPTS_DIR)/openroad/sta.tcl

View File

@@ -74,5 +74,3 @@ write
# Run post timing optimizations STA
estimate_parasitics -global_routing
set ::env(RUN_STANDALONE) 0
source $::env(SCRIPTS_DIR)/openroad/sta.tcl

View File

@@ -78,5 +78,3 @@ write
# Run post timing optimizations STA
estimate_parasitics -global_routing
set ::env(RUN_STANDALONE) 0
source $::env(SCRIPTS_DIR)/openroad/sta.tcl

View File

@@ -65,5 +65,3 @@ write
# Run post timing optimizations STA
estimate_parasitics -placement
set ::env(RUN_STANDALONE) 0
source $::env(SCRIPTS_DIR)/openroad/sta.tcl

View File

@@ -11,54 +11,65 @@
# 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.
if { $::env(RUN_STANDALONE) == 1 } {
source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
if { $::env(CURRENT_ODB) != "0" } {
read
} else {
read_libs
read_lef $::env(MERGED_LEF)
read_netlist
}
source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
if { $::env(STA_PRE_CTS) == 1 } {
unset_propagated_clock [all_clocks]
} else {
set_propagated_clock [all_clocks]
}
set arg_list [list]
lappend arg_list -typical $::env(LIB_TYPICAL)
if { $::env(STA_MULTICORNER) } {
lappend arg_list -fastest $::env(LIB_FASTEST)
lappend arg_list -slowest $::env(LIB_SLOWEST)
}
read_libs {*}$arg_list
read_netlist -all
read_spefs
set_cmd_units -time ns -capacitance pF -current mA -voltage V -resistance kOhm -distance um
if { [info exists ::env(CURRENT_SPEF)] } {
read_spef $::env(CURRENT_SPEF)
if { $::env(STA_PRE_CTS) == 1 } {
unset_propagated_clock [all_clocks]
} else {
set_propagated_clock [all_clocks]
}
puts "min_report"
puts "\n==========================================================================="
puts "report_checks -path_delay min (Hold)"
puts "============================================================================"
report_checks -path_delay min -fields {slew cap input nets fanout} -format full_clock_expanded -group_count 5
foreach corner [sta::corners] {
puts "\n======================= [$corner name] Corner ===================================\n"
report_checks -path_delay min -fields {slew cap input nets fanout} -format full_clock_expanded -group_count 1000 -corner [$corner name]
}
puts "min_report_end"
puts "max_report"
puts "\n==========================================================================="
puts "report_checks -path_delay max (Setup)"
puts "============================================================================"
report_checks -path_delay max -fields {slew cap input nets fanout} -format full_clock_expanded -group_count 5
foreach corner [sta::corners] {
puts "\n======================= [$corner name] Corner ===================================\n"
report_checks -path_delay max -fields {slew cap input nets fanout} -format full_clock_expanded -group_count 1000 -corner [$corner name]
}
puts "max_report_end"
puts "check_report"
puts "\n==========================================================================="
puts "report_checks -unconstrained"
puts "============================================================================"
report_checks -unconstrained -fields {slew cap input nets fanout} -format full_clock_expanded
foreach corner [sta::corners] {
puts "\n======================= [$corner name] Corner ===================================\n"
report_checks -unconstrained -fields {slew cap input nets fanout} -format full_clock_expanded -corner [$corner name]
}
puts "\n==========================================================================="
puts "report_checks --slack_max -0.01"
puts "============================================================================"
report_checks -slack_max -0.01 -fields {slew cap input nets fanout} -format full_clock_expanded
foreach corner [sta::corners] {
puts "\n======================= [$corner name] Corner ===================================\n"
report_checks -slack_max -0.01 -fields {slew cap input nets fanout} -format full_clock_expanded -corner [$corner name]
}
puts "check_report_end"
puts "parastic_annotation_check"
@@ -66,14 +77,16 @@ puts "\n========================================================================
puts "report_parasitic_annotation -report_unannotated"
puts "============================================================================"
report_parasitic_annotation -report_unannotated
puts "parastic_annotation_check"
puts "parastic_annotation_check_end"
puts "check_slew"
puts "\n==========================================================================="
puts " report_check_types -max_slew -max_cap -max_fanout -violators"
puts "============================================================================"
report_check_types -max_slew -max_capacitance -max_fanout -violators
foreach corner [sta::corners] {
puts "\n======================= [$corner name] Corner ===================================\n"
report_check_types -max_slew -max_capacitance -max_fanout -violators -corner [$corner name]
}
puts "\n==========================================================================="
puts "max slew violation count [sta::max_slew_violation_count]"
@@ -96,6 +109,7 @@ puts "==========================================================================
report_wns
puts "wns_report_end"
puts "worst_slack"
puts "\n==========================================================================="
puts " report_worst_slack -max (Setup)"
@@ -108,6 +122,7 @@ puts "==========================================================================
report_worst_slack -min
puts "worst_slack_end"
# report clock skew if the clock port is defined
# OR hangs if this command is run on clockless designs
if { $::env(CLOCK_PORT) != "__VIRTUAL_CLK__" && $::env(CLOCK_PORT) != "" } {
@@ -115,25 +130,22 @@ if { $::env(CLOCK_PORT) != "__VIRTUAL_CLK__" && $::env(CLOCK_PORT) != "" } {
puts "\n==========================================================================="
puts " report_clock_skew"
puts "============================================================================"
report_clock_skew
foreach corner [sta::corners] {
puts "\n======================= [$corner name] Corner ===================================\n"
report_clock_skew -corner [$corner name]
}
puts "clock_skew_end"
}
# This segfaults sometimes.
if { $::env(STA_REPORT_POWER) } {
puts "power_report"
puts "\n==========================================================================="
puts " report_power"
puts "============================================================================"
report_power
puts "power_report_end"
}
puts "area_report"
puts "power_report"
puts "\n==========================================================================="
puts " report_design_area"
puts " report_power"
puts "============================================================================"
report_design_area
puts "area_report_end"
foreach corner [sta::corners] {
puts "\n======================= [$corner name] Corner ===================================\n"
report_power -corner [$corner name]
}
puts "power_report_end"
write
write -no_global_connect

View File

@@ -1,171 +0,0 @@
# 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.
source $::env(SCRIPTS_DIR)/openroad/common/io.tcl
read -multi_corner_libs
set_cmd_units -time ns -capacitance pF -current mA -voltage V -resistance kOhm -distance um
# Read parasitics if they are generated prior to this point
if { [info exists ::env(CURRENT_SPEF)] } {
read_spef -corner ss $::env(CURRENT_SPEF)
read_spef -corner tt $::env(CURRENT_SPEF)
read_spef -corner ff $::env(CURRENT_SPEF)
}
if { $::env(STA_PRE_CTS) == 1 } {
unset_propagated_clock [all_clocks]
} else {
set_propagated_clock [all_clocks]
}
puts "min_report"
puts "\n==========================================================================="
puts "report_checks -path_delay min (Hold)"
puts "============================================================================"
puts "\n======================= Slowest Corner ===================================\n"
report_checks -path_delay min -fields {slew cap input nets fanout} -format full_clock_expanded -group_count 1000 -corner ss
puts "\n======================= Typical Corner ===================================\n"
report_checks -path_delay min -fields {slew cap input nets fanout} -format full_clock_expanded -group_count 1000 -corner tt
puts "\n======================= Fastest Corner ===================================\n"
report_checks -path_delay min -fields {slew cap input nets fanout} -format full_clock_expanded -group_count 1000 -corner ff
puts "min_report_end"
puts "max_report"
puts "\n==========================================================================="
puts "report_checks -path_delay max (Setup)"
puts "============================================================================"
puts "\n======================= Slowest Corner ===================================\n"
report_checks -path_delay max -fields {slew cap input nets fanout} -format full_clock_expanded -group_count 1000 -corner ss
puts "\n======================= Typical Corner ===================================\n"
report_checks -path_delay max -fields {slew cap input nets fanout} -format full_clock_expanded -group_count 1000 -corner tt
puts "\n======================= Fastest Corner ===================================\n"
report_checks -path_delay max -fields {slew cap input nets fanout} -format full_clock_expanded -group_count 1000 -corner ff
puts "max_report_end"
puts "check_report"
puts "\n==========================================================================="
puts "report_checks -unconstrained"
puts "============================================================================"
puts "\n======================= Slowest Corner ===================================\n"
report_checks -unconstrained -fields {slew cap input nets fanout} -format full_clock_expanded -corner ss
puts "\n======================= Typical Corner ===================================\n"
report_checks -unconstrained -fields {slew cap input nets fanout} -format full_clock_expanded -corner tt
puts "\n======================= Fastest Corner ===================================\n"
report_checks -unconstrained -fields {slew cap input nets fanout} -format full_clock_expanded -corner ff
puts "\n==========================================================================="
puts "report_checks --slack_max -0.01"
puts "============================================================================"
puts "\n======================= Slowest Corner ===================================\n"
report_checks -slack_max -0.01 -fields {slew cap input nets fanout} -format full_clock_expanded -corner ss
puts "\n======================= Typical Corner ===================================\n"
report_checks -slack_max -0.01 -fields {slew cap input nets fanout} -format full_clock_expanded -corner tt
puts "\n======================= Fastest Corner ===================================\n"
report_checks -slack_max -0.01 -fields {slew cap input nets fanout} -format full_clock_expanded -corner ff
puts "check_report_end"
puts "parastic_annotation_check"
puts "\n==========================================================================="
puts "report_parasitic_annotation -report_unannotated"
puts "============================================================================"
report_parasitic_annotation -report_unannotated
puts "parastic_annotation_check_end"
puts "check_slew"
puts "\n==========================================================================="
puts " report_check_types -max_slew -max_cap -max_fanout -violators"
puts "============================================================================"
puts "\n======================= Slowest Corner ===================================\n"
report_check_types -max_slew -max_capacitance -max_fanout -violators -corner ss
puts "\n======================= Typical Corner ===================================\n"
report_check_types -max_slew -max_capacitance -max_fanout -violators -corner tt
puts "\n======================= Fastest Corner ===================================\n"
report_check_types -max_slew -max_capacitance -max_fanout -violators -corner ff
puts "\n==========================================================================="
puts "max slew violation count [sta::max_slew_violation_count]"
puts "max fanout violation count [sta::max_fanout_violation_count]"
puts "max cap violation count [sta::max_capacitance_violation_count]"
puts "============================================================================"
puts "check_slew_end"
puts "tns_report"
puts "\n==========================================================================="
puts " report_tns"
puts "============================================================================"
report_tns
puts "tns_report_end"
puts "wns_report"
puts "\n==========================================================================="
puts " report_wns"
puts "============================================================================"
report_wns
puts "wns_report_end"
puts "worst_slack"
puts "\n==========================================================================="
puts " report_worst_slack -max (Setup)"
puts "============================================================================"
report_worst_slack -max
puts "\n==========================================================================="
puts " report_worst_slack -min (Hold)"
puts "============================================================================"
report_worst_slack -min
puts "worst_slack_end"
# report clock skew if the clock port is defined
# OR hangs if this command is run on clockless designs
if { $::env(CLOCK_PORT) != "__VIRTUAL_CLK__" && $::env(CLOCK_PORT) != "" } {
puts "clock_skew"
puts "\n==========================================================================="
puts " report_clock_skew"
puts "============================================================================"
puts "\n======================== Slowest Corner ==================================\n"
report_clock_skew -corner ss
puts "\n======================= Typical Corner ===================================\n"
report_clock_skew -corner tt
puts "\n======================= Fastest Corner ===================================\n"
report_clock_skew -corner ff
puts "clock_skew_end"
}
puts "power_report"
puts "\n==========================================================================="
puts " report_power"
puts "============================================================================"
puts "\n\n======================= Slowest Corner =================================\n"
report_power -corner ss
puts "\n======================= Typical Corner ===================================\n"
report_power -corner tt
puts "\n\n======================= Fastest Corner =================================\n"
report_power -corner ff
puts "power_report_end"
puts "area_report"
puts "\n==========================================================================="
puts " report_design_area"
puts "============================================================================"
report_design_area
puts "area_report_end"
write

View File

@@ -85,7 +85,7 @@ ws = re.compile(r"\s+")
@click.option("--output-dir", default=None, help="Output to this directory.")
@click.option(
"--tool",
type=click.Choice(["openroad", "magic", "yosys"]),
type=click.Choice(["sta", "openroad", "magic", "yosys"]),
help="The tool used for the desired Tcl script. [required]",
)
@click.argument("input_file")
@@ -363,6 +363,8 @@ def issue(
run_cmd = "$TOOL_BIN -exit $PACKAGED_SCRIPT_0"
elif tool == "magic":
run_cmd = "$TOOL_BIN -dnull -noconsole -rcfile $MAGIC_MAGICRC < $PACKAGED_SCRIPT_0"
elif tool == "sta":
run_cmd = "$TOOL_BIN -exit $PACKAGED_SCRIPT_0"
elif tool == "yosys":
run_cmd = "$TOOL_BIN -c $PACKAGED_SCRIPT_0"
f.write(

View File

@@ -255,7 +255,6 @@ class Report(object):
("_sta.worst_slack.rpt", "worst_slack"),
("_sta.clock_skew.rpt", "clock_skew"),
("_sta.power.rpt", "power_report"),
("_sta.area.rpt", "area_report"),
]
for name, log in [

View File

@@ -889,6 +889,18 @@ proc prep {args} {
assert_files_exist "$::env(EXTRA_GDS_FILES)"
}
if { [info exists ::env(VERILOG_STA_NETLISTS)] } {
puts_verbose "Verifying existence of files defined in ::env(VERILOG_STA_NETLISTS)..."
assert_files_exist "$::env(VERILOG_STA_NETLISTS)"
}
if { [info exists ::env(EXTRA_SPEFS)] } {
if { [expr [llength $::env(EXTRA_SPEFS)] % 4] != 0 } {
puts_err "Please define EXTRA_SPEFS correctly. i.e. : <module1> <min1> <nom1> <max1> <module2> ..."
flow_fail
}
}
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "openlane design prep"
return -code ok
@@ -1051,8 +1063,8 @@ proc save_views {args} {
if { [info exists arg_values(-mc_spef_dir)] } {
set destination $path/spef/multicorner
if { [file exists $arg_values(-mc_spef_dir)] } {
file delete -force $destination
file copy -force $arg_values(-mc_spef_dir) $destination
file mkdir $destination
file copy -force {*}[glob $arg_values(-mc_spef_dir)/*] $destination
}
}

View File

@@ -46,6 +46,10 @@ proc run_cts {args} {
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "cts - openroad"
scrot_klayout -layout $::env(CURRENT_DEF) -log $::env(cts_logs)/screenshot.log
if { [info exists ::env(CTS_REPORT_TIMING)] && $::env(CTS_REPORT_TIMING) } {
run_sta -no_save $::env(cts_results) -log $::env(cts_logs)/sta.log
}
}
}

View File

@@ -25,12 +25,14 @@ proc global_placement_or {args} {
run_openroad_script $::env(SCRIPTS_DIR)/openroad/gpl.tcl\
-indexed_log [index_file $::env(placement_logs)/global.log]\
-save "to=$::env(placement_tmpfiles),name=global,def,odb"
-save "to=$::env(placement_tmpfiles),name=global,def,odb,netlist,powered_netlist"
check_replace_divergence
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "global placement - openroad"
run_sta -no_save -log $::env(placement_logs)/sta-global.log
}
proc global_placement {args} {
@@ -189,6 +191,7 @@ proc run_placement {args} {
detailed_placement_or
scrot_klayout -layout $::env(CURRENT_DEF) -log $::env(placement_logs)/screenshot.log
run_sta -no_save -log $::env(placement_logs)/sta.log
}
proc run_resizer_design {args} {

View File

@@ -100,6 +100,7 @@ proc global_routing_fastroute {args} {
-indexed_log [index_file $::env(routing_logs)/global_write_netlist.log]
TIMER::timer_stop
run_sta -no_save -log $::env(routing_logs)/sta-groute.log
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "global routing - openroad"
}
@@ -418,7 +419,6 @@ proc run_routing {args} {
#legalize if not yet legalized
global_routing
if { $::env(RUN_FILL_INSERTION) } {
@@ -453,7 +453,7 @@ proc run_resizer_design_routing {args} {
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "resizer design optimizations - openroad"
run_sta -no_save -log $::env(routing_logs)/sta-resizer_design.log
} else {
puts_info "Skipping Global Routing Resizer Design Optimizations."
}
@@ -472,7 +472,7 @@ proc run_resizer_timing_routing {args} {
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "resizer timing optimizations - openroad"
run_sta -no_save -log $::env(routing_logs)/sta-resizer_timing.log
} else {
puts_info "Skipping Global Routing Resizer Timing Optimizations."
}

View File

@@ -27,6 +27,8 @@ proc run_sta {args} {
-multi_corner
-pre_cts
-netlist_in
-blackbox_check
-no_save
}
parse_key_args "run_sta" args arg_values $options flags_map $flags
@@ -60,13 +62,28 @@ proc run_sta {args} {
set arg_list [list]
lappend arg_list -indexed_log $log
lappend arg_list -save "to=$arg_values(-save_to),noindex,sdf,$lib_option"
if { ![info exist flags_map(-no_save)] } {
lappend arg_list -save "to=$arg_values(-save_to),noindex,sdf,$lib_option"
}
if { [info exists flags_map(-netlist_in)] } {
lappend arg_list -netlist_in
}
proc blackbox_modules_check {file_path} {
set fp [open $file_path r]
set file_path [read $fp]
foreach line [split $file_path "\n"] {
if { [regexp {module\s+(\S+)\s+not\s+found} $line match first_group] } {
puts_warn "Module $first_group blackboxed during sta"
}
}
close $fp
}
set ::env(STA_MULTICORNER) 0
if { $multi_corner == 1 } {
run_openroad_script $::env(SCRIPTS_DIR)/openroad/sta_multi_corner.tcl \
set ::env(STA_MULTICORNER) 1
run_sta_script $::env(SCRIPTS_DIR)/openroad/sta/multi_corner.tcl \
-no_update_current\
{*}$arg_list
@@ -75,12 +92,17 @@ proc run_sta {args} {
}
unset ::env(SAVE_SDF)
} else {
run_openroad_script $::env(SCRIPTS_DIR)/openroad/sta.tcl {*}$arg_list
run_sta_script $::env(SCRIPTS_DIR)/openroad/sta/multi_corner.tcl {*}$arg_list
if { [info exists flags_map(-blackbox_check)] } {
blackbox_modules_check $log
}
}
unset ::env(STA_MULTICORNER)
TIMER::timer_stop
exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "sta - openroad"
}
proc run_parasitics_sta {args} {
set options {
{-out_directory optional}
@@ -137,7 +159,8 @@ proc run_parasitics_sta {args} {
run_sta\
-log $::env(signoff_logs)/rcx_sta.log\
-process_corner $process_corner\
-save_to $directory
-save_to $directory \
-blackbox_check
set ::env(LAST_TIMING_REPORT_TAG) [index_file $::env(signoff_reports)/rcx_sta]
}

View File

@@ -221,6 +221,10 @@ proc run_openroad_script {args} {
run_tcl_script -tool openroad -no_consume {*}$args
}
proc run_sta_script {args} {
run_tcl_script -tool sta -no_consume {*}$args
}
proc run_magic_script {args} {
run_tcl_script -tool magic -no_consume {*}$args
}
@@ -621,8 +625,14 @@ proc run_tcl_script {args} {
set args "magic -noconsole -dnull -rcfile $::env(MAGIC_MAGICRC) < $script |& tee $::env(TERMINAL_OUTPUT) $arg_values(-indexed_log)"
} elseif { $arg_values(-tool) == "yosys" } {
set args "$::env(SYNTH_BIN) -c $script |& tee $::env(TERMINAL_OUTPUT) $arg_values(-indexed_log)"
} elseif { $arg_values(-tool) == "sta" } {
set args "sta -exit -no_init $script |& tee $::env(TERMINAL_OUTPUT) $arg_values(-indexed_log)"
foreach {element value} $save_list {
set cap [string toupper $element]
set ::env(SAVE_${cap}) $value
}
} else {
puts_err "run_tcl_script only supports tools 'magic', 'yosys' or 'openroad' for now."
puts_err "run_tcl_script only supports tools 'magic', 'yosys', 'sta', or 'openroad' for now."
throw_error
}
@@ -685,6 +695,8 @@ proc run_tcl_script {args} {
lappend or_issue_arg_list --input-type "netlist" $::env(CURRENT_NETLIST)
} elseif { $tool != "openroad" || [info exists flag_map(-def_in)]} {
lappend or_issue_arg_list --input-type "def" $::env(CURRENT_DEF)
} elseif { $tool != "sta" } {
lappend or_issue_arg_list --input-type "netlist" $::env(CURRENT_NETLIST)
} else {
lappend or_issue_arg_list --input-type "odb" $::env(CURRENT_ODB)
}
@@ -730,5 +742,4 @@ proc run_tcl_script {args} {
}
}
package provide openlane_utils 0.9