Skip to content

sync - #2

Open
nanocoh wants to merge 4911 commits into
keplertech:masterfrom
The-OpenROAD-Project:master
Open

nanocoh wants to merge 4911 commits into
keplertech:masterfrom
The-OpenROAD-Project:master

Conversation

@nanocoh

@nanocoh nanocoh commented May 23, 2026

Copy link
Copy Markdown

Summary

[Describe your changes here]

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring
  • Documentation update

Impact

[How does this change the tool's behavior?]

Verification

  • I have verified that the local build succeeds (./etc/Build.sh).
  • I have run the relevant tests and they pass.
  • My code follows the repository's formatting guidelines.
  • I have included tests to prevent regressions.
  • I have signed my commits (DCO).

Related Issues

[Link issues here]

jhkim-pii and others added 25 commits October 11, 2026 06:29
Transfer the removed child shared pointer into the newly split CUGR tree node at its last use. This avoids an unnecessary reference-counted copy while preserving the child ownership needed after parent removal.

Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
…cal-builder

tst: add physical design builders for C++ unit tests
ant: return structured antenna check results
The wheel kept repository paths (python/openroad/, src/odb/odb.py), so
`import openroad` failed after `pip install`, and the per-tool modules the
tests import (odb, utl, ant, grt, ...) existed only as shims that
test/bazel_test.sh wrote at test time.

- python/modules holds the per-tool modules as files. openroadpy depends
  on them, the wheel installs them and the openroad package at the top
  level, and bazel_test.sh puts them on the path instead of writing shims.
- odb_py, utl_py and gpl_py no longer add their source directories to
  sys.path. A py_test's `import odb` had loaded a second copy of the
  module next to the src.odb.odb that openroadpy uses, so isinstance
  failed across the two.
- Hermetic py_test examples: openroad_test (unittest) and wheel_test,
  which installs the wheel into an empty directory and imports it in an
  isolated interpreter.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
… Tech

From Python, set_thread_count() and thread_count() act on the OpenRoad
instance owned by the current Tech. When none is alive (never created, or
already garbage collected) they dereferenced a null pointer. Raise ORD-0105
instead; Tcl always has an instance and is unaffected.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
Every caller of ord::getOpenRoad() dereferences the result, so raise
ORD-0105 there rather than only in the thread count functions. This
covers get_db() and the other module-level Python functions, and
getLogger() now goes through it.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
Add cgt, dpl, exa, fin, par, ppl, psm, rsz and wmk, matching the modules
`openroad -python` registers, so the wheel and tests can import them.
wmk_py no longer puts src/wmk on sys.path, as for odb. syn, ram and web
have no Python extension in the Bazel build and are left out.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
rmp.py fell back to openroadpy when rmp_py was missing, but openroadpy has
no rmp API, so in the wheel (which did not ship rmp_py) `import rmp`
succeeded with none of rmp's classes. Re-export src.rmp.rmp_py like the
other modules, ship it through openroadpy, and keep src/rmp off sys.path.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
openroadpy now re-exports odb, utl and rmp, which stay separate extensions
because other extensions import them, so `from openroadpy import *` is the
whole API and every python/modules file is that one line. wmk adds an
alias: in the shared namespace CtsOptions is the cts class, and the
watermark options are WatermarkCtsOptions.

gpl's classes were built twice, in openroadpy and in a separate _gpl.so,
giving two PlaceOptions and Replace classes. Drop the separate extension
(25 MB of the wheel), and drop src/wmk/wmk.py, which python/modules/wmk.py
replaces.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
Signed-off-by: Peter Gadfort <gadfort@zeroasic.com>
Signed-off-by: Peter Gadfort <gadfort@zeroasic.com>
Signed-off-by: osamahammad21 <osama21@aucegypt.edu>
- Guard openroadpy's re-export of odb, utl and rmp with #ifdef BAZEL.
  CMake registers them as top-level modules, so the src.* imports broke
  `openroad -python` at startup.
- //:openroad_py depends on //python/modules, so `import odb` still works
  for downstream users of the public target.
- bazel_test.sh no longer puts every src/* directory on PYTHONPATH, which
  allowed a second copy of the extension modules to load.
- Correct the comment and ORD-0105 message: destroying the current Tech
  clears the instance even while older Techs are alive.
- openroad_test frees its Tech explicitly instead of relying on immediate
  collection; wheel_test installs the wheel with pip rather than unzipping.
- Drop a stale comment left from the removed gpl extension.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
…eel-packaging

python: make the openroad wheel installable and add Python unit tests
Add a py_wrap cc_library (alwayslink) in each tool package that compiles
the tool's own SWIG Python wrapper, as CMake builds one static library per
module. The next commit links them into one extension library.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
The Bazel Python bindings compiled every tool into one combined module,
openroadpy, with odb, utl and rmp as separate extensions. The combined
module flattened all tools into one namespace (cts and wmk both define
CtsOptions, so wmk's was renamed), and each separate extension carried its
own static copy of odb, utl and the logger.

Link every tool's SWIG module (ord_py, odb, utl, ant_py, cts_py, ...) into
one library, _openroad.so. python/modules/_openroad_loader.py loads each
module's init function from that library with ExtensionFileLoader, the
counterpart of CMake's PyImport_AppendInittab: the tools keep separate
namespaces while the dynamic loader maps the library once, so they share
one copy of the C++ state. `import openroad` imports every tool module, as
`openroad -python` does at startup, so objects Design returns get their
tool's class. The flat openroadpy module is gone; its one user,
test/downstream, now imports from openroad.

- The wheel ships _openroad.so instead of _openroadpy.so, _odb.so, _utl.so
  and _rmp_py.so (52 MB, from 64 MB).
- odb_py, utl_py and rmp_py are aliases of //:openroad_py.
- par's vector templates were skipped under Bazel to avoid duplicates in
  the combined module; as its own module par needs them.
- ord::getLogger() falls back to the default logger when no Tech exists,
  so utl's Python logging works before a Tech is created and otherwise
  uses the Tech's logger.
- test/helpers.py takes PlaceOptions from gpl under Bazel too.
- modules_test checks the separate namespaces, the single library mapping,
  objects crossing modules and the shared database.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
odb, utl, gpl and wmk were the only Bazel modules not named <tool>_py, a
leftover from when they were standalone extensions. Name them odb_py,
utl_py, gpl_py and wmk_py as CMake does, so every extension in
_openroad.so is _<tool>_py and the loader needs no special cases. The
package paths stay (src.odb.odb_py), since other generated wrappers import
odb and utl through them; `import odb` and `import utl` are unchanged.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
The finder matched the last component of any module name, so after
`import openroad` another package's _ant_py (or a top-level one) would be
loaded from _openroad.so. Match the exact names the generated wrappers
import: _ord_py and src.<tool>._<tool>_py.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
Every tool's py_wrap repeated the same defines, visibility, alwayslink and
common deps. python_wrap_library in bazel/python_wrap_cc.bzl holds them,
so each tool lists only what is its own.

modules_test's /proc/self/maps check is Linux-only, so it is now a separate
test skipped elsewhere; the check that every module loads from the one
library still runs everywhere.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
syn: give the exported block the tech's DEF units
odb: check for rounding issues in DEF in and warn on doubles in int places
jhkim-pii and others added 30 commits October 16, 2026 23:52
What: UnbufferMt, the Mt form of buffer removal, joins the PARALLEL_EVAL
WNS tail.

Why: removing a buffer on the worst path is a gain the other Mt moves
cannot make.

How: the main thread checks the buffer and estimates the saved delay;
the tail removes buffers only in single-move batches, since a removal
cannot be reverted in place. LEGACY is unchanged.

Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
What: SizeDownFanoutMt, the Mt form of SizeDownFanout, joins the
PARALLEL_EVAL WNS tail, and every Mt generator follows the same steps:
isApplicable() and prepareInputs() on the main thread, generate() and
estimate() on the workers.

Why: the last serial move with an Mt form, and one rule for which code
may read live STA.

How: SizeDownFanoutMt measures the step-down cell per off-path load;
the virtual MoveGenerator::prepareInputs(Target&) replaces the per-move
prepare branches of the policy. PARALLEL_EVAL also stops at the walked
-max_utilization area. LEGACY is unchanged.

Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
What: profile mode 3 records what every move did to timing, and
report_delay_estimator_accuracy_for_rebuffering compares the buffer-tree
estimate of a driver with STA.

Why: to find the moves whose estimate misled the repair and to measure
the buffer-tree estimator.

How: RepairSetupAnalysis snapshots each move and samples timing after
it; the report plans the trees as RebufferMt does, applies the best one
in an ECO journal and undoes it. Lower profile modes do not change.

Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
What: architecture.md describes the setup repair code of this stack: the
policy model of LEGACY and PARALLEL_EVAL, the Mt generator steps and
threading, the PARALLEL_EVAL batch loop, batch outcome, stop rules, WNS
tail stage and effort levels, and the profiler.

Why: the document still described the code before the stack.

How: documentation only.

Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
…z-estimator-side-models

rsz: Model side paths in the Mt delay estimator
…z-rebuffer-mt

rsz: Add the RebufferMt buffer-tree move
…z-parallel-eval

rsz: Add the experimental PARALLEL_EVAL setup repair policy
…ute reroutes, not only the edited ones

Signed-off-by: Eder Monteiro <emrmonteiro@precisioninno.com>
…z-split-load-mt

rsz: Add SplitLoadMt to PARALLEL_EVAL
Signed-off-by: Eder Monteiro <emrmonteiro@precisioninno.com>
…z-unbuffer-mt

rsz: Add UnbufferMt to the PARALLEL_EVAL WNS tail
…z-size-down-mt

rsz: Add SizeDownFanoutMt to the PARALLEL_EVAL WNS tail
…z-move-analysis

rsz: Add the per-move analysis and the rebuffer accuracy report
…z-architecture-doc

doc: Update the rsz setup repair architecture
…into HEAD

Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>

# Conflicts:
#	src/web/src/web.cpp
#	src/web/test/bundle_test.py
Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
…I-bundle-5-cmake-dist

web: embed the checked-in bundle in the CMake build
…-report

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
With -bloat_occupied_layers, a layer whose only shape is an obstruction
with MINSPACING or DESIGNRULEWIDTH was not marked occupied, so it did not
receive the full-layer cover. Include modified obstructions in the
occupancy map when bloating while still writing them individually.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
…I-bundle-6-report

web: build the saved report from the bundle
…pins

ant: use per-layer and hierarchical pin antenna data
The sizing leakage limit is relative to the current cell, so a cell with
unusually low leakage can have every larger size excluded.  In sky130hd,
o211ai_1 leaks 4.9x less than o211ai_2, so with the default 4x limit
repair_timing could never upsize it.  A weak o211ai_1 driving a long
fanout-1 net then stayed the worst path through the whole flow, since
BufferMove does not apply to fanout-1 nets either.

When no larger cell passes the leakage limit, keep the smallest larger
cell that passes every other restriction.  Cells that already have an
allowed larger size are unchanged.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
Find the smallest larger leakage-limited cell, and whether any larger
cell is already swappable, during the main loop.  Insert the fallback
at the position it held in the equivalent cell order instead of
rebuilding the list.  No change in the swappable cells.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
…difiers

odb: preserve LEF box spacing modifiers
Allowing one upsize step under the leakage limit improves timing on
aes_sky130hd (DRT WNS -1.24 -> -1.11 ns, TNS -222 -> -184 ns, hold WNS
-0.09 -> -0.06 ns). Post-route max slew and capacitance slack get worse
(-10% -> -20% and -10% -> -22%), which is outside the -12% limits.
The limits and metrics are regenerated from the bazel run.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
Cells with no larger size under the leakage limit can now take one
upsize step, which changes repair_timing results:

- repair_setup_path14: WNS -0.885 -> -0.888, TNS -2.3 -> -3.0
- repair_setup_path15: WNS -1.281 -> -1.263, TNS -6.8 -> -6.9
- repair_setup_path16: WNS -6.018 -> -6.007, TNS -1853.5 -> -1852.0
- repair_setup_path19: WNS -1.816 -> -1.755, TNS -57.7 -> -56.0

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
…ge-limit-min-upsize

rsz: always allow one upsize step under the leakage limit
repair_antennas -ratio_margin tightens the limits so repair leaves
headroom, but only the partial ratios (PAR/PSR) used it; the cumulative
ones (CAR/CSR) were checked against the full limit.  Apply the margin
to all four.  check_antennas always uses a margin of 0, so its results
don't change.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
…argin

ant: apply ratio_margin to cumulative ratios too
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.