Skip to content

flow: AUTO_MEMORIES_DIR, where AUTO_MEMORIES' views are written and read - #4824

Open
oharboe wants to merge 1 commit into
The-OpenROAD-Project:masterfrom
oharboe:auto-memories-dir
Open

oharboe wants to merge 1 commit into
The-OpenROAD-Project:masterfrom
oharboe:auto-memories-dir

Conversation

@oharboe

@oharboe oharboe commented Nov 11, 2026 •

Copy link
Copy Markdown
Collaborator

TL;DR: AUTO_MEMORIES_DIR names the directory AUTO_MEMORIES writes its generated views and lists to in synthesis and every later stage reads them from. It defaults to $(RESULTS_DIR)/memories, so with the default every path is what it was. Setting it lets a FLOW_INPUT_VARIANT fork run on another variant's AUTO_MEMORIES synthesis, which until now was refused outright.

Why

Synthesis wrote AUTO_MEMORIES' views into $(RESULTS_DIR)/memories, and every later stage read them from its own RESULTS_DIR. A variant that runs stages on another variant's synthesis (FLOW_INPUT_VARIANT, #4812) has no memories of its own, so load_stage_input refused AUTO_MEMORIES=1 in a fork.

export AUTO_MEMORIES_DIR ?= $(RESULTS_DIR)/memories

How it works with FLOW_INPUT_VARIANT

A fork sets AUTO_MEMORIES_DIR to the memories of the variant that synthesised them, for every stage it runs, and FLOW_INPUT_VARIANT for the first:

make DESIGN_CONFIG=... FLOW_VARIANT=base cts
make DESIGN_CONFIG=... FLOW_VARIANT=fork FLOW_INPUT_VARIANT=base \
  AUTO_MEMORIES_DIR=$PWD/results/asap7/<design>/base/memories do-grt
make DESIGN_CONFIG=... FLOW_VARIANT=fork \
  AUTO_MEMORIES_DIR=$PWD/results/asap7/<design>/base/memories do-route do-final

The two variables answer different questions, which is why there are two: FLOW_INPUT_VARIANT is where one stage's input comes from, and holds for the first stage of a fork only; AUTO_MEMORIES_DIR is where synthesis's memories are, and holds for every stage after synthesis. The memories are read in place; nothing is copied.

load_stage_input no longer refuses AUTO_MEMORIES in a fork; it stops only when AUTO_MEMORIES_DIR is still the fork's own directory, where there are no memories, and says to set it. "Own" is compared as a path, not a string (abspath in the Makefile, file normalize in Tcl), so a trailing slash or an absolute spelling of the default still counts.

What reads it

  • gen_memories.py --out-dir (the writer) and clean_synth
  • util.tcl: the lists (auto_memories_names) and views (auto_memories_areas, auto_memories_views), so load_design, read_liberty.tcl and macro_place.tcl
  • synth_preamble.tcl (inlined register files), regfile_dissolve.tcl
  • the KLayout technology's LEFs (--blackboxes) and def2stream.py's blackbox list

No stages in variables.yaml, like AUTO_MEMORIES: every step that reads the views needs it, generate_abstract among them, and erase_non_stage_variables would otherwise clear it there.

In the Makefile, a fork's klayout.lyt depends on the other variant's blackboxes.txt, not on its own memories.json, so make does not regenerate memories into a directory it only reads; and clean_synth removes AUTO_MEMORIES_DIR only when it is the variant's own, never another variant's memories read in place.

def2stream.auto_memories_cells reads AUTO_MEMORIES_DIR and stops when it is unset; RESULTS_DIR is no stand-in, since the memories may be another variant's.

Testing

  • tclfmt/tclint 0.7.0 (the pinned requirements_lock.txt) clean; black 26.10.1 clean; FlowVariables.md regenerated with generate-variables-docs.py, yamlfix clean.
  • flow/test/test_def2stream.py: 20 tests pass, including the updated auto_memories_cells tests; flow/scripts/memories/gen_memories_test.py and flow/test/test_memory_max_bits.py pass.
  • In a Bazel build carrying this change, with AUTO_MEMORIES_DIR set once by synthesis to its own results:
a variant whose floorplan runs on another variant's AUTO_MEMORIES synthesis (SYNTH_HIERARCHICAL, a 2048×32 memory), memories not copied 2_floorplan.odb and .sdc byte-identical to the synthesising variant's own floorplan
the same with AUTO_MEMORIES_DIR left at the default stops at AUTO_MEMORIES=1 reads the memories from AUTO_MEMORIES_DIR, this variant's, shared, and FLOW_INPUT_VARIANT=base reads the design from another. Set AUTO_MEMORIES_DIR ...
pre-layout and CTS abstracts of AUTO_MEMORIES designs, register-file flows (dissolve, inline, keep) pass

🤖 Generated with Claude Code

@gemini-code-assist gemini-code-assist Bot left a comment

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.

Code Review

This pull request introduces AUTO_MEMORIES_DIR and FLOW_INPUT_VARIANT to allow flow variants to share and read synthesis memories and stage inputs from other variants without copying. The changes update the documentation, Makefile, and Tcl scripts to use these variables and introduce helper functions for robust file handling. The review feedback suggests protecting shared memories from being deleted during clean_synth, using file normalize for path comparisons, and adding explicit error checks with clear messages when required memory list files are missing.

Comment thread flow/Makefile Resolved
Comment thread flow/scripts/load.tcl Resolved
Comment thread flow/scripts/util.tcl Resolved
Comment thread flow/scripts/util.tcl Resolved
@openroad-ci

openroad-ci commented Nov 11, 2026 •

Copy link
Copy Markdown
Member

🔍 QoR check

Metrics reflect the PR merge build — i.e. what will land on the target branch.

Commit 951071c · Jenkins build #5 · Baseline: build · View build on dashboard

62 design(s) checked — 0 with regression(s), 0 without a comparable baseline.

⚠️ 51 design(s) were compared against an approximate baseline, not the build at this PR's merge base, so changes already on the target branch can show up as regressions.

Before, synthesis wrote AUTO_MEMORIES' generated views and lists into
$(RESULTS_DIR)/memories and every later stage read them from its own
RESULTS_DIR. A variant that runs stages on another variant's synthesis
(FLOW_INPUT_VARIANT) had no memories of its own, so load_stage_input
refused AUTO_MEMORIES=1 outright.

Now AUTO_MEMORIES_DIR names the directory, with an overridable default:

  export AUTO_MEMORIES_DIR ?= $(RESULTS_DIR)/memories

Synthesis writes there (gen_memories.py --out-dir), and every reader
goes through it: util.tcl's lists and views, synthesis's inlined
register files, regfile_dissolve.tcl, the KLayout technology's LEFs and
def2stream.py's blackbox list. With the default nothing changes.

With FLOW_INPUT_VARIANT: a variant forked off another sets
AUTO_MEMORIES_DIR to that variant's memories for every stage it runs,
next to FLOW_INPUT_VARIANT=<variant> for the first one, and reads the
memories in place, nothing copied. load_stage_input now stops only when
AUTO_MEMORIES_DIR is still this variant's own directory, and says to
set it. The comparison is by path, not by string (abspath in the
Makefile, file normalize in Tcl), so a trailing slash or an absolute
spelling of the default still counts as this variant's.

A fork's klayout.lyt depends on the other variant's blackboxes.txt, not
on this variant's memories.json, so make does not regenerate memories
into a directory it only reads, and clean_synth removes
AUTO_MEMORIES_DIR only when it is this variant's own.

def2stream.auto_memories_cells reads AUTO_MEMORIES_DIR and stops when it
is unset; RESULTS_DIR is no stand-in, as the memories may be another
variant's. Its tests give AUTO_MEMORIES_DIR accordingly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
@oharboe
oharboe marked this pull request as ready for review November 12, 2026 20:07
@oharboe
oharboe requested a review from maliberty November 12, 2026 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants