Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions flow/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,26 @@ $(RESULTS_DIR)/1_1_yosys_canonicalize.rtlil: $(RESULTS_DIR)/memories.json
$(OBJECTS_DIR)/klayout.lyt: $(RESULTS_DIR)/memories.json
endif

# OpenROAD stages read binary liberty (.blib) files, written before 1_synth.
# Yosys reads the text libraries.
export BINARY_LIBS_DIR = $(OBJECTS_DIR)/lib
BINARY_LIBS_STAMP = $(BINARY_LIBS_DIR)/binary_libs.stamp

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stamp depends on library timestamps but not on the library list. On asap7, building with the default CORNER and then running with CORNER=WC leaves the stamp up to date. Every stage then warns FLW-0025 for each SS library and reads the text files, so the speedup is lost until a manual make do-binary-libs. Changing ADDITIONAL_LIBS does the same. Making the stamp also depend on a file that records the list, rewritten only when the list changes, would fix it.

# Generated corner libraries (BLOCKS abstracts) have no make rule.
BINARY_LIBS_CORNER_SOURCES := $(foreach corner,$(CORNERS),$($(shell echo $(corner) | tr a-z A-Z)_LIB_FILES))
BINARY_LIBS_SOURCES := $(LIB_FILES) $(wildcard $(BINARY_LIBS_CORNER_SOURCES))

$(BINARY_LIBS_STAMP): $(BINARY_LIBS_SOURCES) $(SCRIPTS_DIR)/write_binary_libs.tcl $(wildcard $(OPENROAD_EXE))
$(UNSET_AND_MAKE) do-binary-libs

.PHONY: do-binary-libs
do-binary-libs:
mkdir -p $(BINARY_LIBS_DIR) $(LOG_DIR)
$(RUN_CMD) --log $(abspath $(LOG_DIR)/write_binary_libs.log) --tee -- $(OPENROAD_CMD) $(SCRIPTS_DIR)/write_binary_libs.tcl
touch $(BINARY_LIBS_STAMP)

# Order-only here and below, so regenerating the .blib files does not rerun the flow.
$(RESULTS_DIR)/1_synth.odb: | $(BINARY_LIBS_STAMP)

.PHONY: do-yosys
do-yosys: yosys-dependencies
$(SCRIPTS_DIR)/synth.sh $(SYNTH_SCRIPT) $(LOG_DIR)/1_2_yosys.log
Expand Down Expand Up @@ -355,6 +375,7 @@ endef

define OPEN_GUI
.PHONY: open_$(1) gui_$(1) web_$(1)
open_$(1) gui_$(1) web_$(1): | $(BINARY_LIBS_STAMP)
open_$(1):
$(2)=$(RESULTS_DIR)/$(1) $(OPENROAD_NO_EXIT_CMD) $(SCRIPTS_DIR)/open.tcl
gui_$(1):
Expand Down Expand Up @@ -403,7 +424,7 @@ $(eval $(call OPEN_GUI_SHORTCUT,$(1),$(1).odb))
endif

.PHONY: do-$(1)
do-$(1): $(DO_STEP_DEPS_$(1)) $(OBJECTS_DIR)/copyright.txt
do-$(1): $(DO_STEP_DEPS_$(1)) $(OBJECTS_DIR)/copyright.txt | $(BINARY_LIBS_STAMP)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work with bazel-orfs? Each stage runs make do- in its own sandbox, where the stamp from earlier stages probably isn't present. So every stage would redo the full conversion, about 45 s per stage on your large PDK. Also, orfs_run_executable documents that make run writes only run.log and treats OBJECTS_DIR as read-only, but run now also writes .blib files there. Could we get confirmation from the bazel-orfs side, and maybe a variable to turn the binary libraries off?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for thinking of bazel-orfs 🥹

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Makefile today keeps dependencies and execution apart. The file targets and stage aliases ($(RESULTS_DIR)/1_synth.odb, synth, floorplan, ...) carry the dependencies. The do- targets run one step with what is in the tree, and open_*, gui_*, web_* and run run on what is there. bazel-orfs relies on that split: it tracks the dependencies itself and calls the do- targets, and make does the same for the make flow.

Binary liberty fits that design like this:

  • do-binary-libs is a step like the other do- targets.
  • The make flow's dependency goes on the file target, as this PR does with $(RESULTS_DIR)/1_synth.odb: | $(BINARY_LIBS_STAMP). The do-$(1), open_$(1) gui_$(1) web_$(1) and run targets stay as they are.
  • BINARY_LIBS_DIR is the one variable connecting the two: do-binary-libs writes the .blib files into it, and the other steps read them from it. To let a flow set it:
    • In flow/Makefile, export BINARY_LIBS_DIR ?= $(OBJECTS_DIR)/lib. A design's variables reach make through DESIGN_CONFIG as ?= assignments, and ?= here lets that value, or one from the environment, take effect. The make flow keeps the default.
    • In flow/scripts/variables.yaml, an entry next to LIB_FILES, with no stages:, since every OpenROAD step reads liberty:
      BINARY_LIBS_DIR:
        description: >
          Directory of binary liberty (.blib) files, one per library in
          LIB_FILES or <CORNER>_LIB_FILES, named after the library.
          do-binary-libs writes them; the OpenROAD steps read them and
          read the text library when a .blib is absent.
          Defaults to $(OBJECTS_DIR)/lib.
    • binary_lib_dir in util.tcl already reads $::env(BINARY_LIBS_DIR) and needs no change.

With that, bazel-orfs runs do-binary-libs once per library set as an action of its own. Its output directory is cached, and each stage gets BINARY_LIBS_DIR pointing at it. The make flow keeps $(OBJECTS_DIR)/lib and gets the same speedup through its own dependency chain.

$(SCRIPTS_DIR)/flow.sh $(1) $(3)
endef

Expand Down Expand Up @@ -912,7 +933,7 @@ klayout:
$(SCRIPTS_DIR)/klayout.sh

.phony: run
run:
run: | $(BINARY_LIBS_STAMP)
@mkdir -p $(RESULTS_DIR) $(LOG_DIR) $(REPORTS_DIR) $(OBJECTS_DIR)
$(RUN_CMD) --log $(abspath $(LOG_DIR)/$(RUN_LOG_NAME_STEM).log) --tee -- $(OPENROAD_CMD) -no_splash $(if $(filter %.py,$(RUN_SCRIPT)),-python) $(RUN_SCRIPT)

Expand Down
4 changes: 2 additions & 2 deletions flow/scripts/read_liberty.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ if { [env_var_exists_and_non_empty CORNERS] } {
foreach corner $::env(CORNERS) {
set LIBKEY "[string toupper $corner]_LIB_FILES"
foreach libFile $::env($LIBKEY) {
log_cmd read_liberty -corner $corner $libFile
log_cmd read_liberty -corner $corner [lib_file_to_read $libFile]
}
unset LIBKEY
}
unset corner
} else {
## no corner
foreach libFile $::env(LIB_FILES) {
log_cmd read_liberty $libFile
log_cmd read_liberty [lib_file_to_read $libFile]
}
}

Expand Down
24 changes: 24 additions & 0 deletions flow/scripts/util.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -431,3 +431,27 @@ proc source_step_tcl { hook_type step_name } {
set env_var "${hook_type}_${step_name}_TCL"
source_env_var_if_exists $env_var
}

# Binary liberty (.blib) files written by write_binary_libs.tcl
proc binary_lib_dir { } {
if { [env_var_exists_and_non_empty BINARY_LIBS_DIR] } {
return $::env(BINARY_LIBS_DIR)
}
return [file join $::env(OBJECTS_DIR) lib]
}

proc binary_lib_path { lib_file } {
set name [file tail $lib_file]
regsub {\.gz$} $name "" name
return [file join [binary_lib_dir] "[file rootname $name].blib"]
}

# Falls back to the text library when its .blib was not generated
proc lib_file_to_read { lib_file } {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lib_file_to_read uses .blib whenever it exists, but nothing checks that it was made from this library. The stamp is only rebuilt when a library is newer than it. I tested this with the make flow and a stand-in for openroad. I built with ADDITIONAL_LIBS=libA/macro.lib, then switched to libB/macro.lib, which has the same name and an older timestamp. Make said the stamp was up to date, and the stage read macro.blib with libA's content, with no warning. That gives wrong timing from a library swap that tar or cp -p can easily cause. Could write_binary_libs.tcl write a manifest (.blib --> full source path, size, modification time), and lib_file_to_read use the .blib only when the manifest matches, falling back to the text library with FLW-0025 otherwise?

set blib [binary_lib_path $lib_file]
if { [file exists $blib] } {
return $blib
}
utl::warn FLW 25 "$blib not found, reading $lib_file."
return $lib_file
}
31 changes: 31 additions & 0 deletions flow/scripts/write_binary_libs.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Write binary liberty (.blib) files for the OpenROAD stages
source $::env(SCRIPTS_DIR)/util.tcl

set lib_files {}
if { [env_var_exists_and_non_empty CORNERS] } {
foreach corner $::env(CORNERS) {
set LIBKEY "[string toupper $corner]_LIB_FILES"
lappend lib_files {*}$::env($LIBKEY)
}
} else {
lappend lib_files {*}$::env(LIB_FILES)
}

set blib_dir [binary_lib_dir]
file mkdir $blib_dir

# .blib files are named after the library, so names must be unique
array set blib_sources {}
foreach lib_file [lsort -unique $lib_files] {
set blib [binary_lib_path $lib_file]
if { [info exists blib_sources($blib)] } {
# The same library spelled differently, e.g. foo.lib and ./foo.lib
if { [file normalize $blib_sources($blib)] eq [file normalize $lib_file] } {
continue
}
error "Liberty files $blib_sources($blib) and $lib_file both map to $blib"
}
set blib_sources($blib) $lib_file
log_cmd write_liberty_binary $lib_file $blib
}
Comment thread
eder-matheus marked this conversation as resolved.
puts "Wrote [array size blib_sources] binary liberty files to $blib_dir"
2 changes: 1 addition & 1 deletion tools/OpenROAD
Submodule OpenROAD updated 592 files