Skip to content

sync - #2

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

sync#2
nanocoh wants to merge 2472 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]

maliberty and others added 25 commits July 24, 2026 05:13
tap: check if selected master cells are placeable
…lay-controls-layers

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
Move the or_layer_patterns store from a cookie to sessionStorage so fill
patterns behave like the hidden/non-selectable layer sets: they survive
the reload triggered by opening a database but start fresh in a new
session, matching the Qt GUI (which does not persist layer options
across sessions). Addresses review feedback on #10795.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
The per-layer fill-pattern feature had inlined the
overlaps->intersect->toPixels->drawFilledRect sequence at each site that
paints a shape with the layer pattern, duplicating what draw_box_in_tile
already does. Give the lambda an optional pattern argument (default
solid, capturing pat_ox/pat_oy) so the routing/special-net/pin sites call
draw_box_in_tile(box, color, layer_pattern) while OBS, fills and markers
keep calling it with no pattern. Net -21 lines, no behavior change.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
Cover the previously untested per-layer fill-pattern and layer-category
work:

C++ (TestTileGenerator):
- FillPatternParsingClampsToEnum: the "pattern" request field maps to
  TileVisibility::fill_pattern, absent defaults to solid, and out-of-range
  values clamp to solid.
- FillPatternControlsShapeCoverage: a hatch paints fewer pixels than solid
  but more than zero; kNone paints nothing.

C++ (TestSaveReport):
- SerializeTechResponseGroupsOtherLayers: non-routing tech layers land in
  an "Other" category node in the layer hierarchy.

JS:
- nonSolidPatterns: drops solid entries, tolerates null/undefined.
- buildTileRequest: emits the pattern field only for non-solid layers.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
…ebGUI-display-controls-layers

