diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bfaeda9a..543dc879 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,11 +7,22 @@ For various reasons, it's recommended to call working branches, even in your for # Testing and Code Standards Before you submit your changes, it's prudent to perform some kind of smoke test. `make test` tests a simple spm design to ensure nothing has gone horribly wrong. -You will also need to ensure that your Python code passes linting with two tools: `black` and `flake8`. The commands are simply `black .` and `flake8 .`. Please fix all warnings. - +## Choice of Language Try to write all major code in Python. Writing some Tcl is usually a necessity because this project's backbone is unfortunately written in Tcl, but just keep the Tcl to as close to a Python shim as possible. -Please do not write new shell scripts. +Please do not write new shell scripts, no matter how trivial. + +### Tcl +1TBS-indented, four spaces, `lower_snake_case` for local/global variables and `UPPER_SNAKE_CASE` for environment variables. Unfortunately it is impossible to add any other guidelines or standards to the Tcl code considering it is Tcl code. Please exercise your best judgment. + +### Python +Python code should run on Python 3.6+. + +You will need to ensure that your Python code passes linting with the tools and plugins in [`requirements_lint.txt`](./requirements_lint.txt). The commands are simply `black .` and `flake8 .`. Please fix all warnings. + +For new code, please follow [PEP-8 naming conventions](https://peps.python.org/pep-0008/#naming-conventions). The linters do not enforce them just yet because of the corpus of existing code that does not do that, but they will in the future. + +Do all arithmetic either in integers or using the Python [`decimal`](https://docs.python.org/3.6/library/decimal.html) library. All (numerous) existing uses of IEEE-754 are bugs we are interested in fixing. ## Yosys, OpenROAD and Magic Scripts There are some special guidelines for scripts in `scripts/yosys`, `scripts/openroad`, and `scripts/magic`: diff --git a/README.md b/README.md index 4713b6d4..602d3ace 100644 --- a/README.md +++ b/README.md @@ -127,8 +127,6 @@ You can use the following example as a smoke test: To run OpenLane on multiple designs at the same time, check this [section](#regression-and-design-configurations-exploration). -Having trouble running the flow? check [FAQs](https://github.com/The-OpenROAD-Project/OpenLane/wiki) - ## Command line arguments The following are arguments that can be passed to `flow.tcl` diff --git a/configuration/README.md b/configuration/README.md index 8c911745..e3aeecf5 100644 --- a/configuration/README.md +++ b/configuration/README.md @@ -100,8 +100,8 @@ These variables are optional that can be specified in the design configuration f | `VDD_NETS` | Specifies the power nets/pins to be used when creating the power grid for the design. | | `GND_NETS` | Specifies the ground nets/pins to be used when creating the power grid for the design. | | `SYNTH_USE_PG_PINS_DEFINES` | Specifies the power guard used in the verilog source code to specify the power and ground pins. This is used to automatically extract `VDD_NETS` and `GND_NET` variables from the verilog, with the assumption that they will be order `inout vdd1, inout gnd1, inout vdd2, inout gnd2, ...`. | -| `FP_PDN_IRDROP` | Enable calculation of power grid IR drop during PDN generation.
(Default: `1`)| | `FP_IO_MIN_DISTANCE` | The minmimum distance between the IOs in microns.
(Default: `3`) | +| `FP_PDN_IRDROP` | **Removed: worthless** Enable calculation of power grid IR drop during PDN generation.
(Default: `1`)| #### Deprecated I/O Layer variables These variables worked initially, but they were too sky130 specific and will be removed. Currently, if you define them in your design, they'll be used, but it's recommended to update your configuration to use `FP_IO_HLAYER` and `FP_IO_VLAYER`, which are defined in the PDK. @@ -220,10 +220,10 @@ These variables worked initially, but they were too sky130 specific and will be |-|-| | `MAGIC_PAD` | A flag to pad the views generated by magic (.mag, .lef, .gds) with one site. 1 = Enabled, 0 = Disabled
(Default: `0` )| | `MAGIC_ZEROIZE_ORIGIN` | A flag to move the layout such that it's origin in the lef generated by magic is 0,0. 1 = Enabled, 0 = Disabled
(Default: `1` )| -| `MAGIC_GENERATE_GDS` | A flag to generate gds view via magic . 1 = Enabled, 0 = Disabled
(Default: `1` )| -| `MAGIC_GENERATE_LEF` | A flag to generate lef view via magic . 1 = Enabled, 0 = Disabled
(Default: `1` )| -| `MAGIC_GENERATE_MAGLEF` | A flag to generate maglef view via magic . 1 = Enabled, 0 = Disabled
(Default: `1` )| -| `MAGIC_WRITE_FULL_LEF` | A flag to specify whether or not the output LEF should include all shapes inside the macro or an abstracted view of the macro lef view via magic . 1 = Full View, 0 = Abstracted View
(Default: `0` )| +| `MAGIC_GENERATE_GDS` | A flag to generate gds view via magic. 1 = Enabled, 0 = Disabled
(Default: `1` )| +| `MAGIC_GENERATE_LEF` | A flag to generate lef view via magic. 1 = Enabled, 0 = Disabled
(Default: `1` )| +| `MAGIC_GENERATE_MAGLEF` | A flag to generate maglef view via magic. 1 = Enabled, 0 = Disabled
(Default: `1` )| +| `MAGIC_WRITE_FULL_LEF` | A flag to specify whether or not the output LEF should include all shapes inside the macro or an abstracted view of the macro lef view via magic. 1 = Full View, 0 = Abstracted View
(Default: `0` )| | `MAGIC_DRC_USE_GDS` | A flag to choose whether to run the magic DRC checks on GDS or not. If not, then the checks will be done on the DEF/LEF. 1 = GDS, 0 = DEF/LEF
(Default: `1` )| | `MAGIC_EXT_USE_GDS` | A flag to choose whether to run the magic extractions on GDS or DEF/LEF. If GDS was used Device Level LVS will be run. Otherwise, blackbox LVS will be run. 1 = GDS, 0 = DEF/LEF
(Default: `0` )| | `MAGIC_INCLUDE_GDS_POINTERS` | A flag to choose whether to include GDS pointers in the generated mag files or not. 1 = Enabled, 0 = Disabled
(Default: `0` )| @@ -237,7 +237,7 @@ These variables worked initially, but they were too sky130 specific and will be |-|-| | `LVS_INSERT_POWER_PINS` | Enables power pins insertion before running lvs. 1 = Enabled, 0 = Disabled
(Default: `1` )| | `LVS_CONNECT_BY_LABEL` | Enables connections by label in LVS by skipping `extract unique` in magic extractions.
Default: `0` | -| `YOSYS_REWRITE_VERILOG` | Enables yosys to rewrite the verilog before LVS producing a canonical verilog netlist with verbose wire declarations. This flag will be ignored if `LEC_ENABLE` is 1, and it will be rewritten anyways. 1 = Enabled, 0 = Disabled
(Default: `0` ) | +| `YOSYS_REWRITE_VERILOG` | Enables yosys to rewrite the verilog before LVS producing a canonical verilog netlist with verbose wire declarations. 1 = Enabled, 0 = Disabled
(Default: `0` ) | ### Flow control @@ -267,6 +267,7 @@ These variables worked initially, but they were too sky130 specific and will be | `RUN_SPEF_EXTRACTION` | Specifies whether or not to run SPEF extraction on the routed DEF. 1=enabled 0=disabled
Default: `1` | | `GENERATE_FINAL_SUMMARY_REPORT` | Specifies whether or not to generate a final summary report after the run is completed. Check command `generate_final_summary_report`. 1=enabled 0=disabled
Default: `1` | | `RUN_CVC` | Runs CVC on the output spice, which is a Circuit Validity Checker. Voltage aware ERC checker for CDL netlists. Thus, it controls the command `run_lef_cvc`. 1=Enabled, 0=Disabled.
Default: `1` | +| `RUN_IRDROP_REPORT` | Creates an IR Drop report using OpenROAD PSM. 1=Enabled, 0=Disabled.
Default: `0` | | `MAGIC_CONVERT_DRC_TO_RDB` | **Removed: Will always run** Specifies whether or not generate a Calibre RDB out of the magic.drc report. Result is saved in `/results/magic/`. 1=enabled 0=disabled
Default: `1`| ### Checkers diff --git a/configuration/general.tcl b/configuration/general.tcl index 5c5259ab..ac5e6643 100755 --- a/configuration/general.tcl +++ b/configuration/general.tcl @@ -29,11 +29,19 @@ if { ![info exists ::env(TEST_MISMATCHES)] } { set ::env(TEST_MISMATCHES) {all} } -# Flow control defaults -set ::env(RUN_LVS) 1 +# General Defaults +set ::env(CLOCK_PERIOD) "10.0" -set ::env(LEC_ENABLE) 0 -set ::env(YOSYS_REWRITE_VERILOG) 0 +# Flow Controls +set ::env(RUN_SIMPLE_CTS) 0 + +set ::env(FILL_INSERTION) 1 +set ::env(TAP_DECAP_INSERTION) 1 + +set ::env(RUN_DRT) 1 +set ::env(USE_ARC_ANTENNA_CHECK) 1 +set ::env(RUN_SPEF_EXTRACTION) 1 +set ::env(RUN_IRDROP_REPORT) 1 set ::env(PRIMARY_SIGNOFF_TOOL) magic @@ -51,24 +59,19 @@ set ::env(MAGIC_INCLUDE_GDS_POINTERS) 0 set ::env(MAGIC_DISABLE_HIER_GDS) 1 set ::env(MAGIC_CONVERT_DRC_TO_RDB) 1 +set ::env(RUN_KLAYOUT) 1 +set ::env(RUN_KLAYOUT_DRC) 0 set ::env(KLAYOUT_XOR_GDS) 1 set ::env(KLAYOUT_XOR_XML) 1 - -set ::env(RUN_DRT) 1 -set ::env(RUN_SIMPLE_CTS) 0 -set ::env(CLOCK_PERIOD) "10.0" -set ::env(RUN_KLAYOUT) 1 set ::env(TAKE_LAYOUT_SCROT) 0 -set ::env(RUN_KLAYOUT_DRC) 0 set ::env(KLAYOUT_DRC_KLAYOUT_GDS) 0 set ::env(RUN_KLAYOUT_XOR) 1 -set ::env(USE_ARC_ANTENNA_CHECK) 1 -set ::env(FILL_INSERTION) 1 -set ::env(TAP_DECAP_INSERTION) 1 - -set ::env(RUN_SPEF_EXTRACTION) 1 set ::env(RUN_CVC) 1 +set ::env(RUN_LVS) 1 + +set ::env(YOSYS_REWRITE_VERILOG) 0 +set ::env(LEC_ENABLE) 0 set ::env(GENERATE_FINAL_SUMMARY_REPORT) 1 diff --git a/designs/spm/config.json b/designs/spm/config.json index 7f7e0227..5ede731d 100644 --- a/designs/spm/config.json +++ b/designs/spm/config.json @@ -4,7 +4,6 @@ "CLOCK_PERIOD": 10, "CLOCK_PORT": "clk", "CLOCK_NET": "ref::$CLOCK_PORT", - "FP_PDN_AUTO_ADJUST": 0, "FP_PDN_VOFFSET": 7, "FP_PDN_HOFFSET": 7, "FP_PIN_ORDER_CFG": "dir::pin_order.cfg", diff --git a/flow.tcl b/flow.tcl index 75876cdd..9f221cdb 100755 --- a/flow.tcl +++ b/flow.tcl @@ -1,5 +1,5 @@ #!/usr/bin/env tclsh -# Copyright 2020-2021 Efabless Corporation +# 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. @@ -82,6 +82,12 @@ proc run_diode_insertion_2_5_step {args} { } +proc run_irdrop_report_step {args} { + if { $::env(RUN_IRDROP_REPORT) } { + run_irdrop_report + } +} + proc run_lvs_step {{ lvs_enabled 1 }} { if { ! [ info exists ::env(LVS_CURRENT_DEF) ] } { set ::env(LVS_CURRENT_DEF) $::env(CURRENT_DEF) @@ -190,6 +196,7 @@ proc run_non_interactive_mode {args} { "parasitics_sta" "run_parasitics_sta_step" \ "eco" "run_eco_step" \ "diode_insertion" "run_diode_insertion_2_5_step" \ + "irdrop" "run_irdrop_report_step" \ "gds_magic" "run_magic_step" \ "gds_klayout" "run_klayout_step" \ "lvs" "run_lvs_step $LVS_ENABLED " \ diff --git a/run_issue_regressions.py b/run_issue_regressions.py index 2f29c423..a19aceb2 100755 --- a/run_issue_regressions.py +++ b/run_issue_regressions.py @@ -91,7 +91,7 @@ def run_test_case(test_case): # ------------------------------- try: logfile = open(logpath, "w") - print(f"Running test case: {test_case_name} (logging to {logpath})") + print(f"Running test case: {test_case_name} (log: {logpath})") interactive = [] interactive_file = os.path.join(test_case, "interactive.tcl") if os.path.exists(interactive_file): diff --git a/scripts/odbpy/snap_to_grid.py b/scripts/odbpy/snap_to_grid.py new file mode 100644 index 00000000..f79ef907 --- /dev/null +++ b/scripts/odbpy/snap_to_grid.py @@ -0,0 +1,59 @@ +# Copyright 2022 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import math +from decimal import Decimal + +import click + +from reader import OdbReader + + +def snap_value(value: Decimal, manufacturing_grid: Decimal) -> Decimal: + adjusted = math.floor(value / manufacturing_grid) * manufacturing_grid + if adjusted == Decimal(0): + adjusted = math.ceil(value / manufacturing_grid) * manufacturing_grid + return adjusted + + +@click.command() +@click.option( + "-o", + "--output", + required=True, + help="A text file to which final values are output.", +) +@click.option( + "-l", + "--input-lef", + required=True, + help="Input LEF file (for the manufacturing grid)", +) +@click.argument("input_values", type=Decimal, nargs=-1) +def cli(output, input_lef, input_values): + reader = OdbReader(input_lef, None) + manufacturing_grid = Decimal(reader.db.getTech().getManufacturingGrid()) / Decimal( + reader.db.getTech().getDbUnitsPerMicron() + ) + with open(output, "w") as f: + print( + " ".join( + [str(snap_value(value, manufacturing_grid)) for value in input_values] + ), + end="", + file=f, + ) + + +if __name__ == "__main__": + cli() diff --git a/scripts/openroad/irdrop.tcl b/scripts/openroad/irdrop.tcl new file mode 100644 index 00000000..ef2e4aec --- /dev/null +++ b/scripts/openroad/irdrop.tcl @@ -0,0 +1,37 @@ +# Copyright 2022 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if {[catch {read_lef $::env(MERGED_LEF)} errmsg]} { + puts stderr $errmsg + exit 1 +} + +if {[catch {read_def $::env(CURRENT_DEF)} errmsg]} { + puts stderr $errmsg + exit 1 +} + +foreach lib $::env(LIB_SYNTH_COMPLETE) { + read_liberty $lib +} + +if { [info exists ::env(EXTRA_LIBS) ] } { + foreach lib $::env(EXTRA_LIBS) { + read_liberty $lib + } +} + +source $::env(SCRIPTS_DIR)/openroad/set_rc.tcl + +analyze_power_grid -net $::env(VDD_NET) -outfile $::env(_tmp_save_rpt) diff --git a/scripts/openroad/pdn.tcl b/scripts/openroad/pdn.tcl index ad9d1ddc..f2c61b82 100644 --- a/scripts/openroad/pdn.tcl +++ b/scripts/openroad/pdn.tcl @@ -1,4 +1,4 @@ -# Copyright 2020-2021 Efabless Corporation +# 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. @@ -50,10 +50,4 @@ if { $::env(FP_PDN_CHECK_NODES) } { check_power_grid -net $::env(GND_NET) } -if { $::env(FP_PDN_IRDROP) } { - # set rc values - source $::env(SCRIPTS_DIR)/openroad/set_rc.tcl - analyze_power_grid -net $::env(VDD_NET) -outfile $::env(PGA_RPT_FILE) -} - write_def $::env(SAVE_DEF) diff --git a/scripts/tcl_commands/all.tcl b/scripts/tcl_commands/all.tcl index 6229e4b2..764f4d01 100755 --- a/scripts/tcl_commands/all.tcl +++ b/scripts/tcl_commands/all.tcl @@ -980,11 +980,11 @@ proc set_layer_tracks {args} { } proc run_or_antenna_check {args} { - TIMER::timer_start increment_index - puts_info "Running OpenROAD Antenna Rule Checker..." - + TIMER::timer_start set log [index_file $::env(signoff_logs)/antenna.log] + puts_info "Running OpenROAD Antenna Rule Checker (log: [relpath . $log])..." + run_openroad_script $::env(SCRIPTS_DIR)/openroad/antenna_check.tcl -indexed_log $log set antenna_violators_rpt [index_file $::env(signoff_reports)/antenna_violators.rpt] @@ -1006,6 +1006,22 @@ proc run_antenna_check {args} { } } +proc run_irdrop_report {args} { + increment_index + TIMER::timer_start + set log [index_file $::env(signoff_logs)/irdrop.log] + puts_info "Creating IR Drop Report (log: [relpath . $log])..." + + set rpt [index_file $::env(signoff_reports)/irdrop.rpt] + + set ::env(_tmp_save_rpt) $rpt + run_openroad_script $::env(SCRIPTS_DIR)/openroad/irdrop.tcl -indexed_log $log + unset ::env(_tmp_save_rpt) + + TIMER::timer_stop + exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "ir drop report - openroad" +} + proc or_gui {args} { run_openroad_script -gui $::env(SCRIPTS_DIR)/openroad/gui.tcl } diff --git a/scripts/tcl_commands/cts.tcl b/scripts/tcl_commands/cts.tcl index 4a2483e7..be596f08 100755 --- a/scripts/tcl_commands/cts.tcl +++ b/scripts/tcl_commands/cts.tcl @@ -58,10 +58,8 @@ proc run_cts {args} { set ::env(CURRENT_STAGE) cts increment_index TIMER::timer_start - - set cts_log [index_file $::env(cts_logs)/cts.log] - set cts_log_rel [relpath . $cts_log] - puts_info "Running Clock Tree Synthesis (logging to '$cts_log_rel')..." + set log [index_file $::env(cts_logs)/cts.log] + puts_info "Running Clock Tree Synthesis (log: [relpath . $log])..." if { ! [info exists ::env(CLOCK_NET)] } { set ::env(CLOCK_NET) $::env(CLOCK_PORT) @@ -77,7 +75,7 @@ proc run_cts {args} { trim_lib -input $::env(LIB_SYNTH_COMPLETE) -output $::env(LIB_CTS) -drc_exclude_only } - run_openroad_script $::env(SCRIPTS_DIR)/openroad/cts.tcl -indexed_log $cts_log + run_openroad_script $::env(SCRIPTS_DIR)/openroad/cts.tcl -indexed_log $log check_cts_clock_nets set ::env(cts_reports) $report_tag_holder @@ -101,10 +99,12 @@ proc run_resizer_timing {args} { if { $::env(PL_RESIZER_TIMING_OPTIMIZATIONS) == 1} { increment_index TIMER::timer_start - puts_info "Running Placement Resizer Timing Optimizations..." + set log [index_file $::env(cts_logs)/resizer.log] + puts_info "Running Placement Resizer Timing Optimizations (log: [relpath . $log])..." + set ::env(SAVE_DEF) [index_file $::env(cts_tmpfiles)/resizer_timing.def] set ::env(SAVE_SDC) [index_file $::env(cts_tmpfiles)/resizer_timing.sdc] - run_openroad_script $::env(SCRIPTS_DIR)/openroad/resizer_timing.tcl -indexed_log [index_file $::env(cts_logs)/resizer.log] + run_openroad_script $::env(SCRIPTS_DIR)/openroad/resizer_timing.tcl -indexed_log $log set_def $::env(SAVE_DEF) set ::env(CURRENT_SDC) $::env(SAVE_SDC) diff --git a/scripts/tcl_commands/cvc.tcl b/scripts/tcl_commands/cvc.tcl index 492b0544..52e70fb0 100755 --- a/scripts/tcl_commands/cvc.tcl +++ b/scripts/tcl_commands/cvc.tcl @@ -42,7 +42,8 @@ proc run_lef_cvc {args} { increment_index TIMER::timer_start - puts_info "Running CVC..." + set log [index_file $::env(signoff_logs)/erc_screen.log] + puts_info "Running CVC (log: [relpath . $log])..." # merge cdl views of the optimization library and the base library if they are different if { $::env(STD_CELL_LIBRARY_OPT) != $::env(STD_CELL_LIBRARY) } { @@ -68,7 +69,7 @@ proc run_lef_cvc {args} { # The main event try_catch cvc $::env(CVC_SCRIPTS_DIR)/cvcrc \ - |& tee $::env(TERMINAL_OUTPUT) [index_file $::env(signoff_logs)/erc_screen.log] + |& tee $::env(TERMINAL_OUTPUT) $log TIMER::timer_stop diff --git a/scripts/tcl_commands/floorplan.tcl b/scripts/tcl_commands/floorplan.tcl index fbb56aa6..66f8223b 100755 --- a/scripts/tcl_commands/floorplan.tcl +++ b/scripts/tcl_commands/floorplan.tcl @@ -38,14 +38,16 @@ proc set_core_dims {args} { proc init_floorplan {args} { increment_index - puts_info "Running Initial Floorplanning..." TIMER::timer_start + set log [index_file $::env(floorplan_logs)/initial_fp.log] + puts_info "Running Initial Floorplanning (log: [relpath . $log])..." + set ::env(SAVE_DEF) [index_file $::env(floorplan_tmpfiles)/initial_fp.def] set ::env(SAVE_SDC) [index_file $::env(floorplan_tmpfiles)/initial_fp.sdc] set ::env(fp_report_prefix) [index_file $::env(floorplan_reports)/initial_fp] - run_openroad_script $::env(SCRIPTS_DIR)/openroad/floorplan.tcl -indexed_log [index_file $::env(floorplan_logs)/initial_fp.log] -netlist_in + run_openroad_script $::env(SCRIPTS_DIR)/openroad/floorplan.tcl -indexed_log $log -netlist_in check_floorplan_missing_lef check_floorplan_missing_pins @@ -65,18 +67,29 @@ proc init_floorplan {args} { puts_verbose "Core area width: $core_width" puts_verbose "Core area height: $core_height" + set min_width [expr {$::env(FP_PDN_VOFFSET) + $::env(FP_PDN_VPITCH)}] + set min_height [expr {$::env(FP_PDN_HOFFSET) + $::env(FP_PDN_HPITCH)}] + if { $::env(FP_PDN_AUTO_ADJUST) } { - if { $core_width <= [expr {$::env(FP_PDN_VOFFSET) + $::env(FP_PDN_VPITCH)}] ||\ - $core_height <= [expr {$::env(FP_PDN_HOFFSET) + $::env(FP_PDN_HPITCH)}]} { - puts_warn "Current core area is too small for a power grid. The power grid will be minimized." + if { $core_width <= $min_width || $core_height <= $min_height } { - set ::env(FP_PDN_VOFFSET) [expr {$core_width/8.0}] - set ::env(FP_PDN_HOFFSET) [expr {$core_height/8.0}] + set intermediate [index_file $::env(floorplan_tmpfiles)/minimized_pdn.txt] - set ::env(FP_PDN_VPITCH) [expr {$core_width/4.0}] - set ::env(FP_PDN_HPITCH) [expr {$core_height/4.0}] + try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/odbpy/snap_to_grid.py\ + --output $intermediate\ + --input-lef $::env(MERGED_LEF)\ + [expr {$core_width/8.0}] [expr {$core_height/8.0}] [expr {$core_width/4.0}] [expr {$core_height/4.0}] + + set adjusted_values [cat $intermediate] + + set ::env(FP_PDN_VOFFSET) [lindex $adjusted_values 0] + set ::env(FP_PDN_HOFFSET) [lindex $adjusted_values 1] + + set ::env(FP_PDN_VPITCH) [lindex $adjusted_values 2] + set ::env(FP_PDN_HPITCH) [lindex $adjusted_values 3] + + puts_warn "Current core area is too small for a power grid. The power grid will be minimized." } - } puts_verbose "Final Vertical PDN Offset: $::env(FP_PDN_VOFFSET)" @@ -99,8 +112,10 @@ proc init_floorplan_or {args} { proc place_io_ol {args} { increment_index - puts_info "Running IO Placement..." TIMER::timer_start + set log [index_file $::env(floorplan_logs)/place_io.log] + puts_info "Running IO Placement (log: [relpath . $log])..." + set options { {-lef optional} {-def optional} @@ -157,7 +172,7 @@ proc place_io_ol {args} { --length $arg_values(-length)\ {*}$flags_map(-unmatched_error)\ {*}$arg_values(-extra_args)\ - $arg_values(-def) |& tee [index_file $::env(floorplan_logs)/place_io_ol.log] $::env(TERMINAL_OUTPUT) + $arg_values(-def) |& tee $log $::env(TERMINAL_OUTPUT) set_def $arg_values(-output_def) @@ -167,19 +182,19 @@ proc place_io_ol {args} { proc place_io {args} { increment_index - puts_info "Running IO Placement..." TIMER::timer_start + set log [index_file $::env(floorplan_logs)/io.log] + puts_info "Running IO Placement..." + set ::env(SAVE_DEF) [index_file $::env(floorplan_tmpfiles)/io.def] - run_openroad_script $::env(SCRIPTS_DIR)/openroad/ioplacer.tcl -indexed_log [index_file $::env(floorplan_logs)/io.log] + run_openroad_script $::env(SCRIPTS_DIR)/openroad/ioplacer.tcl -indexed_log $log TIMER::timer_stop exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "ioplace - openroad" set_def $::env(SAVE_DEF) } proc place_contextualized_io {args} { - increment_index - puts_info "Running Contextualized IO Placement..." set options {{-lef required} {-def required}} set flags {} parse_key_args "place_contextualized_io" args arg_values $options flags_map $flags @@ -188,7 +203,11 @@ proc place_contextualized_io {args} { puts_err "Contextual IO placement: def/lef files don't exist, exiting" flow_fail } + + increment_index TIMER::timer_start + set log [index_file $::env(floorplan_logs)/io.contextualize.log] + puts_info "Running Contextualized IO Placement (log: [relpath . $log])..." file copy -force $arg_values(-def) $::env(placement_tmpfiles)/top_level.def file copy -force $arg_values(-lef) $::env(placement_tmpfiles)/top_level.lef @@ -200,7 +219,7 @@ proc place_contextualized_io {args} { --input-lef $::env(MERGED_LEF) \ --top-def $::env(placement_tmpfiles)/top_level.def \ --top-lef $::env(placement_tmpfiles)/top_level.lef \ - $prev_def |& tee [index_file $::env(floorplan_logs)/io.contextualize.log] + $prev_def |& tee puts_info "Custom floorplan created." @@ -226,10 +245,12 @@ proc tap_decap_or {args} { if { $::env(TAP_DECAP_INSERTION) } { if {[info exists ::env(FP_WELLTAP_CELL)] && $::env(FP_WELLTAP_CELL) ne ""} { increment_index - puts_info "Running Tap/Decap Insertion..." TIMER::timer_start + set log [index_file $::env(floorplan_logs)/tap.log] + puts_info "Running Tap/Decap Insertion (log: [relpath . $log])..." + set ::env(SAVE_DEF) $::env(floorplan_results)/$::env(DESIGN_NAME).def - run_openroad_script $::env(SCRIPTS_DIR)/openroad/tapcell.tcl -indexed_log [index_file $::env(floorplan_logs)/tap.log] + run_openroad_script $::env(SCRIPTS_DIR)/openroad/tapcell.tcl -indexed_log $log TIMER::timer_stop exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "tap/decap insertion - openroad" set_def $::env(SAVE_DEF) diff --git a/scripts/tcl_commands/klayout.tcl b/scripts/tcl_commands/klayout.tcl index 8fe17ce7..2de75cc9 100755 --- a/scripts/tcl_commands/klayout.tcl +++ b/scripts/tcl_commands/klayout.tcl @@ -13,11 +13,12 @@ # limitations under the License. proc run_klayout {args} { - TIMER::timer_start set ::env(CURRENT_STAGE) signoff if {[ info exists ::env(KLAYOUT_TECH)] } { increment_index - puts_info "Streaming out GDS-II with Klayout..." + set log [index_file $::env(signoff_logs)/gdsii-klayout.log] + TIMER::timer_start + puts_info "Streaming out GDS-II with Klayout (log: [relpath . $log])..." set gds_files_in "" if { [info exist ::env(EXTRA_GDS_FILES)] } { set gds_files_in $::env(EXTRA_GDS_FILES) @@ -39,7 +40,7 @@ proc run_klayout {args} { -rd "config_file="\ -rd "seal_gds="\ -rd lef_file=$::env(MERGED_LEF)\ - |& tee $::env(TERMINAL_OUTPUT) [index_file $::env(signoff_logs)/gdsii-klayout.log] + |& tee $::env(TERMINAL_OUTPUT) $log if {[info exists ::env(KLAYOUT_PROPERTIES)]} { @@ -69,9 +70,6 @@ proc run_klayout {args} { proc scrot_klayout {args} { if {$::env(TAKE_LAYOUT_SCROT)} { - increment_index - TIMER::timer_start - puts_info "Taking a Screenshot of the Layout Using Klayout..." if {[ info exists ::env(KLAYOUT_TECH)] } { set options { {-log required} @@ -81,7 +79,11 @@ proc scrot_klayout {args} { if {[info exists ::env(CURRENT_GDS)]} { set_if_unset arg_values(-layout) $::env(CURRENT_GDS) } + increment_index + TIMER::timer_start set log [index_file $arg_values(-log)] + puts_info "Creating a screenshot using Klayout (log: [relpath . $log])..." + try_catch bash $::env(SCRIPTS_DIR)/klayout/scrotLayout.sh $::env(KLAYOUT_TECH) $arg_values(-layout) |& tee $::env(TERMINAL_OUTPUT) $log puts_info "Screenshot taken." TIMER::timer_stop @@ -97,10 +99,7 @@ proc scrot_klayout {args} { } proc run_klayout_drc {args} { - TIMER::timer_start if {[ info exists ::env(KLAYOUT_DRC_TECH_SCRIPT)] && [file exists $::env(KLAYOUT_DRC_TECH_SCRIPT)]} { - increment_index - puts_info "Running DRC on the layout using Klayout..." set options { {-gds optional} {-stage optional} @@ -110,7 +109,13 @@ proc run_klayout_drc {args} { set_if_unset arg_values(-gds) $::env(CURRENT_GDS) } set_if_unset arg_values(-stage) magic - try_catch bash $::env(SCRIPTS_DIR)/klayout/run_drc.sh $::env(KLAYOUT_DRC_TECH_SCRIPT) $arg_values(-gds) $arg_values(-gds).lydrc |& tee $::env(TERMINAL_OUTPUT) [index_file $::env(signoff_logs)/$arg_values(-stage).drc.log] + + increment_index + TIMER::timer_start + set log [index_file $::env(signoff_logs)/$arg_values(-stage).drc.log] + puts_info "Running DRC on the layout using Klayout (log: [relpath . $log])..." + + try_catch bash $::env(SCRIPTS_DIR)/klayout/run_drc.sh $::env(KLAYOUT_DRC_TECH_SCRIPT) $arg_values(-gds) $arg_values(-gds).lydrc |& tee $::env(TERMINAL_OUTPUT) $log file copy -force $arg_values(-gds).lydrc [index_file $::env(signoff_reports)/$arg_values(-stage).lydrc] puts_info "Klayout DRC Complete" TIMER::timer_stop @@ -125,10 +130,6 @@ proc run_klayout_drc {args} { } proc run_klayout_gds_xor {args} { - increment_index - index_file $::env(signoff_logs)/xor.log - TIMER::timer_start - puts_info "Running XOR on the layouts using Klayout..." set options { {-layout1 optional} {-layout2 optional} @@ -142,11 +143,17 @@ proc run_klayout_gds_xor {args} { set_if_unset arg_values(-output_gds) $::env(signoff_reports)/$::env(DESIGN_NAME).xor.gds if { [file exists $arg_values(-layout1)]} { if { [file exists $arg_values(-layout2)] } { + + increment_index + TIMER::timer_start + set log [index_file $::env(signoff_logs)/xor.log] + puts_info "Running XOR on the layouts using Klayout (log: [relpath . $log])..." + if { $::env(KLAYOUT_XOR_GDS) } { try_catch bash $::env(SCRIPTS_DIR)/klayout/xor.sh \ $arg_values(-layout1) $arg_values(-layout2) $::env(DESIGN_NAME) \ $arg_values(-output_gds) \ - |& tee $::env(TERMINAL_OUTPUT) [index_file $::env(signoff_logs)/xor.log] + |& tee $::env(TERMINAL_OUTPUT) $log try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/parse_klayout_xor_log.py \ -l [index_file $::env(signoff_logs)/xor.log] \ -o [index_file $::env(signoff_reports)/xor.rpt] diff --git a/scripts/tcl_commands/lvs.tcl b/scripts/tcl_commands/lvs.tcl index 8d6cc7e1..88565a5f 100755 --- a/scripts/tcl_commands/lvs.tcl +++ b/scripts/tcl_commands/lvs.tcl @@ -40,9 +40,6 @@ proc verilog_to_verilogPower {args} { # WORKS ON DEF FILES proc write_powered_verilog {args} { - increment_index - TIMER::timer_start - puts_info "Writing Powered Verilog..." set options { {-def optional} {-lef optional} @@ -63,6 +60,11 @@ proc write_powered_verilog {args} { set_if_unset arg_values(-def_log) /dev/null set_if_unset arg_values(-log) /dev/null + increment_index + TIMER::timer_start + set log [index_file $arg_values(-log)] + puts_info "Writing Powered Verilog (log: [relpath . $log])..." + if { [info exists ::env(SYNTH_USE_PG_PINS_DEFINES)] } { set_if_unset arg_values(-powered_netlist) $::env(synthesis_tmpfiles)/pg_define.v } else { @@ -78,7 +80,7 @@ proc write_powered_verilog {args} { $arg_values(-def) \ |& tee $::env(TERMINAL_OUTPUT) [index_file $arg_values(-def_log)] - write_verilog $arg_values(-output_verilog) -def $arg_values(-output_def) -log [index_file $arg_values(-log)] -canonical + write_verilog $arg_values(-output_verilog) -def $arg_values(-output_def) -log $log -canonical TIMER::timer_stop exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "write powered verilog - openlane" } diff --git a/scripts/tcl_commands/magic.tcl b/scripts/tcl_commands/magic.tcl index 81f79368..48791874 100755 --- a/scripts/tcl_commands/magic.tcl +++ b/scripts/tcl_commands/magic.tcl @@ -16,11 +16,12 @@ proc run_magic {args} { TIMER::timer_start increment_index puts_info "Running Magic to generate various views..." + set ::env(CURRENT_STAGE) signoff # |----------------------------------------------------| # |---------------- 6. TAPE-OUT ---------------------| # |----------------------------------------------------| - puts_info "Streaming out GDS-II with Magic..." - set ::env(CURRENT_STAGE) signoff + set log [index_file $::env(signoff_logs)/gdsii.log] + puts_info "Streaming out GDS-II with Magic (log: [relpath . $log])..." # the following MAGTYPE better be mag for clean GDS generation # use load -dereference to ignore it later if needed @@ -29,7 +30,7 @@ proc run_magic {args} { set ::env(MAGIC_GDS) $::env(signoff_results)/$::env(DESIGN_NAME).magic.gds run_magic_script\ - -indexed_log [index_file $::env(signoff_logs)/gdsii.log]\ + -indexed_log $log\ $::env(SCRIPTS_DIR)/magic/mag_gds.tcl if { $::env(PRIMARY_SIGNOFF_TOOL) == "magic" } { @@ -42,13 +43,13 @@ proc run_magic {args} { scrot_klayout -log $::env(cts_logs)/screenshot.log if { ($::env(MAGIC_GENERATE_LEF) && $::env(MAGIC_GENERATE_MAGLEF)) || $::env(MAGIC_INCLUDE_GDS_POINTERS) } { + set log [index_file $::env(signoff_logs)/gds_ptrs.log] puts_info "Generating MAGLEF views..." # Generate mag file that includes GDS pointers set ::env(MAGTYPE) mag - run_magic_script\ - -indexed_log [index_file $::env(signoff_logs)/gds_ptrs.log]\ - $::env(SCRIPTS_DIR)/magic/gds_pointers.tcl + run_magic_script $::env(SCRIPTS_DIR)/magic/gds_pointers.tcl\ + -indexed_log $log # Only keep the properties section in the file try_catch sed -i -n "/^<< properties >>/,/^<< end >>/p" $::env(signoff_tmpfiles)/gds_ptrs.mag @@ -86,15 +87,15 @@ proc run_magic {args} { proc run_magic_drc {args} { increment_index TIMER::timer_start - puts_info "Running Magic DRC..." + set log [index_file $::env(signoff_logs)/drc.log] + puts_info "Running Magic DRC (log: [relpath . $log])..." set ::env(drc_prefix) $::env(signoff_reports)/drc # Has to be maglef for DRC Checking set ::env(MAGTYPE) maglef - run_magic_script\ - -indexed_log [index_file $::env(signoff_logs)/drc.log]\ - $::env(SCRIPTS_DIR)/magic/drc.tcl + run_magic_script $::env(SCRIPTS_DIR)/magic/drc.tcl\ + -indexed_log $log puts_info "Converting Magic DRC Violations to Magic Readable Format..." try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/drc_rosetta.py magic to_tcl\ @@ -125,13 +126,16 @@ proc run_magic_drc {args} { proc run_magic_spice_export {args} { TIMER::timer_start increment_index + set log "" if { [info exist ::env(MAGIC_EXT_USE_GDS)] && $::env(MAGIC_EXT_USE_GDS) } { set extract_type "gds.spice" - puts_info "Running Magic Spice Export from GDS..." + set log [index_file $::env(signoff_logs)/$extract_type.log] + puts_info "Running Magic Spice Export from GDS (log: [relpath . $log])..." # GDS extracted file design.gds.spice, log file magic_gds.spice.log } else { set extract_type "spice" - puts_info "Running Magic Spice Export from LEF..." + set log [index_file $::env(signoff_logs)/$extract_type.log] + puts_info "Running Magic Spice Export from LEF (log: [relpath . $log])..." # LEF extracted file design.spice (copied to design.lef.spice), log file magic_spice.log } @@ -144,9 +148,8 @@ proc run_magic_spice_export {args} { set ::env(_tmp_magic_feedback_file) $feedback_file set ::env(MAGTYPE) maglef - run_magic_script\ - -indexed_log [index_file $::env(signoff_logs)/$extract_type.log]\ - $::env(SCRIPTS_DIR)/magic/extract_spice.tcl + run_magic_script $::env(SCRIPTS_DIR)/magic/extract_spice.tcl\ + -indexed_log $log unset ::env(_tmp_magic_extract_type) unset ::env(_tmp_magic_feedback_file) @@ -162,14 +165,16 @@ proc run_magic_spice_export {args} { } proc export_magic_view {args} { - increment_index - TIMER::timer_start set options { {-def required} {-output required} } set flags {} parse_key_args "export_magic_view" args arg_values $options flags_map $flags + + increment_index + TIMER::timer_start + set script_dir $::env(signoff_tmpfiles)/magic_mag_save.tcl set stream [open $script_dir w] @@ -193,27 +198,26 @@ proc export_magic_view {args} { proc run_magic_antenna_check {args} { increment_index TIMER::timer_start - puts_info "Running Magic Antenna Checks..." + set log [index_file $::env(signoff_logs)/antenna.log] + puts_info "Running Magic Antenna Checks (log: [relpath . $log])..." + set feedback_file [index_file $::env(signoff_reports)/antenna.feedback.txt] # the following MAGTYPE has to be mag; antennacheck needs to know # about the underlying devices, layers, etc. set ::env(MAGTYPE) mag - set antenna_log [index_file $::env(signoff_logs)/antenna.log] - set ::env(_tmp_feedback_file) $feedback_file - run_magic_script\ - -indexed_log $antenna_log\ - $::env(SCRIPTS_DIR)/magic/antenna_check.tcl + run_magic_script $::env(SCRIPTS_DIR)/magic/antenna_check.tcl\ + -indexed_log $log unset ::env(_tmp_feedback_file) set antenna_violators_rpt [index_file $::env(signoff_reports)/antenna_violators.rpt] # process the log - try_catch awk "/Cell:/ {print \$2}" $antenna_log > $antenna_violators_rpt + try_catch awk "/Cell:/ {print \$2}" $log > $antenna_violators_rpt set ::env(ANTENNA_VIOLATOR_LIST) $antenna_violators_rpt diff --git a/scripts/tcl_commands/placement.tcl b/scripts/tcl_commands/placement.tcl index f4ca18f1..96ca38f4 100755 --- a/scripts/tcl_commands/placement.tcl +++ b/scripts/tcl_commands/placement.tcl @@ -15,7 +15,9 @@ proc global_placement_or {args} { increment_index TIMER::timer_start - puts_info "Running Global Placement..." + set log [index_file $::env(placement_logs)/global.log] + puts_info "Running Global Placement (log: [relpath . $log])..." + set ::env(SAVE_DEF) [index_file $::env(placement_tmpfiles)/global.def] # random initial placement @@ -24,7 +26,7 @@ proc global_placement_or {args} { set ::env(PL_SKIP_INITIAL_PLACEMENT) 1 } - run_openroad_script $::env(SCRIPTS_DIR)/openroad/gpl.tcl -indexed_log [index_file $::env(placement_logs)/global.log] + run_openroad_script $::env(SCRIPTS_DIR)/openroad/gpl.tcl -indexed_log $log # sometimes replace fails with a ZERO exit code; the following is a workaround # until the cause is found and fixed @@ -48,14 +50,15 @@ proc global_placement {args} { proc random_global_placement {args} { increment_index TIMER::timer_start - puts_info "Performing Random Global Placement..." + set log [index_file $::env(placement_logs)/global.log] + puts_info "Performing Random Global Placement (log: [relpath . $log])..." set ::env(SAVE_DEF) [index_file $::env(placement_tmpfiles)/global.def] try_catch $::env(OPENROAD_BIN) -python $::env(SCRIPTS_DIR)/odbpy/random_place.py\ --output $::env(SAVE_DEF) \ --input-lef $::env(MERGED_LEF) \ $::env(CURRENT_DEF) \ - |& tee $::env(TERMINAL_OUTPUT) [index_file $::env(placement_logs)/global.log] + |& tee $::env(TERMINAL_OUTPUT) $log TIMER::timer_stop exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "random global placement - openlane" @@ -72,9 +75,10 @@ proc detailed_placement_or {args} { increment_index TIMER::timer_start - puts_info "Running Detailed Placement..." - set ::env(SAVE_DEF) $arg_values(-def) set log [index_file $arg_values(-log)] + puts_info "Running Detailed Placement (log: [relpath . $log])..." + + set ::env(SAVE_DEF) $arg_values(-def) run_openroad_script $::env(SCRIPTS_DIR)/openroad/dpl.tcl -indexed_log $log set_def $::env(SAVE_DEF) @@ -104,15 +108,16 @@ proc add_macro_placement {args} { } proc manual_macro_placement {args} { - increment_index - TIMER::timer_start - puts_info "Performing Manual Macro Placement..." - set options {} set flags {-f} parse_key_args "manual_macro_placement" args arg_values $options flags_map $flags + increment_index + TIMER::timer_start + set log [index_file $::env(placement_logs)/macro_placement.log] + puts_info "Performing Manual Macro Placement (log: [relpath . $log])..." + set fbasename [file rootname $::env(CURRENT_DEF)] set output_def ${fbasename}.macro_placement.def @@ -129,7 +134,7 @@ proc manual_macro_placement {args} { try_catch openroad -python\ $::env(SCRIPTS_DIR)/odbpy/manual_macro_place.py {*}$arg_list |&\ - tee $::env(TERMINAL_OUTPUT) [index_file $::env(placement_logs)/macro_placement.log] + tee $::env(TERMINAL_OUTPUT) $log set_def $output_def } @@ -137,12 +142,13 @@ proc manual_macro_placement {args} { proc basic_macro_placement {args} { increment_index TIMER::timer_start - puts_info "Running basic macro placement..." + set log [index_file $::env(placement_logs)/basic_mp.log] + puts_info "Running basic macro placement (log: [relpath . $log])..." set fbasename [file rootname $::env(CURRENT_DEF)] set ::env(SAVE_DEF) ${fbasename}.macro_placement.def - run_openroad_script $::env(SCRIPTS_DIR)/openroad/basic_mp.tcl -indexed_log [index_file $::env(placement_logs)/basic_mp.log] + run_openroad_script $::env(SCRIPTS_DIR)/openroad/basic_mp.tcl -indexed_log $log check_macro_placer_num_solns @@ -186,10 +192,12 @@ proc run_resizer_design {args} { if { $::env(PL_RESIZER_DESIGN_OPTIMIZATIONS) == 1} { increment_index TIMER::timer_start - puts_info "Running Placement Resizer Design Optimizations..." + set log [index_file $::env(placement_logs)/resizer.log] + puts_info "Running Placement Resizer Design Optimizations (log: [relpath . $log])..." + set ::env(SAVE_DEF) [index_file $::env(placement_tmpfiles)/resizer.def] set ::env(SAVE_SDC) [index_file $::env(placement_tmpfiles)/resizer.sdc] - run_openroad_script $::env(SCRIPTS_DIR)/openroad/resizer.tcl -indexed_log [index_file $::env(placement_logs)/resizer.log] + run_openroad_script $::env(SCRIPTS_DIR)/openroad/resizer.tcl -indexed_log $log set_def $::env(SAVE_DEF) set ::env(CURRENT_SDC) $::env(SAVE_SDC) @@ -212,7 +220,8 @@ proc remove_buffers_from_ports {args} { # analog ports. increment_index TIMER::timer_start - puts_info "Removing Buffers from Ports (If Applicable)..." + set log [index_file $::env(placement_logs)/remove_buffers_from_ports.log] + puts_info "Removing Buffers from Ports (If Applicable) (log: [relpath . $log])..." set fbasename [file rootname $::env(CURRENT_DEF)] set ::env(SAVE_DEF) ${fbasename}.buffers_removed.def @@ -221,7 +230,7 @@ proc remove_buffers_from_ports {args} { --input-lef $::env(MERGED_LEF)\ --ports $::env(DONT_BUFFER_PORTS)\ $::env(CURRENT_DEF)\ - |& tee $::env(TERMINAL_OUTPUT) [index_file $::env(placement_logs)/remove_buffers_from_ports.log] + |& tee $::env(TERMINAL_OUTPUT) $log set_def $::env(SAVE_DEF) TIMER::timer_stop diff --git a/scripts/tcl_commands/routing.tcl b/scripts/tcl_commands/routing.tcl index 4a4c3f58..84276779 100755 --- a/scripts/tcl_commands/routing.tcl +++ b/scripts/tcl_commands/routing.tcl @@ -97,6 +97,7 @@ proc global_routing {args} { increment_index TIMER::timer_start puts_info "Running Global Routing..." + set ::env(SAVE_GUIDE) [index_file $::env(routing_tmpfiles)/global.guide] set ::env(SAVE_DEF) [index_file $::env(routing_tmpfiles)/global.def] @@ -128,18 +129,15 @@ proc detailed_routing_tritonroute {args} { increment_index TIMER::timer_start - - set drt_log [index_file $::env(routing_logs)/detailed.log] - set drt_log_relative [relpath . $drt_log] - - puts_info "Running Detailed Routing (logging to '$drt_log_relative')..." + set log [index_file $::env(routing_logs)/detailed.log] + puts_info "Running Detailed Routing (log: [relpath . $log])..." set ::env(SAVE_DEF) $::env(routing_results)/$::env(DESIGN_NAME).def set ::env(_tmp_drt_file_prefix) $::env(routing_tmpfiles)/drt set ::env(_tmp_drt_rpt_prefix) $::env(routing_reports)/drt - run_openroad_script $::env(SCRIPTS_DIR)/openroad/droute.tcl -indexed_log $drt_log + run_openroad_script $::env(SCRIPTS_DIR)/openroad/droute.tcl -indexed_log $log unset ::env(_tmp_drt_file_prefix) unset ::env(_tmp_drt_rpt_prefix) @@ -169,23 +167,27 @@ proc ins_fill_cells_or {args} { } proc ins_fill_cells {args} { - increment_index - - if {$::env(FILL_INSERTION)} { - TIMER::timer_start - puts_info "Running Fill Insertion..." - set ::env(SAVE_DEF) [index_file $::env(routing_tmpfiles)/fill.def] - run_openroad_script $::env(SCRIPTS_DIR)/openroad/fill.tcl -indexed_log [index_file $::env(routing_logs)/fill.log] - set_def $::env(SAVE_DEF) - TIMER::timer_stop - exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "fill insertion - openroad" + if {!$::env(FILL_INSERTION)} { + return } + increment_index + TIMER::timer_start + set log [index_file $::env(routing_logs)/fill.log] + puts_info "Running Fill Insertion (log: [relpath . $log])..." + + set ::env(SAVE_DEF) [index_file $::env(routing_tmpfiles)/fill.def] + + run_openroad_script $::env(SCRIPTS_DIR)/openroad/fill.tcl -indexed_log $log + set_def $::env(SAVE_DEF) + TIMER::timer_stop + exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "fill insertion - openroad" } proc power_routing {args} { increment_index TIMER::timer_start - puts_info "Routing top-level power nets..." + set log [index_file $::env(routing_logs)/power_routing.log] + puts_info "Routing top-level power nets (log: [relpath . $log])..." set options { {-lef optional} @@ -213,7 +215,7 @@ proc power_routing {args} { --output $arg_values(-output_def)\ {*}$arg_values(-extra_args)\ $arg_values(-def)\ - |& tee [index_file $::env(routing_logs)/power_routing.log] $::env(TERMINAL_OUTPUT) + |& tee $log $::env(TERMINAL_OUTPUT) set_def $arg_values(-output_def) TIMER::timer_stop @@ -223,10 +225,10 @@ proc power_routing {args} { proc gen_pdn {args} { increment_index TIMER::timer_start - puts_info "Generating PDN..." + set log [index_file $::env(floorplan_logs)/pdn.log] + puts_info "Generating PDN (log: [relpath . $log])..." set ::env(SAVE_DEF) [index_file $::env(floorplan_tmpfiles)/pdn.def] - set ::env(PGA_RPT_FILE) [index_file $::env(floorplan_tmpfiles)/pdn.pga.rpt] if { ! [info exists ::env(VDD_NET)] } { set ::env(VDD_NET) $::env(VDD_PIN) @@ -236,9 +238,7 @@ proc gen_pdn {args} { set ::env(GND_NET) $::env(GND_PIN) } - run_openroad_script $::env(SCRIPTS_DIR)/openroad/pdn.tcl \ - |& -indexed_log [index_file $::env(floorplan_logs)/pdn.log] - + run_openroad_script $::env(SCRIPTS_DIR)/openroad/pdn.tcl -indexed_log $log TIMER::timer_stop exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "pdn generation - openroad" @@ -252,10 +252,12 @@ proc gen_pdn {args} { proc ins_diode_cells_1 {args} { increment_index TIMER::timer_start - puts_info "Running Diode Insertion..." + set log [index_file $::env(routing_logs)/diodes.log] + puts_info "Running Diode Insertion (log: [relpath . $log])..." + set ::env(SAVE_DEF) [index_file $::env(routing_tmpfiles)/diodes.def] - run_openroad_script $::env(SCRIPTS_DIR)/openroad/diodes.tcl -indexed_log [index_file $::env(routing_logs)/diodes.log] + run_openroad_script $::env(SCRIPTS_DIR)/openroad/diodes.tcl -indexed_log $log set_def $::env(SAVE_DEF) @@ -272,7 +274,9 @@ proc ins_diode_cells_1 {args} { proc ins_diode_cells_4 {args} { increment_index TIMER::timer_start - puts_info "Running Diode Insertion..." + set log [index_file $::env(routing_logs)/diodes.log] + puts_info "Running Diode Insertion (log: [relpath . $log])..." + set ::env(SAVE_DEF) [index_file $::env(routing_tmpfiles)/diodes.def] # Select diode cell @@ -295,7 +299,7 @@ proc ins_diode_cells_4 {args} { --diode-cell $::env(DIODE_CELL)\ --diode-pin $::env(DIODE_CELL_PIN)\ --fake-diode-cell $::antenna_cell_name\ - $::env(CURRENT_DEF) |& tee $::env(TERMINAL_OUTPUT) [index_file $::env(routing_logs)/diodes.log] + $::env(CURRENT_DEF) |& tee $::env(TERMINAL_OUTPUT) $log set_def $::env(SAVE_DEF) @@ -356,15 +360,15 @@ proc run_spef_extraction {args} { assert_files_exist "$::env(RCX_RULESET) $::env(RCX_LEF)" increment_index - TIMER::timer_start set log [index_file $arg_values(-log)] + TIMER::timer_start set ec_postfix "" if { [info exists arg_values(-process_corner)]} { set ec_postfix " at the $arg_values(-process_corner) process corner" } - puts_info "Running SPEF Extraction$ec_postfix..." + puts_info "Running SPEF Extraction$ec_postfix (log: [relpath . $log])..." if { $::env(SPEF_EXTRACTOR) == "def2spef" } { puts_warn "def2spef/spef_extractor has been removed. OpenROAD OpenRCX will be used instead." @@ -451,10 +455,13 @@ proc run_resizer_timing_routing {args} { if { $::env(GLB_RESIZER_TIMING_OPTIMIZATIONS) == 1} { increment_index TIMER::timer_start - puts_info "Running Global Routing Resizer Timing Optimizations..." + set log [index_file $::env(routing_logs)/resizer.log] + puts_info "Running Global Routing Resizer Timing Optimizations (log: [relpath . $log])..." + set ::env(SAVE_DEF) [index_file $::env(routing_tmpfiles)/resizer_timing.def] set ::env(SAVE_SDC) [index_file $::env(routing_tmpfiles)/resizer_timing.sdc] - run_openroad_script $::env(SCRIPTS_DIR)/openroad/resizer_routing_timing.tcl -indexed_log [index_file $::env(routing_logs)/resizer.log] + + run_openroad_script $::env(SCRIPTS_DIR)/openroad/resizer_routing_timing.tcl -indexed_log $log set_def $::env(SAVE_DEF) set ::env(CURRENT_SDC) $::env(SAVE_SDC) diff --git a/scripts/tcl_commands/sta.tcl b/scripts/tcl_commands/sta.tcl index 8c988db1..bf538cca 100644 --- a/scripts/tcl_commands/sta.tcl +++ b/scripts/tcl_commands/sta.tcl @@ -30,23 +30,23 @@ proc run_sta {args} { set ::env(STA_LEF) $arg_values(-lef) set ::env(RUN_STANDALONE) 1 - increment_index - TIMER::timer_start - set corner_prefix "Single-Corner" if { $multi_corner } { set corner_prefix "Multi-Corner" } + set process_corner_postfix "" if { [info exists arg_values(-process_corner)]} { set process_corner_postfix " at the $arg_values(-process_corner) process corner" } - puts_info "Running $corner_prefix Static Timing Analysis$process_corner_postfix..." + + increment_index + TIMER::timer_start + set log [index_file $arg_values(-log)] + puts_info "Running $corner_prefix Static Timing Analysis$process_corner_postfix (log: [relpath . $log])..." set ::env(STA_PRE_CTS) $pre_cts - set log [index_file $arg_values(-log)] - if {[info exists ::env(CLOCK_PORT)]} { if { $multi_corner == 1 } { run_openroad_script $::env(SCRIPTS_DIR)/openroad/sta_multi_corner.tcl \ diff --git a/scripts/tcl_commands/synthesis.tcl b/scripts/tcl_commands/synthesis.tcl index b1b6cd75..794178a5 100755 --- a/scripts/tcl_commands/synthesis.tcl +++ b/scripts/tcl_commands/synthesis.tcl @@ -25,6 +25,7 @@ proc run_yosys {args} { set options { {-output optional} + {-log optional} } set flags { -no_set_netlist @@ -32,6 +33,8 @@ proc run_yosys {args} { parse_key_args "run_yosys" args arg_values $options flags_map $flags + set_if_unset arg_values(-log) /dev/null + if { [info exists arg_values(-output)] } { set ::env(SAVE_NETLIST) $arg_values(-output) } else { @@ -61,7 +64,7 @@ proc run_yosys {args} { try_catch $::env(SYNTH_BIN) \ -c $::env(SYNTH_SCRIPT) \ - -l [index_file $::env(synthesis_logs)/synthesis.log] \ + -l $arg_values(-log)\ |& tee $::env(TERMINAL_OUTPUT) if { ! [info exists flags_map(-no_set_netlist)] } { @@ -112,14 +115,16 @@ proc run_synth_exploration {args} { proc run_synthesis {args} { increment_index TIMER::timer_start - puts_info "Running Synthesis..." + set log [index_file $::env(synthesis_logs)/synthesis.log] + puts_info "Running Synthesis (log: [relpath . $log])..." + set ::env(CURRENT_SDC) $::env(BASE_SDC_FILE) # in-place insertion if { [file exists $::env(synthesis_results)/$::env(DESIGN_NAME).v] } { puts_warn "A netlist at $::env(synthesis_results)/$::env(DESIGN_NAME).v already exists. Synthesis will be skipped." set_netlist $::env(synthesis_results)/$::env(DESIGN_NAME).v } else { - run_yosys + run_yosys -log $log } TIMER::timer_stop exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "synthesis - yosys" @@ -187,11 +192,12 @@ proc yosys_rewrite_verilog {filename} { increment_index TIMER::timer_start - puts_info "Rewriting $filename to $::env(SAVE_NETLIST) using Yosys..." + set log [index_file $::env(synthesis_logs)/rewrite_verilog.log] + puts_info "Rewriting $filename to $::env(SAVE_NETLIST) using Yosys (log: [relpath . $log])..." try_catch $::env(SYNTH_BIN) \ -c $::env(SCRIPTS_DIR)/yosys/rewrite_verilog.tcl \ - -l [index_file $::env(synthesis_logs)/rewrite_verilog.log] + -l $log TIMER::timer_stop exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "verilog rewrite - yosys" @@ -223,10 +229,11 @@ proc logic_equiv_check {args} { } increment_index TIMER::timer_start - puts_info "Running LEC: $::env(LEC_LHS_NETLIST) Vs. $::env(LEC_RHS_NETLIST)" + set log [index_file $::env(synthesis_logs).equiv.log] + puts_info "Running LEC: $::env(LEC_LHS_NETLIST) Vs. $::env(LEC_RHS_NETLIST) (log: [relpath . $log])..." - if { [catch {exec $::env(SYNTH_BIN) -c $::env(SCRIPTS_DIR)/yosys/logic_equiv_check.tcl -l [index_file $::env(synthesis_logs).equiv.log] |& tee $::env(TERMINAL_OUTPUT)} ]} { + if { [catch {exec $::env(SYNTH_BIN) -c $::env(SCRIPTS_DIR)/yosys/logic_equiv_check.tcl -l $log |& tee $::env(TERMINAL_OUTPUT)} ]} { puts_err "$::env(LEC_LHS_NETLIST) is not logically equivalent to $::env(LEC_RHS_NETLIST)." TIMER::timer_stop exec echo "[TIMER::get_runtime]" | python3 $::env(SCRIPTS_DIR)/write_runtime.py "logic equivalence check - yosys"