diff --git a/Changelog.md b/Changelog.md index eb15b2729..5a8ecdbc2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -18,26 +18,92 @@ ## Steps -* `Yosys.*` - * Added `SYNTH_CORNER` +* `Odb.AddPDNObstructions`, `Odb.AddRoutingObstructions` + + * `PDN_OBSTRUCTIONS` and `ROUTING_OBSTRUCTIONS` are now lists of tuples + instead of variable-length Tcl-style lists (AKA: strings). + +* `OpenROAD.*` + + * Added `log_cmd` from OpenROAD-flow-scripts -- neat idea for consistency + * New convenience methods to append flags to calls based on environment + variables + * **Internal**: Steps now sensitive to `_OPENROAD_GUI` environment variable -- + coupled with `--only`, it runs a step in OpenROAD then doesn't quit so you + may inspect the result. + * This is not part of the OpenLane stable API and may be broken at any + moment. * `OpenROAD.CTS` + * Added flags `CTS_OBSTRUCTION_AWARE` and `CTS_BALANCE_LEVELS` * Added `CTS_SINK_BUFFER_MAX_CAP_DERATE_PCT` * Added `CTS_DELAY_BUFFER_DERATE_PCT` +* `OpenROAD.CutRows` + + * Added `FP_PRUNE_THRESHOLD` to prune rows not meeting the threshold after + cutting. + * `OpenROAD.DetailedRouting` - * Added `DRT_SAVE_SNAPSHOTS` which enables saving snapshots of the layout each detalied routing iteration. + + * Added `DRT_SAVE_SNAPSHOTS` which enables saving snapshots of the layout each + detalied routing iteration. * Added `DRT_SAVE_DRC_REPORT_ITERS` - +* `OpenROAD.GlobalPlacement` + + * Added optional variable `PL_ROUTABILITY_MAX_DENSITY_PCT` + +* `OpenROAD.RepairDesignPostGPL` + + * Added optional variable `DESIGN_REPAIR_MAX_UTIL_PCT` + +* `OpenROAD.ResizerTimingPostCTS` + + * Renamed `PL_RESIZER_GATE_CLONING` to `PL_RESIZER_SETUP_GATE_CLONING` + + * Fixed `PL_RESIZER_SETUP_GATE_CLONING` incorrectly applied to hold fixing + + * Added the following optional variables + + * `PL_RESIZER_SETUP_BUFFERING` + * `PL_RESIZER_SETUP_BUFFER_REMOVAL` + * `PL_RESIZER_SETUP_REPAIR_TNS_PCT` + * `PL_RESIZER_SETUP_MAX_UTIL_PCT` + * `PL_RESIZER_HOLD_REPAIR_TNS_PCT` + * `PL_RESIZER_HOLD_MAX_UTIL_PCT` + +* `OpenROAD.RepairDesignPostGRT` + + * Renamed `GRT_RESIZER_GATE_CLONING` to `GRT_RESIZER_SETUP_GATE_CLONING` + + * Fixed `GRT_RESIZER_SETUP_GATE_CLONING` incorrectly applied to hold fixing + + * Added the following optional variables + + * `GRT_RESIZER_SETUP_BUFFERING` + * `GRT_RESIZER_SETUP_BUFFER_REMOVAL` + * `GRT_RESIZER_SETUP_REPAIR_TNS_PCT` + * `GRT_RESIZER_SETUP_MAX_UTIL_PCT` + * `GRT_RESIZER_HOLD_REPAIR_TNS_PCT` + * `GRT_RESIZER_HOLD_MAX_UTIL_PCT` + +* Created `OpenROAD.UnplaceAll` + + * Removes the placement status of all instances. + +* `Yosys.*Synthesis` + + * Added `SYNTH_CORNER`: a step-specific override for `DEFAULT_CORNER`. + ## Tool Updates * Updated nix-eda - * Updated nixpkgs to nixos-24.11 (@ `3c53b4b`) - * Updated KLayout to `0.29.9` - * Updated Magic to `8.3.503` - * Updated Netgen to `1.5.287` + * Updated nixpkgs to nixos-24.11 (@ `3c53b4b`) + * Updated KLayout to `0.29.9` + * Updated Magic to `8.3.503` + * Updated Netgen to `1.5.287` * Updated ioplace-parser to`0.4.0` * Updated OpenROAD to `1d61007` * Updated OpenSTA to `aa598a2` @@ -45,6 +111,7 @@ ## Misc. Enhancements/Bugfixes * `openlane.state` + * `DesignFormat` * Now a dataclass encapsulating the information about the DesignFormat directly. @@ -60,8 +127,28 @@ * States initialized with keys that have values that are `None` now remove said keys. +* `openlane.config` + + * Moved a number of global variables: + * `WIRE_LENGTH_THRESHOLD` moved from global variables to + `Checker.WireLength` + * `GPIO_PAD_*` removed- no step currently uses them + * `FP_TRACKS_INFO`, `FP_TAPCELL_DIST` moved to relevant steps + * `FILL_CELL` and `DECAP_CELL` renamed to `FILL_CELLS` and `DECAP_CELLS` as + they are both lists + * `EXTRA_GDS_FILES` and `FALLBACK_SDC_FILE` renamed to `EXTRA_GDS` and + `FALLBACK_SDC`: information can be obtained from their typing + * Changed some `decimal.Decimal` initializations to use integers or strings + instead of floats. + ## API Breaks +* `Odb.AddRoutingObstructions`, `Odb.AddPDNObstructions` + + * Typing for representation of obstructions has been changed. Designs with a + meta version of 2 or higher must update their variables from strings to + tuples. + * `openlane.steps` * `TclStep` now uses the IDs uppercased for `CURRENT_` and `SAVE_`. @@ -79,19 +166,27 @@ to `full_name`. The enumeration's name has been added to `alts`, while `.name` is now an alias for `.id`. +* `openlane.config` + + * `WIRE_LENGTH_THRESHOLD`, `GPIO_PAD_*`, `FP_TRACKS_INFO`, `FP_TAPCELL_DIST` + are no longer global variables. + + * `FILL_CELL`, `DECAP_CELL`, `EXTRA_GDS_FILES`, `FALLBACK_SDC_FILE` were all + renamed, see Misc. Enhancements/Bugfixes. + # 2.3.2 ## Steps * `Yosys.*` - * Fixed blackbox Verilog and lib models causing a crash if they are - gzipped and/or have the extension `.gz`. - + * Fixed blackbox Verilog and lib models causing a crash if they are gzipped + and/or have the extension `.gz`. + ## Tool Updates * Relaxed requirement on `httpx` to include `0.28.X`, which has no removals compared to `0.27.0`. - + ## Documentation * Clarified support for gzipped files in the Classic flow. diff --git a/openlane/config/flow.py b/openlane/config/flow.py index b595913bc..bb2f2ae2c 100644 --- a/openlane/config/flow.py +++ b/openlane/config/flow.py @@ -53,44 +53,12 @@ def _prefix_to_wildcard(prefixes_raw: Union[str, Sequence[str]]): "The ground pin for the cells.", pdk=True, ), - Variable( - "WIRE_LENGTH_THRESHOLD", - Optional[Decimal], - "A value above which wire lengths generate warnings.", - units="µm", - pdk=True, - ), Variable( "TECH_LEFS", Dict[str, Path], "Map of corner patterns to to technology LEF files. A corner not matched here will not be supported by OpenRCX in the default flow.", pdk=True, ), - Variable( - "GPIO_PADS_LEF", - Optional[List[Path]], - "Path(s) to GPIO pad LEF file(s).", - pdk=True, - ), - Variable( - "GPIO_PADS_LEF_CORE_SIDE", - Optional[List[Path]], - "Path(s) to GPIO pad LEF file(s) as used for routing (?).", - pdk=True, - ), - Variable( - "GPIO_PADS_VERILOG", - Optional[List[Path]], - "Path(s) to GPIO pad Verilog models.", - pdk=True, - ), - Variable( - "GPIO_PAD_CELLS", - Optional[List[str]], - "A list of pad cell name prefixes.", - deprecated_names=[("GPIO_PADS_PREFIX", _prefix_to_wildcard)], - pdk=True, - ), Variable( "PRIMARY_GDSII_STREAMOUT_TOOL", str, @@ -136,20 +104,6 @@ def _prefix_to_wildcard(prefixes_raw: Union[str, Sequence[str]]): pdk=True, ), # Floorplanning - Variable( - "FP_TRACKS_INFO", - Path, - "A path to the a classic OpenROAD `.tracks` file. Used by the floorplanner to generate tracks.", - deprecated_names=["TRACKS_INFO_FILE"], - pdk=True, - ), - Variable( - "FP_TAPCELL_DIST", - Decimal, - "The distance between tap cell columns.", - units="µm", - pdk=True, - ), Variable( "FP_IO_HLAYER", str, @@ -190,16 +144,18 @@ def _prefix_to_wildcard(prefixes_raw: Union[str, Sequence[str]]): pdk=True, ), Variable( - "FILL_CELL", + "FILL_CELLS", List[str], "A list of cell names or wildcards of fill cells to be used in fill insertion.", pdk=True, + deprecated_names=["FILL_CELL"], ), Variable( - "DECAP_CELL", + "DECAP_CELLS", List[str], "A list of cell names or wildcards of decap cells to be used in fill insertion.", pdk=True, + deprecated_names=["DECAP_CELL"], ), Variable( "LIB", @@ -358,7 +314,7 @@ def _prefix_to_wildcard(prefixes_raw: Union[str, Sequence[str]]): Variable( "ENDCAP_CELL", str, - "Defines so-called 'end-cap' cells- decap cells placed at either sides of a design.", + "Defines the so-called 'end-cap' cell- class of decap cells placed at either sides of a design.", pdk=True, deprecated_names=["FP_ENDCAP_CELL"], ), @@ -474,17 +430,46 @@ def _prefix_to_wildcard(prefixes_raw: Union[str, Sequence[str]]): "Specifies LIB files of pre-hardened macros used in the current design, used during timing analyses (and during parasitics-based STA as a fallback). These are loaded indiscriminately for all timing corners.", ), Variable( - "EXTRA_GDS_FILES", + "EXTRA_GDS", Optional[List[Path]], "Specifies GDS files of pre-hardened macros used in the current design, used during tape-out.", + deprecated_names=["EXTRA_GDS_FILES"], ), Variable( - "FALLBACK_SDC_FILE", + "FALLBACK_SDC", Path, "A fallback SDC file for when a step-specific SDC file is not defined.", - deprecated_names=["BASE_SDC_FILE", "SDC_FILE"], + deprecated_names=["FALLBACK_SDC_FILE", "BASE_SDC_FILE", "SDC_FILE"], default=Path(os.path.join(get_script_dir(), "base.sdc")), ), ] +__for_whenever_we_implement_padring = [ + Variable( + "GPIO_PADS_LEF", + Optional[List[Path]], + "Path(s) to GPIO pad LEF file(s).", + pdk=True, + ), + Variable( + "GPIO_PADS_LEF_CORE_SIDE", + Optional[List[Path]], + "Path(s) to GPIO pad LEF file(s) as used for routing (?).", + pdk=True, + ), + Variable( + "GPIO_PADS_VERILOG", + Optional[List[Path]], + "Path(s) to GPIO pad Verilog models.", + pdk=True, + ), + Variable( + "GPIO_PAD_CELLS", + Optional[List[str]], + "A list of pad cell name prefixes.", + deprecated_names=[("GPIO_PADS_PREFIX", _prefix_to_wildcard)], + pdk=True, + ), +] + flow_common_variables = pdk_variables + scl_variables + option_variables diff --git a/openlane/config/preprocessor.py b/openlane/config/preprocessor.py index 1051b7aba..7d9b121a1 100644 --- a/openlane/config/preprocessor.py +++ b/openlane/config/preprocessor.py @@ -180,7 +180,7 @@ def evaluate(expression: str, symbols: Mapping[str, Any]) -> Decimal: eval_stack.pop() eval_stack.pop() - result = Decimal(0.0) + result = Decimal("0") if token.value == "**": result = number1**number2 elif token.value == "*": diff --git a/openlane/scripts/magic/common/read.tcl b/openlane/scripts/magic/common/read.tcl index 83e753de8..cad9990e6 100644 --- a/openlane/scripts/magic/common/read.tcl +++ b/openlane/scripts/magic/common/read.tcl @@ -55,8 +55,8 @@ proc read_extra_gds {} { set old_readonly [gds readonly] gds rescale false gds readonly true - if { [info exist ::env(EXTRA_GDS_FILES)] } { - set gds_files_in $::env(EXTRA_GDS_FILES) + if { [info exist ::env(EXTRA_GDS)] } { + set gds_files_in $::env(EXTRA_GDS) foreach gds_file $gds_files_in { puts "> gds read $gds_file" gds read $gds_file diff --git a/openlane/scripts/magic/gds/extras_mag.tcl b/openlane/scripts/magic/gds/extras_mag.tcl index 3865a704e..cb61fad15 100755 --- a/openlane/scripts/magic/gds/extras_mag.tcl +++ b/openlane/scripts/magic/gds/extras_mag.tcl @@ -25,8 +25,8 @@ if { $::env(MAGIC_GDS_POLYGON_SUBCELLS) } { gds polygon subcells true } -if { [info exist ::env(EXTRA_GDS_FILES)] } { - set gds_files_in $::env(EXTRA_GDS_FILES) +if { [info exist ::env(EXTRA_GDS)] } { + set gds_files_in $::env(EXTRA_GDS) foreach gds_file $gds_files_in { gds read $gds_file diff --git a/openlane/scripts/openroad/common/dpl.tcl b/openlane/scripts/openroad/common/dpl.tcl index cf8158580..66dec0051 100644 --- a/openlane/scripts/openroad/common/dpl.tcl +++ b/openlane/scripts/openroad/common/dpl.tcl @@ -15,7 +15,7 @@ source $::env(SCRIPTS_DIR)/openroad/common/dpl_cell_pad.tcl remove_fillers -detailed_placement\ +log_cmd detailed_placement\ -max_displacement [subst { $::env(PL_MAX_DISPLACEMENT_X) $::env(PL_MAX_DISPLACEMENT_Y) }] if { [info exists ::env(PL_OPTIMIZE_MIRRORING)] && $::env(PL_OPTIMIZE_MIRRORING) } { diff --git a/openlane/scripts/openroad/common/grt.tcl b/openlane/scripts/openroad/common/grt.tcl index 12ba85f7a..96bc24427 100644 --- a/openlane/scripts/openroad/common/grt.tcl +++ b/openlane/scripts/openroad/common/grt.tcl @@ -26,7 +26,7 @@ lappend arg_list -verbose if { $::env(GRT_ALLOW_CONGESTION) == 1 } { lappend arg_list -allow_congestion } -puts $arg_list -global_route {*}$arg_list -write_guide $::env(STEP_DIR)/after_grt.guide \ No newline at end of file +log_cmd global_route {*}$arg_list + +write_guide $::env(STEP_DIR)/after_grt.guide diff --git a/openlane/scripts/openroad/common/io.tcl b/openlane/scripts/openroad/common/io.tcl index 486211086..6f37c5eac 100644 --- a/openlane/scripts/openroad/common/io.tcl +++ b/openlane/scripts/openroad/common/io.tcl @@ -316,6 +316,70 @@ proc read_current_odb {args} { set_dont_use_cells } +proc _populate_cells_by_class {} { + if { [info exists ::_cells_by_class(physical)] } { + return + } + + set ::_cells_by_class(physical) [list] + set ::_cells_by_class(non_timing) [list] + set _comment_ { + We naïvely assume anything not in these classes is not a cell with a + logical function. This may not be comprehensive, but is good enough. + + CORE just means a macro used in the core area (i.e. a standard cell.) + + Thing is, it has a lot of subclasses for physical cells: + + `FEEDTHRU`,`SPACER`,`ANTENNACELL`,`WELLTAP` + + Only `TIEHIGH`, `TIELOW` are for logical cells. Thus, the inclusion + list allows them as well. `BLOCKS` are macros, which we cannot discern + whether they have a logical function or not, so we include them + regardless. + + We do make one exception for `ANTENNACELL`s. These are not counted as + logical cells but they are not exempt from the so-called SDF-friendly + netlist as they do affect timing ever so slightly. + } + set logical_classes { + BLOCK + BUMP + CORE + CORE_TIEHIGH + CORE_TIELOW + COVER + PAD + PAD_AREAIO + PAD_INOUT + PAD_INPUT + PAD_OUTPUT + PAD_POWER + PAD_SPACER + } + + foreach lib $::libs { + foreach master [$lib getMasters] { + if { [lsearch -exact $logical_classes [$master getType]] == -1 } { + lappend ::_cells_by_class(physical) [$master getName] + if { "[$master getType]" != "CORE_ANTENNACELL" } { + lappend ::_cells_by_class(non_timing) [$master getName] + } + } + } + } +} + +proc get_timing_excluded_cells {args} { + _populate_cells_by_class + return $::_cells_by_class(non_timing) +} + +proc get_physical_cells {args} { + _populate_cells_by_class + return $::_cells_by_class(physical) +} + proc write_views {args} { # This script will attempt to write views based on existing "SAVE_" # environment variables. If the SAVE_ variable exists, the script will @@ -349,20 +413,16 @@ proc write_views {args} { } if { [info exists ::env(SAVE_SDF_PNL)] } { - set exclude_cells "[join $::env(FILL_CELL)] [join $::env(DECAP_CELL)] [join $::env(WELLTAP_CELL)] [join $::env(ENDCAP_CELL)]" - puts "Writing nofill powered netlist to '$::env(SAVE_SDF_PNL)'…" - puts "Excluding $exclude_cells" + puts "Writing timing powered netlist to '$::env(SAVE_SDF_PNL)'…" write_verilog -include_pwr_gnd \ - -remove_cells "$exclude_cells"\ + -remove_cells "[get_timing_excluded_cells]"\ $::env(SAVE_SDF_PNL) } if { [info exists ::env(SAVE_LOGICAL_PNL)] } { - set exclude_cells "[join [lindex [split $::env(DIODE_CELL) "/"] 0]] [join $::env(FILL_CELL)] [join $::env(DECAP_CELL)] [join $::env(WELLTAP_CELL)] [join $::env(ENDCAP_CELL)]" - puts "Writing nofilldiode powered netlist to '$::env(SAVE_LOGICAL_PNL)'…" - puts "Excluding $exclude_cells" + puts "Writing logic-only powered netlist to '$::env(SAVE_LOGICAL_PNL)'…" write_verilog -include_pwr_gnd \ - -remove_cells "$exclude_cells"\ + -remove_cells "[get_physical_cells]"\ $::env(SAVE_LOGICAL_PNL) } @@ -474,3 +534,85 @@ if { [namespace exists utl] } { puts "%OL_METRIC $metric $value" } } + +proc exit_unless_gui {{status 0}} { + if { ![info exists ::env(_OPENROAD_GUI)] || !$::env(_OPENROAD_GUI) } { + exit $status + } +} + +proc find_unfixed_macros {} { + set macros [list] + + foreach inst [$::block getInsts] { + set inst_master [$inst getMaster] + + # BLOCK means MACRO cells + if { ![string match [$inst_master getType] "BLOCK"] } { + continue + } + + if { [$inst isFixed] } { + continue + } + + lappend macros $inst + } + return $macros +} + +proc append_if_exists_argument {list_arg glob_variable_name option} { + upvar $list_arg local_array + if [info exists ::env($glob_variable_name) ] { + lappend local_array $option $::env($glob_variable_name) + } +} + +proc append_if_flag {list_arg glob_variable_name flag} { + upvar $list_arg local_array + if { [info exists ::env($glob_variable_name)] && $::env($glob_variable_name) } { + lappend local_array $flag + } +} +proc append_if_not_flag {list_arg glob_variable_name flag} { + upvar $list_arg local_array + if { [info exists ::env($glob_variable_name)] && !$::env($glob_variable_name) } { + lappend local_array $flag + } +} + +# Code below adapted from OpenROAD Flow Scripts under the following license: +# +# BSD 3-Clause License +# +# Copyright (c) 2018-2023, The Regents of the University of California +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: + +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +proc log_cmd {cmd args} { + puts "+ $cmd [join $args " "]" + $cmd {*}$args +} diff --git a/openlane/scripts/openroad/common/set_global_connections.tcl b/openlane/scripts/openroad/common/set_global_connections.tcl index 13a48b433..cf5dd7627 100644 --- a/openlane/scripts/openroad/common/set_global_connections.tcl +++ b/openlane/scripts/openroad/common/set_global_connections.tcl @@ -45,7 +45,7 @@ proc set_global_connections {} { if { $power_pin == "" || $ground_pin == "" } { puts "PDN_MACRO_CONNECTIONS missing power and ground pin names" - exit -1 + exit_unless_gui 1 } set matched 0 @@ -57,7 +57,7 @@ proc set_global_connections {} { } if { $matched != 1 } { puts "\[ERROR\] No match found for regular expression '$instance_name' defined in PDN_MACRO_CONNECTIONS." - exit 1 + exit_unless_gui 1 } add_global_connection \ diff --git a/openlane/scripts/openroad/common/set_power_nets.tcl b/openlane/scripts/openroad/common/set_power_nets.tcl index 951b5f749..b8b623a73 100644 --- a/openlane/scripts/openroad/common/set_power_nets.tcl +++ b/openlane/scripts/openroad/common/set_power_nets.tcl @@ -17,7 +17,7 @@ if { [info exists ::env(VDD_NETS)] || [info exists ::env(GND_NETS)] } { # current assumption: they cannot have a common ground if { ! [info exists ::env(VDD_NETS)] || ! [info exists ::env(GND_NETS)] } { puts stderr "\[ERROR\] VDD_NETS and GND_NETS must *both* either be defined or undefined" - exit -1 + exit_unless_gui 1 } set ::env(VDD_NET) [lindex $::env(VDD_NETS) 0] set ::env(GND_NET) [lindex $::env(GND_NETS) 0] diff --git a/openlane/scripts/openroad/cts.tcl b/openlane/scripts/openroad/cts.tcl index 81fcf05de..2a8147fcd 100755 --- a/openlane/scripts/openroad/cts.tcl +++ b/openlane/scripts/openroad/cts.tcl @@ -33,7 +33,7 @@ if { [info exists ::env(CTS_MAX_CAP)] } { if { [info exists ::env(CTS_MAX_SLEW)] } { lappend cts_characterization_args -max_slew [expr {$::env(CTS_MAX_SLEW) * 1e-9}]; # ns -> S } -configure_cts_characterization {*}$cts_characterization_args +log_cmd configure_cts_characterization {*}$cts_characterization_args puts "\[INFO\] Performing clock tree synthesis…" puts "\[INFO\] Looking for the following net(s): $::env(CLOCK_NET)" @@ -66,8 +66,7 @@ if { [info exists ::env(CTS_BALANCE_LEVELS)] && $::env(CTS_BALANCE_LEVELS) } { lappend arg_list -balance_levels } -puts "clock_tree_synthesis {*}$arg_list" -clock_tree_synthesis {*}$arg_list +log_cmd clock_tree_synthesis {*}$arg_list set_propagated_clock [all_clocks] diff --git a/openlane/scripts/openroad/cut_rows.tcl b/openlane/scripts/openroad/cut_rows.tcl index 076e37a6d..0167ee7c6 100644 --- a/openlane/scripts/openroad/cut_rows.tcl +++ b/openlane/scripts/openroad/cut_rows.tcl @@ -14,10 +14,27 @@ source $::env(SCRIPTS_DIR)/openroad/common/io.tcl read_current_odb -cut_rows\ - -endcap_master $::env(ENDCAP_CELL)\ - -halo_width_x $::env(FP_MACRO_HORIZONTAL_HALO)\ - -halo_width_y $::env(FP_MACRO_VERTICAL_HALO) +set arg_list [list] +lappend arg_list -endcap_master $::env(ENDCAP_CELL) +lappend arg_list -halo_width_x $::env(FP_MACRO_HORIZONTAL_HALO) +lappend arg_list -halo_width_y $::env(FP_MACRO_VERTICAL_HALO) +if { [info exists ::env(FP_PRUNE_THRESHOLD)] } { + lappend arg_list -row_min_width $::env(FP_PRUNE_THRESHOLD) +} +log_cmd cut_rows {*}$arg_list + +# # verify -row_min_width worked +# if { [info exists ::env(FP_PRUNE_THRESHOLD)] } { +# foreach row [$::block getRows] { +# set bbox [$row getBBox] +# set width [expr ([$bbox xMax] - [$bbox xMin])] +# set width_um [expr $width / $::dbu] +# if { $width < $::env(FP_PRUNE_THRESHOLD) } { +# exit -1 +# # odb::dbRow_destroy $row +# } +# } +# } write_views diff --git a/openlane/scripts/openroad/drt.tcl b/openlane/scripts/openroad/drt.tcl index fa5a00773..61b9c8d80 100755 --- a/openlane/scripts/openroad/drt.tcl +++ b/openlane/scripts/openroad/drt.tcl @@ -36,7 +36,7 @@ if { $::env(DRT_SAVE_SNAPSHOTS) } { if { [info exists ::env(DRT_SAVE_DRC_REPORT_ITERS)] } { set drc_report_iter_step_arg "-drc_report_iter_step $::env(DRT_SAVE_DRC_REPORT_ITERS)" } -detailed_route\ +log_cmd detailed_route\ -bottom_routing_layer $min_layer\ -top_routing_layer $max_layer\ -output_drc $::env(STEP_DIR)/$::env(DESIGN_NAME).drc\ diff --git a/openlane/scripts/openroad/fill.tcl b/openlane/scripts/openroad/fill.tcl index 3575e15ef..2f60001c8 100755 --- a/openlane/scripts/openroad/fill.tcl +++ b/openlane/scripts/openroad/fill.tcl @@ -15,11 +15,11 @@ source $::env(SCRIPTS_DIR)/openroad/common/io.tcl read_current_odb set fill_list [list] -foreach {pattern} $::env(DECAP_CELL) { +foreach {pattern} $::env(DECAP_CELLS) { set stripped [string map {' {}} $pattern] lappend fill_list $stripped } -foreach {pattern} $::env(FILL_CELL) { +foreach {pattern} $::env(FILL_CELLS) { set stripped [string map {' {}} $pattern] lappend fill_list $stripped } diff --git a/openlane/scripts/openroad/floorplan.tcl b/openlane/scripts/openroad/floorplan.tcl index f3e750f43..aa1c0e918 100755 --- a/openlane/scripts/openroad/floorplan.tcl +++ b/openlane/scripts/openroad/floorplan.tcl @@ -53,7 +53,7 @@ puts "\[INFO\] Using $::env(FP_SIZING) sizing for the floorplan." if {$::env(FP_SIZING) == "absolute"} { if { [llength $::env(DIE_AREA)] != 4 } { puts stderr "Invalid die area string '$::env(DIE_AREA)'." - exit -1 + exit_unless_gui 1 } if { ! [info exists ::env(CORE_AREA)] } { set die_ll_x [lindex $::env(DIE_AREA) 0] @@ -70,7 +70,7 @@ if {$::env(FP_SIZING) == "absolute"} { } else { if { [llength $::env(CORE_AREA)] != 4 } { puts stderr "Invalid core area string '$::env(CORE_AREA)'." - exit -1 + exit_unless_gui 1 } puts "\[INFO\] Using the set CORE_AREA; ignoring core margin parameters" } @@ -94,7 +94,7 @@ if { [info exists ::env(FP_OBSTRUCTIONS)] } { } } -initialize_floorplan {*}$arg_list +log_cmd initialize_floorplan {*}$arg_list insert_tiecells $::env(SYNTH_TIELO_CELL) -prefix "TIE_ZERO_" insert_tiecells $::env(SYNTH_TIEHI_CELL) -prefix "TIE_ONE_" diff --git a/openlane/scripts/openroad/gpl.tcl b/openlane/scripts/openroad/gpl.tcl index ad1015e6a..241d0d077 100755 --- a/openlane/scripts/openroad/gpl.tcl +++ b/openlane/scripts/openroad/gpl.tcl @@ -26,11 +26,11 @@ foreach inst $::insts { } if { !$placement_needed } { - puts stderr "\[WARNING\] All instances are FIXED/FIRM." - puts stderr "\[WARNING\] No need to perform global placement." - puts stderr "\[WARNING\] Skipping…" + puts "\[INFO\] All instances are FIXED/FIRM." + puts "\[INFO\] No need to perform global placement." + puts "\[INFO\] Skipping…" write_views - exit 0 + exit_unless_gui } set arg_list [list] @@ -56,8 +56,7 @@ if { $::env(PL_SKIP_INITIAL_PLACEMENT) } { lappend arg_list -skip_initial_place } - -if { [info exists ::env(__PL_SKIP_IO)] } { +if { [info exists ::env(__PL_SKIP_IO)] && $::env(__PL_SKIP_IO) == "1" } { lappend arg_list -skip_io } @@ -75,8 +74,7 @@ lappend arg_list -pad_right $cell_pad_side lappend arg_list -pad_left $cell_pad_side lappend arg_list -init_wirelength_coef $::env(PL_WIRE_LENGTH_COEF) -puts "+ global_placement $arg_list" -global_placement {*}$arg_list +log_cmd global_placement {*}$arg_list source $::env(SCRIPTS_DIR)/openroad/common/set_rc.tcl diff --git a/openlane/scripts/openroad/insert_buffer.tcl b/openlane/scripts/openroad/insert_buffer.tcl index e0e41b7b6..032d2118b 100644 --- a/openlane/scripts/openroad/insert_buffer.tcl +++ b/openlane/scripts/openroad/insert_buffer.tcl @@ -121,7 +121,7 @@ if { [info exists ::env(INSERT_BUFFER_COMMAND) ]} { read_current_odb set arg_list [split $::env(INSERT_BUFFER_COMMAND) " "] - insert_buffer {*}$arg_list + log_cmd insert_buffer {*}$arg_list write_views -} \ No newline at end of file +} diff --git a/openlane/scripts/openroad/ioplacer.tcl b/openlane/scripts/openroad/ioplacer.tcl index 6e0aa2ab1..6a8d45a88 100755 --- a/openlane/scripts/openroad/ioplacer.tcl +++ b/openlane/scripts/openroad/ioplacer.tcl @@ -55,8 +55,7 @@ if { $::env(FP_PPL_MODE) == "annealing" } { set HMETAL $::env(FP_IO_HLAYER) set VMETAL $::env(FP_IO_VLAYER) -puts "\[INFO\] place_pins args: $arg_list" -place_pins {*}$arg_list \ +log_cmd place_pins {*}$arg_list \ -random_seed 42 \ -hor_layers $HMETAL \ -ver_layers $VMETAL diff --git a/openlane/scripts/openroad/irdrop.tcl b/openlane/scripts/openroad/irdrop.tcl index f5545707f..60fbeec7c 100644 --- a/openlane/scripts/openroad/irdrop.tcl +++ b/openlane/scripts/openroad/irdrop.tcl @@ -27,7 +27,7 @@ if { [info exists ::env(VSRC_LOC_FILES)] } { lappend arg_list -net $net lappend arg_list -voltage_file $::env(STEP_DIR)/net-$net.csv lappend arg_list -vsrc $vsrc_file - analyze_power_grid {*}$arg_list + log_cmd analyze_power_grid {*}$arg_list } puts "%OL_END_REPORT" } else { @@ -38,14 +38,14 @@ if { [info exists ::env(VSRC_LOC_FILES)] } { lappend arg_list -net $net lappend arg_list -voltage_file $::env(STEP_DIR)/net-$net.csv set_pdnsim_net_voltage -net $net -voltage $::env(LIB_VOLTAGE) - analyze_power_grid {*}$arg_list + log_cmd analyze_power_grid {*}$arg_list } foreach net "$::env(GND_NETS)" { set arg_list [list] lappend arg_list -net $net lappend arg_list -voltage_file $::env(STEP_DIR)/net-$net.csv set_pdnsim_net_voltage -net $net -voltage 0 - analyze_power_grid {*}$arg_list + log_cmd analyze_power_grid {*}$arg_list } puts "%OL_END_REPORT" } diff --git a/openlane/scripts/openroad/pdn.tcl b/openlane/scripts/openroad/pdn.tcl index 59e8af625..900eeb9ec 100644 --- a/openlane/scripts/openroad/pdn.tcl +++ b/openlane/scripts/openroad/pdn.tcl @@ -23,28 +23,29 @@ read_pdn_cfg set arg_list [list] if { $::env(FP_PDN_SKIPTRIM) } { lappend arg_list -skip_trim - puts "adding -skip_trim to pdngen" } # run PDNGEN -if {[catch {pdngen {*}$arg_list} errmsg]} { +if {[catch {log_cmd pdngen {*}$arg_list} errmsg]} { puts stderr $errmsg - exit 1 -} + exit_unless_gui 1 +} else { + write_views + report_design_area_metrics -write_views -report_design_area_metrics + foreach {net} "$::env(VDD_NETS) $::env(GND_NETS)" { + set report_file $::env(STEP_DIR)/$net-grid-errors.rpt -foreach {net} "$::env(VDD_NETS) $::env(GND_NETS)" { - set report_file $::env(STEP_DIR)/$net-grid-errors.rpt + # For some reason, check_power_grid is… totally okay if no nodes are found + # at all. i.e. PDN generation has completely failed. + # This is a fallback file. + set f [open $report_file "w"] + puts $f "" + close $f - # For some reason, check_power_grid is… totally okay if no nodes are found - # at all. i.e. PDN generation has completely failed. - # This is a fallback file. - set f [open $report_file "w"] - puts $f "" - close $f + if { [catch {check_power_grid -net $net -error_file $report_file} err] } { + puts stderr "\[WARNING\] Grid check for $net failed: $err" + } - if { [catch {check_power_grid -net $net -error_file $report_file} err] } { - puts stderr "\[WARNING\] Grid check for $net failed: $err" } + } diff --git a/openlane/scripts/openroad/rcx.tcl b/openlane/scripts/openroad/rcx.tcl index 573506797..534119784 100644 --- a/openlane/scripts/openroad/rcx.tcl +++ b/openlane/scripts/openroad/rcx.tcl @@ -26,7 +26,7 @@ if { !$::env(RCX_MERGE_VIA_WIRE_RES) } { # RCX puts "Using RCX ruleset '$::env(RCX_RULESET)'…" define_process_corner -ext_model_index 0 CURRENT_CORNER -extract_parasitics $rcx_flags\ +log_cmd extract_parasitics $rcx_flags\ -ext_model_file $::env(RCX_RULESET)\ -lef_res write_views diff --git a/openlane/scripts/openroad/repair_design.tcl b/openlane/scripts/openroad/repair_design.tcl index ef457ae10..cbd5c6add 100644 --- a/openlane/scripts/openroad/repair_design.tcl +++ b/openlane/scripts/openroad/repair_design.tcl @@ -42,17 +42,25 @@ if { $::env(DESIGN_REPAIR_BUFFER_OUTPUT_PORTS) } { buffer_ports -outputs } +set arg_list [list] +lappend arg_list -verbose +lappend arg_list -max_wire_length $::env(DESIGN_REPAIR_MAX_WIRE_LENGTH) +lappend arg_list -slew_margin $::env(DESIGN_REPAIR_MAX_SLEW_PCT) +lappend arg_list -cap_margin $::env(DESIGN_REPAIR_MAX_CAP_PCT) +if { [info exists ::env(DESIGN_REPAIR_MAX_UTILIZATION)] } { + lappend arg_list -max_utilization $::env(DESIGN_REPAIR_MAX_UTILIZATION) +} +if { [info exists ::env(DESIGN_REPAIR_BUFFER_GAIN)] } { + lappend arg_list -buffer_gain $::env(DESIGN_REPAIR_BUFFER_GAIN) +} # Repair Design -repair_design -verbose \ - -max_wire_length $::env(DESIGN_REPAIR_MAX_WIRE_LENGTH) \ - -slew_margin $::env(DESIGN_REPAIR_MAX_SLEW_PCT) \ - -cap_margin $::env(DESIGN_REPAIR_MAX_CAP_PCT) +log_cmd repair_design {*}$arg_list if { $::env(DESIGN_REPAIR_TIE_FANOUT) } { # repair tie lo fanout - repair_tie_fanout -separation $::env(DESIGN_REPAIR_TIE_SEPARATION) $::env(SYNTH_TIELO_CELL) + repair_tie_fanout -verbose -separation $::env(DESIGN_REPAIR_TIE_SEPARATION) $::env(SYNTH_TIELO_CELL) # repair tie hi fanout - repair_tie_fanout -separation $::env(DESIGN_REPAIR_TIE_SEPARATION) $::env(SYNTH_TIEHI_CELL) + repair_tie_fanout -verbose -separation $::env(DESIGN_REPAIR_TIE_SEPARATION) $::env(SYNTH_TIEHI_CELL) } report_floating_nets -verbose diff --git a/openlane/scripts/openroad/repair_design_postgrt.tcl b/openlane/scripts/openroad/repair_design_postgrt.tcl index 54e9ec5fa..e0404305c 100644 --- a/openlane/scripts/openroad/repair_design_postgrt.tcl +++ b/openlane/scripts/openroad/repair_design_postgrt.tcl @@ -31,11 +31,19 @@ source $::env(SCRIPTS_DIR)/openroad/common/grt.tcl #} estimate_parasitics -global_routing -# Repair design -repair_design -verbose \ - -max_wire_length $::env(GRT_DESIGN_REPAIR_MAX_WIRE_LENGTH) \ - -slew_margin $::env(GRT_DESIGN_REPAIR_MAX_SLEW_PCT) \ - -cap_margin $::env(GRT_DESIGN_REPAIR_MAX_CAP_PCT) +# Repair Design +set arg_list [list] +lappend arg_list -verbose +lappend arg_list -max_wire_length $::env(GRT_DESIGN_REPAIR_MAX_WIRE_LENGTH) +lappend arg_list -slew_margin $::env(GRT_DESIGN_REPAIR_MAX_SLEW_PCT) +lappend arg_list -cap_margin $::env(GRT_DESIGN_REPAIR_MAX_CAP_PCT) +if { [info exists ::env(GRT_DESIGN_REPAIR_MAX_UTILIZATION)] } { + lappend arg_list -max_utilization $::env(GRT_DESIGN_REPAIR_MAX_UTILIZATION) +} +if { [info exists ::env(GRT_DESIGN_REPAIR_BUFFER_GAIN)] } { + lappend arg_list -buffer_gain $::env(GRT_DESIGN_REPAIR_BUFFER_GAIN) +} +log_cmd repair_design {*}$arg_list # Re-DPL and GRT source $::env(SCRIPTS_DIR)/openroad/common/dpl.tcl diff --git a/openlane/scripts/openroad/rsz_timing_postcts.tcl b/openlane/scripts/openroad/rsz_timing_postcts.tcl index be22825ea..a3c2dd4ec 100644 --- a/openlane/scripts/openroad/rsz_timing_postcts.tcl +++ b/openlane/scripts/openroad/rsz_timing_postcts.tcl @@ -1,4 +1,4 @@ -# Copyright 2020-2023 Efabless Corporation +# Copyright 2020-2024 Efabless Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -34,9 +34,11 @@ lappend setup_args -verbose lappend setup_args -setup lappend setup_args -setup_margin $::env(PL_RESIZER_SETUP_SLACK_MARGIN) lappend setup_args -max_buffer_percent $::env(PL_RESIZER_SETUP_MAX_BUFFER_PCT) -if { $::env(PL_RESIZER_GATE_CLONING) != 1 } { - lappend setup_args -skip_gate_cloning -} +append_if_not_flag setup_args PL_RESIZER_SETUP_BUFFERING -skip_buffering +append_if_not_flag setup_args PL_RESIZER_SETUP_BUFFER_REMOVAL -skip_buffer_removal +append_if_not_flag setup_args PL_RESIZER_SETUP_GATE_CLONING -skip_gate_cloning +append_if_exists_argument setup_args PL_RESIZER_SETUP_REPAIR_TNS_PCT -repair_tns +append_if_exists_argument setup_args PL_RESIZER_SETUP_MAX_UTIL_PCT -max_utilization set hold_args [list] lappend hold_args -verbose @@ -44,16 +46,16 @@ lappend hold_args -hold lappend hold_args -setup_margin $::env(PL_RESIZER_SETUP_SLACK_MARGIN) lappend hold_args -hold_margin $::env(PL_RESIZER_HOLD_SLACK_MARGIN) lappend hold_args -max_buffer_percent $::env(PL_RESIZER_HOLD_MAX_BUFFER_PCT) -if { $::env(PL_RESIZER_ALLOW_SETUP_VIOS) == 1 } { - lappend hold_args -allow_setup_violations -} +append_if_flag hold_args PL_RESIZER_ALLOW_SETUP_VIOS -allow_setup_violations +append_if_exists_argument hold_args PL_RESIZER_HOLD_REPAIR_TNS_PCT -repair_tns +append_if_exists_argument hold_args PL_RESIZER_HOLD_MAX_UTIL_PCT -max_utilization if { $::env(PL_RESIZER_FIX_HOLD_FIRST) == 1 } { - repair_timing {*}$hold_args - repair_timing {*}$setup_args + log_cmd repair_timing {*}$hold_args + log_cmd repair_timing {*}$setup_args } else { - repair_timing {*}$setup_args - repair_timing {*}$hold_args + log_cmd repair_timing {*}$setup_args + log_cmd repair_timing {*}$hold_args } # Legalize diff --git a/openlane/scripts/openroad/rsz_timing_postgrt.tcl b/openlane/scripts/openroad/rsz_timing_postgrt.tcl index 2ad629281..897163c0c 100644 --- a/openlane/scripts/openroad/rsz_timing_postgrt.tcl +++ b/openlane/scripts/openroad/rsz_timing_postgrt.tcl @@ -1,4 +1,4 @@ -# Copyright 2020-2023 Efabless Corporation +# Copyright 2020-2024 Efabless Corporation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -37,9 +37,11 @@ lappend setup_args -verbose lappend setup_args -setup lappend setup_args -setup_margin $::env(GRT_RESIZER_SETUP_SLACK_MARGIN) lappend setup_args -max_buffer_percent $::env(GRT_RESIZER_SETUP_MAX_BUFFER_PCT) -if { $::env(GRT_RESIZER_GATE_CLONING) != 1 } { - lappend setup_args -skip_gate_cloning -} +append_if_not_flag setup_args GRT_RESIZER_SETUP_BUFFERING -skip_buffering +append_if_not_flag setup_args GRT_RESIZER_SETUP_BUFFER_REMOVAL -skip_buffer_removal +append_if_not_flag setup_args GRT_RESIZER_SETUP_GATE_CLONING -skip_gate_cloning +append_if_exists_argument setup_args GRT_RESIZER_SETUP_REPAIR_TNS_PCT -repair_tns +append_if_exists_argument setup_args GRT_RESIZER_SETUP_MAX_UTIL_PCT -max_utilization set hold_args [list] lappend hold_args -verbose @@ -47,16 +49,16 @@ lappend hold_args -hold lappend hold_args -setup_margin $::env(GRT_RESIZER_SETUP_SLACK_MARGIN) lappend hold_args -hold_margin $::env(GRT_RESIZER_HOLD_SLACK_MARGIN) lappend hold_args -max_buffer_percent $::env(GRT_RESIZER_HOLD_MAX_BUFFER_PCT) -if { $::env(GRT_RESIZER_ALLOW_SETUP_VIOS) == 1 } { - lappend hold_args -allow_setup_violations -} +append_if_flag hold_args GRT_RESIZER_ALLOW_SETUP_VIOS -allow_setup_violations +append_if_exists_argument hold_args GRT_RESIZER_HOLD_REPAIR_TNS_PCT -repair_tns +append_if_exists_argument hold_args GRT_RESIZER_HOLD_MAX_UTIL_PCT -max_utilization if { $::env(GRT_RESIZER_FIX_HOLD_FIRST) == 1 } { - repair_timing {*}$hold_args - repair_timing {*}$setup_args + log_cmd repair_timing {*}$hold_args + log_cmd repair_timing {*}$setup_args } else { - repair_timing {*}$setup_args - repair_timing {*}$hold_args + log_cmd repair_timing {*}$setup_args + log_cmd repair_timing {*}$hold_args } # Re-DPL and GRT diff --git a/openlane/scripts/openroad/sta/check_macro_instances.tcl b/openlane/scripts/openroad/sta/check_macro_instances.tcl index d6aa20448..057da8c29 100644 --- a/openlane/scripts/openroad/sta/check_macro_instances.tcl +++ b/openlane/scripts/openroad/sta/check_macro_instances.tcl @@ -49,5 +49,5 @@ foreach {instance_name macro_name} $::env(_check_macro_instances) { } if { $error_count != 0 } { - exit -1 + exit_unless_gui 1 } diff --git a/openlane/scripts/openroad/tapcell.tcl b/openlane/scripts/openroad/tapcell.tcl index 355e16355..8e921df99 100755 --- a/openlane/scripts/openroad/tapcell.tcl +++ b/openlane/scripts/openroad/tapcell.tcl @@ -14,7 +14,7 @@ source $::env(SCRIPTS_DIR)/openroad/common/io.tcl read_current_odb -tapcell\ +log_cmd tapcell\ -distance $::env(FP_TAPCELL_DIST)\ -tapcell_master "$::env(WELLTAP_CELL)"\ -endcap_master "$::env(ENDCAP_CELL)"\ diff --git a/openlane/scripts/openroad/ungpl.tcl b/openlane/scripts/openroad/ungpl.tcl new file mode 100644 index 000000000..a44c301d8 --- /dev/null +++ b/openlane/scripts/openroad/ungpl.tcl @@ -0,0 +1,23 @@ +# Copyright 2024 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_current_odb + +set ::insts [$::block getInsts] + +foreach inst $::insts { + $inst setPlacementStatus "NONE" +} + +write_views diff --git a/openlane/steps/checker.py b/openlane/steps/checker.py index cab542e05..a0fe3cc53 100644 --- a/openlane/steps/checker.py +++ b/openlane/steps/checker.py @@ -266,7 +266,16 @@ class WireLength(MetricChecker): default=True, deprecated_names=["QUIT_ON_LONG_WIRE"], ) - config_vars = [error_on_var] + config_vars = [ + error_on_var, + Variable( + "WIRE_LENGTH_THRESHOLD", + Optional[Decimal], + "A value above which wire lengths generate warnings.", + units="µm", + pdk=True, + ), + ] def get_threshold(self) -> Optional[Decimal]: threshold = self.config["WIRE_LENGTH_THRESHOLD"] diff --git a/openlane/steps/klayout.py b/openlane/steps/klayout.py index 527775633..1e4d4e835 100644 --- a/openlane/steps/klayout.py +++ b/openlane/steps/klayout.py @@ -131,7 +131,7 @@ def get_cli_args( for gds in self.toolbox.get_macro_views(self.config, DesignFormat.GDS): gds_args.append("--with-gds-file") gds_args.append(gds) - if extra_gds := self.config["EXTRA_GDS_FILES"]: + if extra_gds := self.config["EXTRA_GDS"]: for gds in extra_gds: gds_args.append("--with-gds-file") gds_args.append(gds) diff --git a/openlane/steps/misc.py b/openlane/steps/misc.py index 4d54a8d4d..cd855afb9 100644 --- a/openlane/steps/misc.py +++ b/openlane/steps/misc.py @@ -39,7 +39,7 @@ class LoadBaseSDC(Step): outputs = [DesignFormat.SDC] def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]: - path = self.config["FALLBACK_SDC_FILE"] + path = self.config["FALLBACK_SDC"] target = os.path.join(self.step_dir, f"{self.config['DESIGN_NAME']}.sdc") diff --git a/openlane/steps/odb.py b/openlane/steps/odb.py index 71ea6b77d..3c24211d2 100644 --- a/openlane/steps/odb.py +++ b/openlane/steps/odb.py @@ -502,9 +502,9 @@ class AddRoutingObstructions(OdbpyStep): config_vars = [ Variable( "ROUTING_OBSTRUCTIONS", - Optional[List[str]], + Optional[List[Tuple[str, Decimal, Decimal, Decimal, Decimal]]], "Add routing obstructions to the design. If set to `None`, this step is skipped." - + " Format of each obstruction item is: layer llx lly urx ury.", + + " Format of each obstruction item is a tuple of: layer name, llx, lly, urx, ury.", units="µm", default=None, deprecated_names=["GRT_OBS"], @@ -525,7 +525,7 @@ def get_command(self) -> List[str]: if obstructions := self.config[self.config_vars[0].name]: for obstruction in obstructions: command.append("--obstructions") - command.append(obstruction) + command.append(" ".join([str(o) for o in obstruction])) return command def run(self, state_in, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]: @@ -554,9 +554,9 @@ class AddPDNObstructions(AddRoutingObstructions): config_vars = [ Variable( "PDN_OBSTRUCTIONS", - Optional[List[str]], + Optional[List[Tuple[str, Decimal, Decimal, Decimal, Decimal]]], "Add routing obstructions to the design before PDN stage. If set to `None`, this step is skipped." - + " Format of each obstruction item is: layer llx lly urx ury.", + + " Format of each obstruction item is a tuple of: layer name, llx, lly, urx, ury,.", units="µm", default=None, ), diff --git a/openlane/steps/openroad.py b/openlane/steps/openroad.py index cc5230d3d..900f526fd 100644 --- a/openlane/steps/openroad.py +++ b/openlane/steps/openroad.py @@ -173,7 +173,7 @@ class CheckSDCFiles(Step): def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]: default_sdc_file = [ - var for var in option_variables if var.name == "FALLBACK_SDC_FILE" + var for var in option_variables if var.name == "FALLBACK_SDC" ][0] assert default_sdc_file is not None @@ -258,7 +258,7 @@ def prepare_env(self, env: dict, state: State) -> dict: lib_list = self.toolbox.filter_views(self.config, self.config["LIB"]) lib_list += self.toolbox.get_macro_views(self.config, DesignFormat.LIB) - env["_SDC_IN"] = self.config["PNR_SDC_FILE"] or self.config["FALLBACK_SDC_FILE"] + env["_SDC_IN"] = self.config["PNR_SDC_FILE"] or self.config["FALLBACK_SDC"] env["_PNR_LIBS"] = TclStep.value_to_tcl(lib_list) env["_MACRO_LIBS"] = TclStep.value_to_tcl( self.toolbox.get_macro_views(self.config, DesignFormat.LIB) @@ -342,7 +342,7 @@ def get_command(self) -> List[str]: metrics_path = os.path.join(self.step_dir, "or_metrics_out.json") return [ "openroad", - "-exit", + ("-gui" if os.getenv("_OPENROAD_GUI", "0") == "1" else "-exit"), "-no_splash", "-metrics", metrics_path, @@ -912,6 +912,13 @@ class Floorplan(OpenROADStep): inputs = [DesignFormat.NETLIST] config_vars = OpenROADStep.config_vars + [ + Variable( + "FP_TRACKS_INFO", + Path, + "A path to the a classic OpenROAD `.tracks` file. Used by the floorplanner to generate tracks.", + deprecated_names=["TRACKS_INFO_FILE"], + pdk=True, + ), Variable( "FP_SIZING", Literal["absolute", "relative"], @@ -1106,7 +1113,7 @@ def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]: @Step.factory.register() class TapEndcapInsertion(OpenROADStep): """ - Places well TAP cells across a floorplan, as well as end-cap cells at the + Places welltap cells across a floorplan, as well as endcap cells at the edges of the floorplan. """ @@ -1117,7 +1124,7 @@ class TapEndcapInsertion(OpenROADStep): Variable( "FP_MACRO_HORIZONTAL_HALO", Decimal, - "Specify the horizontal halo size around macros while cutting rows.", + "Specify the horizontal halo size around macros.", default=10, units="µm", deprecated_names=["FP_TAP_HORIZONTAL_HALO"], @@ -1125,17 +1132,40 @@ class TapEndcapInsertion(OpenROADStep): Variable( "FP_MACRO_VERTICAL_HALO", Decimal, - "Specify the vertical halo size around macros while cutting rows.", + "Specify the vertical halo size around macros.", default=10, units="µm", deprecated_names=["FP_TAP_VERTICAL_HALO"], ), + Variable( + "FP_TAPCELL_DIST", + Decimal, + "The distance between tap cell columns.", + units="µm", + pdk=True, + ), ] def get_script_path(self): return os.path.join(get_script_dir(), "openroad", "tapcell.tcl") +@Step.factory.register() +class UnplaceAll(OpenROADStep): + """ + Sets placement status of *all* instances to NONE. + + Useful in flows where a preliminary placement is needed as a pre-requisite + to something else but that placement must be discarded. + """ + + id = "OpenROAD.UnplaceAll" + name = "Unplace All" + + def get_script_path(self): + return os.path.join(get_script_dir(), "openroad", "ungpl.tcl") + + def get_psm_error_count(rpt: io.TextIOWrapper) -> int: sio = io.StringIO() @@ -1217,7 +1247,7 @@ class _GlobalPlacement(OpenROADStep): "The desired placement density of cells. If not specified, the value will be equal to (`FP_CORE_UTIL` + 5 * `GPL_CELL_PADDING` + 10).", units="%", deprecated_names=[ - ("PL_TARGET_DENSITY", lambda d: Decimal(d) * Decimal(100.0)) + ("PL_TARGET_DENSITY", lambda d: Decimal(d) * Decimal("100")) ], ), Variable( @@ -1316,7 +1346,7 @@ class GlobalPlacement(_GlobalPlacement): @Step.factory.register() class GlobalPlacementSkipIO(_GlobalPlacement): """ - Performs global placement without taking I/O into consideration. + Performs preliminary global placement as a basis for pin placement. This is useful for flows where the: * Cells are placed @@ -1335,6 +1365,11 @@ class GlobalPlacementSkipIO(_GlobalPlacement): default="matching", deprecated_names=[("FP_IO_MODE", _migrate_ppl_mode)], ), + Variable( + "FP_PIN_ORDER_CFG", + Optional[Path], + "Path to a custom pin configuration file.", + ), Variable( "FP_DEF_TEMPLATE", Optional[Path], @@ -1346,39 +1381,18 @@ def run(self, state_in: State, **kwargs) -> Tuple[ViewsUpdate, MetricsUpdate]: kwargs, env = self.extract_env(kwargs) if self.config["FP_DEF_TEMPLATE"] is not None: info( - f"I/O pins were loaded from {self.config['FP_DEF_TEMPLATE']}. Skipping the first global placement iteration…" + f"I/O pins were loaded from {self.config['FP_DEF_TEMPLATE']}. Returning state unaltered…" + ) + return {}, {} + if self.config["FP_PIN_ORDER_CFG"] is not None: + info( + f"I/O pins to be placed from {self.config['FP_PIN_ORDER_CFG']}. Returning state unaltered…" ) return {}, {} env["__PL_SKIP_IO"] = "1" return super().run(state_in, env=env, **kwargs) -@Step.factory.register() -class BasicMacroPlacement(OpenROADStep): - id = "OpenROAD.BasicMacroPlacement" - name = "Basic Macro Placement" - - config_vars = OpenROADStep.config_vars + [ - Variable( - "PL_MACRO_HALO", - str, - "Macro placement halo. Format: `{Horizontal} {Vertical}`.", - default="0 0", - units="µm", - ), - Variable( - "PL_MACRO_CHANNEL", - str, - "Channel widths between macros. Format: `{Horizontal} {Vertical}`.", - default="0 0", - units="µm", - ), - ] - - def get_script_path(self): - raise NotImplementedError() - - @Step.factory.register() class DetailedPlacement(OpenROADStep): """ @@ -1946,7 +1960,7 @@ class CutRows(OpenROADStep): Variable( "FP_MACRO_HORIZONTAL_HALO", Decimal, - "Specify the horizontal halo size around macros while cutting rows.", + "Specify the horizontal halo size around macros.", default=10, units="µm", deprecated_names=["FP_TAP_HORIZONTAL_HALO"], @@ -1954,11 +1968,18 @@ class CutRows(OpenROADStep): Variable( "FP_MACRO_VERTICAL_HALO", Decimal, - "Specify the vertical halo size around macros while cutting rows.", + "Specify the vertical halo size around macros.", default=10, units="µm", deprecated_names=["FP_TAP_VERTICAL_HALO"], ), + Variable( + "FP_PRUNE_THRESHOLD", + Optional[Decimal], + 'If specified, all rows smaller in width than this value will be removed. This helps avoid "islets" of cells that are hard to route and connect to PDNs.', + pdk=True, + units="µm", + ), ] def get_script_path(self): @@ -2342,10 +2363,47 @@ class ResizerTimingPostCTS(ResizerStep): default=False, ), Variable( - "PL_RESIZER_GATE_CLONING", + "PL_RESIZER_SETUP_GATE_CLONING", bool, "Enables gate cloning when attempting to fix setup violations", default=True, + deprecated_names=["PL_RESIZER_GATE_CLONING"], + ), + Variable( + "PL_RESIZER_SETUP_BUFFERING", + bool, + "Rebuffering and load splitting during setup fixing.", + default=True, + ), + Variable( + "PL_RESIZER_SETUP_BUFFER_REMOVAL", + bool, + "Buffer removal transform during setup fixing.", + default=True, + ), + Variable( + "PL_RESIZER_SETUP_REPAIR_TNS_PCT", + Optional[Decimal], + "Percentage of violating endpoints to repair during setup fixing.", + units="%", + ), + Variable( + "PL_RESIZER_SETUP_MAX_UTIL_PCT", + Optional[Decimal], + "Defines the percentage of core area used during setup fixing.", + units="%", + ), + Variable( + "PL_RESIZER_HOLD_REPAIR_TNS_PCT", + Optional[Decimal], + "Percentage of violating endpoints to repair during hold fixing.", + units="%", + ), + Variable( + "PL_RESIZER_HOLD_MAX_UTIL_PCT", + Optional[Decimal], + "Defines the percentage of core area used during hold fixing.", + units="%", ), Variable( "PL_RESIZER_FIX_HOLD_FIRST", @@ -2415,10 +2473,11 @@ class ResizerTimingPostGRT(ResizerStep): deprecated_names=["GLB_RESIZER_ALLOW_SETUP_VIOS"], ), Variable( - "GRT_RESIZER_GATE_CLONING", + "GRT_RESIZER_SETUP_GATE_CLONING", bool, "Enables gate cloning when attempting to fix setup violations", default=True, + deprecated_names=["GRT_RESIZER_GATE_CLONING"], ), Variable( "GRT_RESIZER_RUN_GRT", @@ -2426,6 +2485,42 @@ class ResizerTimingPostGRT(ResizerStep): "Gates running global routing after resizer steps. May be useful to disable for designs where global routing takes non-trivial time.", default=True, ), + Variable( + "GRT_RESIZER_SETUP_BUFFERING", + bool, + "Rebuffering and load splitting during setup fixing.", + default=True, + ), + Variable( + "GRT_RESIZER_SETUP_BUFFER_REMOVAL", + bool, + "Buffer removal transform during setup fixing.", + default=True, + ), + Variable( + "GRT_RESIZER_SETUP_REPAIR_TNS_PCT", + Optional[Decimal], + "Percentage of violating endpoints to repair during setup fixing.", + units="%", + ), + Variable( + "GRT_RESIZER_SETUP_MAX_UTIL_PCT", + Optional[Decimal], + "Defines the percentage of core area used during setup fixing.", + units="%", + ), + Variable( + "GRT_RESIZER_HOLD_REPAIR_TNS_PCT", + Optional[Decimal], + "Percentage of violating endpoints to repair during hold fixing.", + units="%", + ), + Variable( + "GRT_RESIZER_HOLD_MAX_UTIL_PCT", + Optional[Decimal], + "Defines the percentage of core area used during hold fixing.", + units="%", + ), Variable( "GRT_RESIZER_FIX_HOLD_FIRST", bool, diff --git a/pyproject.toml b/pyproject.toml index b010f3c15..fd36212cc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "openlane" -version = "3.0.0.dev7" +version = "3.0.0.dev8" description = "An infrastructure for implementing chip design flows" authors = ["Efabless Corporation and Contributors "] readme = "Readme.md" diff --git a/test/steps/all b/test/steps/all index acfad0066..f6f0faeb5 160000 --- a/test/steps/all +++ b/test/steps/all @@ -1 +1 @@ -Subproject commit acfad0066ba462962c03ff2234db0ef23f90f649 +Subproject commit f6f0faeb55f38b29c59be30f8b1cde139699796e diff --git a/test/steps/excluded_step_tests b/test/steps/excluded_step_tests index 1ea9c89ee..e69de29bb 100644 --- a/test/steps/excluded_step_tests +++ b/test/steps/excluded_step_tests @@ -1,2 +0,0 @@ -checker.holdviolations/004-success-hold-overwrite -checker.holdviolations/005-fail-different-corner