web: add Implant/Other layer categories and per-layer fill patterns
hermetic-llvm 0.8.14 enables the cc_toolchain coverage features and declares
gcov / llvm-cov / llvm-profdata as toolchain files (hermeticbuild/hermetic-llvm
#675, fixed by #677), so instrumentation, tool staging into the test sandbox
and LLVM_COV/LLVM_PROFDATA all come from the toolchain.

Remove the hand-rolled instrumentation copts/linkopts, the two --test_env
paths that hardcoded the LLVM release (they broke on every module bump) and
--strategy=TestRunner=local: coverage tests run sandboxed again.

Add --noexperimental_fetch_all_coverage_outputs to work around a rules_cc bug
(dangling `gcov` symlink in each test's raw _coverage tree in llvm mode);
drop it once rules_cc >= 0.2.23 (bazelbuild/rules_cc#795) is released.

0.8.14 still pins LLVM 22.1.8, so the compiler is unchanged.

Verified: `bazelisk coverage --config=coverage -- //src/utl/test:cpp_tests`
passes 4/4 sandboxed, combined lcov report has 1464 DA: lines across 57 files
(all under src/), genhtml renders 39.6% lines / 44.2% functions -- identical
to the numbers from the original coverage config. `bazelisk build //:openroad`
succeeds.

Signed-off-by: SombraSoft <sombrio@sombrasoft.dev>
Keep the toolchain pin consistent across the repo: the downstream-consumer
test module and the equivalent snippet in docs/user/Bazel.md tracked the
version we bumped in the previous commit.

Note that test/downstream currently fails analysis regardless of the llvm
version -- rules_pycross rejects the module graph with "Unknown Python
version: 3.8" -- so this bump is verified only through module resolution
(`bazelisk mod graph` shows llvm@0.8.14). The pycross failure reproduces
unchanged on master at 0.8.11 and is tracked separately.

Signed-off-by: SombraSoft <sombrio@sombrasoft.dev>
This dependency is also depending on the platform configuration.

Signed-off-by: Henner Zeller <h.zeller@acm.org>
This now can evaluate the config settings (e.g. `//:platform`) and
even undertands the same flags bazel would accept:
`
https://github.com/hzeller/bant/releases/tag/v0.3.4

This in particular is useful to see through the `select()` in the
`//:openroad` binary to choose the correct libraries to depend on
and the build cleaner `dwyu` command to see that the library it
complained about before is actually already there.

Signed-off-by: Henner Zeller <h.zeller@acm.org>
The new version of bant has the fix that broke the detailed
version.

Signed-off-by: Henner Zeller <h.zeller@acm.org>
The source codes that include these headers don't add the path
prefix where the headers are to be found. So add the include
path to the library that they are legitimately available.

Signed-off-by: Henner Zeller <h.zeller@acm.org>
The ui_* includes are used without prefix, so add an `includes=[]`
The SteinerRenderer.h includes gui/gui.h - add dependency.
Refine the bant macro that reflects how qt6_library() is to
be handled w.r.t. dependencies.

Fixes: #10993

Signed-off-by: Henner Zeller <h.zeller@acm.org>
The fix for #10993 made the used qt libraries visible to `bant`, thus
it can now properly generate the compilation db include paths
for it.

Signed-off-by: Henner Zeller <h.zeller@acm.org>
the generated headers use qt libs, so make them visible.

Signed-off-by: Henner Zeller <h.zeller@acm.org>
The //src/gui should be agnostic of qt headers, yet it had
one header that included Qt headers (but was not needed).
Remove.

Fixes: #10997

Signed-off-by: Henner Zeller <h.zeller@acm.org>
Breakdown:

```
src/drt/test/fixture.cpp:                #include <cstdint> for (std::)?u?int.*_t
src/drt/test/fixture.h:                  #include <cstdint> for (std::)?u?int.*_t
src/gpl/src/gpu/gpuHpwlBackend.cpp:      #include <cstddef> for (std::)?size_t
src/grt/src/cugr/src/Design.cpp:         #include <string> for std::string
src/odb/src/3dblox/baseParser.cpp:       #include <fstream> for std::ifstream
src/odb/src/db/dbExtControl.cpp:         #include <cstdint> for (std::)?u?int.*_t
src/odb/src/db/dbExtControl.cpp:         #include <string> for std::string
src/odb/test/cpp/Test3DBloxChecker.cpp:  #include <string> for std::string
src/rcx/src/ext.cpp:                     #include <memory> for std::unique_ptr
src/rcx/src/netRC.cpp:                   #include <memory> for std::make_unique
src/rsz/include/rsz/Resizer.hh:          #include "sta/ArcDelayCalc.hh" for sta::ArcDelayCalc
src/rsz/src/move/VtSwapMtCandidate.cc:   #include <string> for std::string
src/rsz/src/policy/SetupCritVtSwapPolicy.cc: #include "sta/Delay.hh" for sta::Slack
src/rsz/src/policy/SetupLegacyBase.cc:   #include <string_view> for std::string_view
src/rsz/test/cpp/TestResizer.cc:         #include "rsz/Resizer.hh" for rsz::MoveType
src/rsz/test/cpp/TestResizer.cc:         #include "sta/Delay.hh" for sta::ArcDelay
src/syn/src/elab/driver.cc:              #include <string_view> for std::string_view
src/syn/src/flow/acd.cc:                 #include <cstddef> for (std::)?size_t
src/syn/src/flow/acd.cc:                 #include <string> for std::string
src/syn/src/flow/acd_resynth.cc:         #include "db_sta/dbSta.hh" for sta::dbStaState
src/syn/src/flow/acd_resynth.cc:         #include "odb/db.h" for odb::dbBlock
src/syn/src/flow/acd_resynth.cc:         #include "odb/dbTypes.h" for odb::dbMasterType
src/syn/src/flow/acd_resynth.cc:         #include "sta/Graph.hh" for sta::Vertex
src/syn/src/flow/acd_resynth.cc:         #include "sta/NetworkClass.hh" for sta::PinSet
src/syn/src/flow/acd_resynth.cc:         #include "utl/Logger.h" for debugPrint
src/syn/src/flow/acd_timing.cc:          #include "sta/NetworkClass.hh" for sta::PinSet
src/syn/src/flow/acd_timing.cc:          #include <cstddef> for (std::)?size_t
src/syn/src/flow/acd_timing.cc:          #include <limits> for std::numeric_limits
src/syn/src/flow/acd_timing.cc:          #include <utility> for std::pair
src/syn/src/flow/export.cc:              #include "odb/dbTypes.h" for odb::dbIoType
src/syn/test/npn_test.cc:                #include <set> for std::set
src/syn/test/sm_test.cc:                 #include <string> for std::string
src/tst/include/tst/fixture.h:           #include "odb/db.h" for odb::dbLib
src/utl/src/CFileUtils.cpp:              #include <system_error> for std::error_code
```

Signed-off-by: Henner Zeller <h.zeller@acm.org>
removeBuffers() loses the connection through a kept sub-module when the
feedthrough buffer it removes has its two flat nets at different hierarchy
depths.  The emitted hierarchical netlist ends up with a sub-module output
port that nothing drives, so LEC and gate level simulation fail while
placement and routing see a correctly merged flat net and report nothing.

Add BufRemTest3.HierFeedthroughAcrossLevels covering that shape:

  top
  +- u_wrap (wrap_mod)
  |    +- u_blk (blk_mod)
  |         +- u_drv    (drv_mod)  NOR2_X1 drives drv_o
  |         +- u_ft_mod (ft_mod)   ft_i -> BUF_X1 u_ft -> ft_o
  +- u_sink (sink_mod)             sink_i -> OR2_X1 .A1

The buffer input comes from a sibling sub-module output port, so its flat
net stays deep at u_wrap/u_blk/drv_to_ft, while the buffer output leaves
three module boundaries before re-entering sink_mod, so its flat net is the
top level net mid.  That depth asymmetry is what distinguishes this case
from the existing FeedthroughAssign test, where both nets sit at top level.

The test asserts the whole chain so a future failure points at the right
stage: the flat dbNets have to merge, both boundary ModNets of ft_mod have
to end up on one net, the surviving ModNet must not take the output port
name, and write_verilog has to emit "assign ft_o = ft_i;" inside ft_mod.

The input netlist is written in write_verilog output style so that a diff
against the golden shows only the buffer to assign change.

This test fails on current master by design.  The golden file holds the
netlist a correct remove_buffers has to produce.

Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
removeBuffer() already keeps the input ModNet as the survivor when dropping
the buffer turns a sub-module into a feedthrough, because VerilogWriter can
only express that feedthrough as an alias of the output port onto a net with
a different name.  The survivor rename that follows undid this.

When the surviving flat net is the deeper of the two, both the flat net and
the ModNet were renamed to the removed net's name so the shallower and more
canonical name wins.  That is right for the flat net, but for the ModNet it
hands the survivor the output port name.  writeAssigns() then finds output
port and net names equal, skips the alias, and emits a sub-module whose
output port has no driver at all.  Input ports are never aliased, so nothing
else bridges the two boundary terminals and the connection is lost in the
hierarchical netlist.  The flat dbNet merge stays correct, so placement and
routing see a properly driven net and report nothing, and only LEC or gate
level simulation fails.

Skip the ModNet rename when the removal creates a feedthrough.  The flat net
rename is unaffected.  Hoist bufferRemovalCreatesFeedthrough() into a local
so both places share one result.

This makes BufRemTest3.HierFeedthroughAcrossLevels pass.

Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
…erage-hermetic-llvm-0814

bazel: drop coverage workarounds, bump llvm to 0.8.14
oharboe and others added 30 commits August 5, 2026 23:51
Optimize EstimateParasitics::layerRC to query layer resistance and
capacitance via layer-number-indexed vectors rather than std::unordered_map
lookups per layer on every wire segment during parasitics estimation.

Use assert(layer != nullptr) in setLayerRC and layerRC.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
odb, est: optimize layer lookups in dbTech and EstimateParasitics
Signed-off-by: Arthur Koucher <arthurkoucher@precisioninno.com>
dbSta: add SWIG interface to allow dbNet -> sta::Net conversion
Signed-off-by: Naveen Venkat <archgen.guest@nyayanidhi.in>
Adds the four display-control overlays of parity table 2.5 to the web viewer —
access-point markers, dbRegion boundaries, the manufacturing grid and the GCell
grid — plus the Misc toggles that go with them: "Flywires only", "Focused nets
guides" and "Highlight selected".

Each overlay is a self-painting pseudo layer registered in one table
(PseudoLayerDef), which is the single source of truth for the tile dispatch, the
pseudo-layer guard and the order saveImage composites them in.  That order
mirrors the zIndex the client gives each layer, so a saved PNG is the view on
screen; compositing in registry order instead put the manufacturing grid over
the routing and the pin markers over the tech layers.

Two overlays needed a deliberate deviation from Qt.  The manufacturing grid is
decimated adaptively rather than hidden below the legibility limit: a 10 DBU
grid on a 9.3 mm die only clears a 5 px spacing at z=15, so Qt's rule makes the
overlay unreachable in practice.  Access points are culled by the marker's
extent rather than its centre, because the X reaches half a marker past the
point and a centre-based cull chopped it along every tile seam.

"Flywires only" suppresses the routed wire and guide shapes but keeps the
terminal pin boxes and the special (geometric) routing, matching what the GUI
draws in that mode — without the SWires a selected supply net came back with no
highlight at all.  The flywire fan is capped at 4096 lines: the GUI draws
straight to the screen, but here the driver x sink product is materialized in
the session and copied per overlay tile.

Oblique segments convert to pixels in double and are clipped by drawLine rather
than going through the clamped integer conversion, whose per-axis saturation
rotates a segment instead of shortening it once one axis overflows.

Includes the review feedback from PR #10806: highlights are re-derived from the
selection they came from so a "Flywires only" flip cannot drop a multi-selection,
the per-block overlay caches are invalidated on a design change and hand out
shared ownership instead of a reference that outlives its lock, and the
supersampled render path is honored throughout.

Signed-off-by: Jorge Ferreira <jorge.ferreira@precisioninno.com>
…ebGUI-display-controls-overlays-grids-misc1

web: add display-control overlays from parity table 2.5 (#10619)
clang-format fix
typo fix

Signed-off-by: Jeff Ng <jeffng@precisioninno.com>
…ge-2

added layer name to min pitch message - take 2
…C by tech

Rename isIdealClockPin/isIdealClockNet to isSkipPin/isSkipNet and
broaden the skip criterion used during incremental parasitic updates.
A net is skipped when its driver pin carries no parasitic-dependent
timing: it is an ideal clock, or it is constant or has a disabled
timing constraint. The reasons are evaluated per mode and combined, so
a pin that is constant in one mode and disabled in another is still
skipped, while the ideal-clock reason keeps its cross-mode semantics
(a clock in at least one mode and ideal in every mode where it is a
clock, ignoring non-clock modes). Skipping avoids both wire RC
re-estimation and delaysInvalidFromFanin() for these nets.

Convert the estimateWireParasiticSteiner guard to an early return and
key wire RC by technology so multi-tech designs resolve per-tech
values with a default fallback.

Add unit tests exercising the skip logic through the public parasitics
API: ideal-clock and scan-clock (via arrival validity), and constant,
disabled, and mixed constant/disabled nets (via reduced pi-Elmore
presence), plus per-tech wire RC resolution.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
…irrelevant-nets-per-tech-rc

est: skip parasitic estimation for timing-irrelevant nets
The pull request lock file check compared MODULE.bazel against itself
instead of MODULE.bazel.lock, so it has been blind since it was rewritten
in #10690. Compare MODULE.bazel.lock, and emit a GitHub error annotation
with the exact regeneration command so the diff is actionable.

Regenerate MODULE.bazel.lock, which drifted once the rules_python pip
extension was invalidated and re-queried pypi.org/simple, adding
dist_hashes facts for markdown-it-py, pygments, rich and setuptools.

Drop the lock file update from the master push auto-format job: master is
protected, so its push is rejected with GH006 whenever the job produces a
diff, which is why every master push has been red since 2026-08-04.

Signed-off-by: Joao Luis Sombrio <sombrio@sombrasoft.dev>
…or one site gaps

Signed-off-by: Augusto Berndt <augusto.berndt@precisioninno.com>
…exists before checking for one site gap

Signed-off-by: Augusto Berndt <augusto.berndt@precisioninno.com>
design_powergrid__drop__average carried results.avg_voltage, so on a power net
it reported the supply voltage rather than the drop. avg_ir_drop was already
computed and used in the text report, but never reached the metric.

The mistake was invisible on a ground net, where net_voltage is 0 and
getSolution() sets avg_ir_drop = avg_voltage, so half of every run looked
correct. On a 1.8 V power net the metric read 1.79999 where the average drop
was 6.41e-06.

Also adds design_powergrid__voltage__average, so the value that metric used to
carry is still available and is named for what it is, alongside the existing
design_powergrid__voltage__worst.

Fixes #11096

Signed-off-by: Shivaram Mysore <shivaram.mysore@gmail.com>
…k-check-fix

ci: fix MODULE.bazel.lock gate and regenerate the lock file
Signed-off-by: Peter Gadfort <gadfort@zeroasic.com>
psm: report the average IR drop under the drop__average metric
…ered nodes

The three writers derive their output from a solution and all reached into
currents_/voltages_ with at(), so calling one before analyze_power_grid threw a
bare std::out_of_range with nothing to act on. write_pg_spice threw after it had
already written the resistive network, leaving a syntactically valid spice deck
with no sources and no sinks -- a floating network a simulator solves to nonsense
rather than rejects.

Each writer now calls ensureSolution() before creating its file, which reports
the net and corner and names analyze_power_grid.

writeSpiceFile additionally looked up every ITermNode in the per-node current
map with at(). That map is sparse by construction: generateCurrentMap() inserts
only nodes of instances returned by getInstancePower(), so a filler, tap or decap
has no entry. solve() reads the same map with find() and a zero default, so the
sparse case was already handled twenty lines of context away. The lookup now
matches, and skips a node with no current the way the neighbouring
kSpiceFileMinCurrent guard already skips a negligible one.

Adds report_writers_require_solution, covering write_pg_spice before a solution
exists -- including that no file is left behind -- and all three writers after
one.

Fixes #11098

Signed-off-by: Shivaram Mysore <shivaram.mysore@gmail.com>
The ensureSolution comment ran to 81 columns against the 80-column limit.
Verified with the same clang-format CI uses, Ubuntu 18.1.3, via --dry-run
-Werror on both changed files.

Signed-off-by: Shivaram Mysore <shivaram.mysore@gmail.com>
ord: register Tech for Python global APIs
odb: ensure chip has a name and not a nullptr
Addresses both review comments on #11103.

hasSolution() requires the current map to be non-empty, so a grid solved with
no powered instances -- a DEF-only or floorplanning analysis, where the solve
populates voltages and generateCurrentMap() inserts nothing -- would have been
rejected by the guard immediately after a successful solve. Voltages are still
reportable in that case.

Each writer now tests the map it actually reads: the voltage and EM writers
require node voltages, and the spice writer requires the current map, whose
emptiness is already handled by the find() lookup over ITerm nodes. The helper
is renamed reportNoSolution() since it no longer decides, only reports.

Also registers report_writers_require_solution in src/psm/test/BUILD. It was
added to the CMake list only, so Bazel generated no target for it and Bazel CI
could not run the regression. AGENTS.md asks for dual CMake+Bazel registration.

Signed-off-by: Shivaram Mysore <shivaram.mysore@gmail.com>
tap: fix overlapping endcap cells at macro boundary jogs
psm: error early when a report writer has no solution, and skip unpowered nodes
…y wire RC by tech"

This reverts commit dcd6b63.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
dpl: ensure site exists for one site gap check
dpl: draw diamond search as a per-instance outline
Revert "est: skip parasitic estimation for timing-irrelevant nets; key wire RC by tech"
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.