Skip to content

sync - #2

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

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

dsengupta0628 and others added 25 commits August 12, 2026 15:25
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
Signed-off-by: Eder Monteiro <emrmonteiro@precisioninno.com>
grt: size monotonic route buffer to the actual route length
…rting point

Signed-off-by: Arthur Koucher <arthurkoucher@precisioninno.com>
…ngestion

GRT: Fix FastRoute blocked tracks computation
Signed-off-by: dsengupta0628 <dsengupta@precisioninno.com>
dpl: check edge spacing DRC on opt_mirror
…ff-register-latch-mask

gpl: Separate registers and latches in MBFF masks
Signed-off-by: Mike Inouye <mikeinouye@google.com>
Signed-off-by: Mike Inouye <mikeinouye@google.com>
…place-bracket

odb: Avoid Verilog namespace collisions
mbff: dont count Enable input pin as data input
Add `global_placement -place_ios`, which turns every movable IO port into a
variable of the same Nesterov solve as the cells instead of treating it as a
fixed anchor. The solved pin locations are written to the database; snapping
them onto routing-track slots stays place_pins' job, the same way
detailed_placement follows global_placement for cells.

An IO pin becomes a GCell in NesterovBase::ioPinStor_ and its existing GPin is
re-linked to it, so the unchanged weighted-average wirelength gradient starts
differentiating the pin - no IO-specific gradient code. A pin is confined to
the die perimeter by projecting it, every iteration, onto a set of perimeter
segments that models the unconstrained case, set_io_pin_constraint regions and
exclude_io_pin_region uniformly. Mirrored pairs carry one degree of freedom:
the follower is the exact reflection of its master, and initIoConstraints()
intersects the master's locus with the mirror of the follower's so that
reflection is always legal - ppl treats it as a hard constraint and errors
(PPL-82) otherwise.

Three interactions needed care:

  - IO pins carry no 2-D density force. They sit on the die perimeter, outside
    the core bin grid, and contribute no area to it, so -place_ios does not
    move the cells' overflow convergence point.
  - Their step-to-step displacement is a projection jump rather than a gradient
    step, and the Barzilai-Borwein step length is shared by every GCell, so
    they are excluded from that norm. Including them left overflow oscillating
    at 0.25-0.43 instead of reaching the 0.1 target.
  - The device-resident coordinate, wirelength and HPWL pipelines are built
    from NesterovBaseCommon::gCellStor_ and do not model ioPinStor_, so
    -place_ios keeps them host-resident and forces the CPU backends.

Ports the solve does not model - power/ground, and anything not on a signal or
clock net - own no GPin, so their gradient would be identically zero. They are
left for place_pins to place, which means an unplaced port is a normal state
during global placement and no longer an error (GPL-326).

-place_ios is mutually exclusive with -timing_driven, -routability_driven,
-incremental, -skip_io and -skip_nesterov_place.

Signed-off-by: Minju Kim <mkim@precisioninno.com>
NesterovBase::ioNbPos() called std::vector<GCellHandle>::size() inside the
class body, where GCellHandle is still only forward declared - its definition
follows NesterovBase in the same header. GCC accepted it, clang/libc++ did not:

  vector.h:385:48: error: arithmetic on a pointer to an incomplete type
  'gpl::GCellHandle'

which broke every Bazel target depending on //src/gpl:gpl.

Keep the declaration in the class and move the body below GCellHandle.

Signed-off-by: Minju Kim <mkim@precisioninno.com>
- indexOfGCell() compared pointers from two different pools with < and >=,
  which is undefined behavior. std::less gives a total order over all
  pointers, so the range check stays valid when the GCell comes from
  ioPinStor_.
- getDistance() divided by n, which is nb_gcells_.size() - ioPinStor_.size()
  and can be zero when every movable object is an IO pin. The resulting NaN
  step length propagates into the whole solve.
- A blocked region that does not overlap the edge span produced a free
  segment reaching past the end of that span. Not reachable today, since
  odb clamps every region into the die area, but the function no longer
  depends on that.
- A constraint region that is not a die-edge interval is a top-layer region:
  the pin belongs on the top-layer grid inside the die, not on the perimeter,
  and ppl makes the same distinction in getConstraintsFromDB(). Such a pin
  was seeded as a movable IO GCell and warned that it would be placed on the
  free perimeter; the solve then dragged it to a die edge and placed the
  cells against a position place_pins discards. Leave those pins to
  place_pins, and reuse GPL-172 to report how many the perimeter model
  skipped.

Signed-off-by: Minju Kim <mkim@precisioninno.com>
odb: temporary fix for wire ordering of input bump nets
…ROAD into ant_order_independent_merge

Signed-off-by: Eder Monteiro <emrmonteiro@precisioninno.com>
Signed-off-by: Eder Monteiro <emrmonteiro@precisioninno.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Equivalence checking needs an oracle. kepler-formal is GPL-3.0 and OpenROAD is
BSD-3-Clause, so it is invoked as a subprocess and never linked: //src/tst:lec
builds the config, runs the binary, and classifies the verdict, linking nothing
of it.

It builds from source as a bazel dev_dependency, so a developer needs no manual
install and the tests cannot silently run against whatever binary happens to be
on $PATH. Two things make that work:

  - //bazel:kepler.bzl carries a Starlark transition that strips `-xc++` from
    cxxopts for kepler's subtree. OpenROAD sets that flag globally, and it
    breaks cmake's compiler probe inside rules_foreign_cc, which kepler's
    oneTBB dependency uses. The transition keeps the flag for OpenROAD's own
    compilation, which is what it is there for.

  - bazel/kepler-patches/ drops a linkopt that naja's python-embed leaks, which
    would otherwise export a system library search directory into the link.

At run time lec.cpp resolves the binary from $KEPLER_FORMAL, then the test's
runfiles, then $PATH, so a locally installed binary still wins for anyone who
wants to point at their own build. A test that declares :kepler_formal_bin in
data always has it, so under bazel the tool is never missing and a LEC test can
never quietly degrade into a no-op.

Three details about reading kepler's output, all of which have been wrong at
some point and each of which fails silently rather than loudly:

  - The SEC encoding is dual_rail_steady, not binary. Which one is sound
    flipped between kepler revisions; the comment in lec.cpp records the
    mutation battery that settled it.

  - A proved verdict has two spellings. dual_rail_steady prints "No
    binary-defined difference was found" where binary prints "No difference
    was found", and matching only the first turns every pass into
    "inconclusive".

  - The verdict text is read BEFORE the exit status, and the exit status only
    decides what an absent verdict means. kepler-formal used to exit 0 whether
    it proved equivalence or found a difference; it now exits 3 on a
    difference. An exit-code-first classifier therefore reports every genuine
    inequivalence as a tool error, which is the worst direction to be wrong in:
    it makes a real defect indistinguishable from a broken fixture.

The installer gains the host tools kepler's own build reaches outside bazel for
(bison, flex, m4, cmake, pkg-config, python3 headers); without them the failure
surfaces as an unhelpful repository-rule error inside a bazel fetch.

The tests for this land in the next commit, with the fixture they need.

Signed-off-by: Peter Gadfort <gadfort@zeroasic.com>
gadfort and others added 30 commits August 21, 2026 11:39
Signed-off-by: Peter Gadfort <gadfort@zeroasic.com>
grt: persist routing engine choice for cross-session repair_antennas
dpl: remove negotiation standalone padding check
Signed-off-by: Eder Monteiro <emrmonteiro@precisioninno.com>
Signed-off-by: Eder Monteiro <emrmonteiro@precisioninno.com>
…check

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
Signed-off-by: Mike Inouye <mikeinouye@google.com>
Signed-off-by: Mike Inouye <mikeinouye@google.com>
…ayer

grt/cugr: support pins above the max routing layer
rsz: Fix UB in performEarlySizingRound
pad: reorganize RDLRoute into per net to allow to better route continuity checking
gui: avoid call to sortItems since that triggers from bazel segfault
place_macro validated the core-containment rectangle using the
instance's
bounding box *before* the requested orientation was applied. The four
right-angle orientations (R90, R270, MXR90, MYR90)
swap width and height, so whenever the requested orientation differed
from the current one in right-angle-ness the check used the wrong
footprint: it rejected legal placements of rotated macros with
MPL-0034, and symmetrically would accept ones that do not fit.

Compute the width and height the macro will actually have once
`orientation` is applied, and validate that instead. The comparison is
made against the instance's current orientation rather than assuming
R0, so a macro that has already been rotated is handled correctly too.

The new test places a 100x400um macro at R90 in a 499.89x198.80um
core, where the rotated footprint (400x100) fits and the unrotated one
(100x400) does not. It also asserts the same origin is still rejected
at R0, so the fix cannot silently over-correct.

Signed-off-by: sfmth <sfmth0@gmail.com>
The new test was added to COMPULSORY_TESTS but not to the per-test
resource dict. src/mpl/test/BUILD does not glob the testcases/
directory -- the filegroup globs only `test_name + ".*"`, which picks up
the .tcl, .ok and .defok, so each test's LEF and DEF have to be listed
explicitly.

The Bazel target therefore resolved and ran without
testcases/place_macro_rotated.{lef,def}, while the CMake build passed
because it collects test inputs differently.

bazel query deps(//src/mpl/test:place_macro_rotated_resources) now lists
all six required inputs, and
bazel test //src/mpl/test:place_macro_rotated-tcl_test passes.

Signed-off-by: sfmth <sfmth0@gmail.com>
Set the orientation before building the containment rectangle instead of
computing the post-orientation footprint by hand, per review. getBBox()
then already reports the footprint the macro will have, so the explicit
width/height swap and its right-angle-ness comparison are unnecessary.
setOrient() had to precede setLocation() in any case; it now precedes
the
core-containment check as well.

Rename the test to place_macro_with_right_angle_rotation and reduce it
to
the single R90 placement. The negative case it also asserted is no
longer
sound: with setOrient() ahead of the check, a rejected placement leaves
the instance rotated, so catching MPL-0034 and then writing the DEF
would
serialize the macro at the rejected orientation.

Signed-off-by: sfmth <sfmth0@gmail.com>
Rename the test and all five of its files to
place_macro_right_angle_rotation, so the CMake test name, the Bazel
targets, the .tcl/.ok/.defok and the testcases LEF/DEF agree. The
half-applied rename currently on the PR branch renamed only the Bazel
entries, which fails the package load -- "Error in glob: glob pattern
'place_macro_with_right_angle_rotation.*' didn't match anything" -- and
takes all of Jenkins down with it.

Reword the comment above setOrient() and cut the test down to its header
line, both verbatim as requested in review.

Signed-off-by: sfmth <sfmth0@gmail.com>
mpl: check core containment against the post-orientation footprint
…w-metrics-check

test: check flow metrics under bazel
Add README sections for save_display_controls and restore_display_controls,
and bring the web_server entry in line with web.tcl: -stop, an OS-assigned
default port, and -dir as deprecated rather than required.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
Both tests were registered against the wrong dependency set, so each failed
in one build system while passing in the other.

display_state_test imports jsdom, but was registered with JS_FILES, which
carries only the product's own JS sources.  jsdom comes from
:node_modules/jsdom, bundled into DOM_TEST_DATA with the other DOM tests.
Node could not resolve the import and the test aborted before running a
single case, so nothing it covers was ever actually checked.

TestSaveDisplayControls compiles gui/src/stub.cpp to pick up the three
gui::Gui symbols web_serve.cpp needs, and stub.cpp's initGui calls
DescriptorRegistry::initDescriptors, which lives in init_descriptors.cpp.
Bazel's :gui_stub deps on :gui and gets that file; CMake has no equivalent
library, since gui_descriptors deliberately holds only the registry and the
descriptor implementations live inside the Qt gui target the test cannot
link.  The reference was therefore unresolvable, and the test now compiles
the three Qt-free descriptor sources itself.  bufferTreeDescriptor.cpp is
not among them despite init_descriptors.cpp calling BufferTree::setSTA: it
reaches QColor through colorGenerator.h and does not compile without Qt,
and stub.cpp supplies the BufferTree definitions instead.

The link failed under GNU ld on every CMake platform, not only the one CI
reported; elsewhere a parallel gmake aborted before reaching the target.
Bazel is unaffected because lld discards the never-called initGui before
its relocation has to resolve.

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

Addresses a portion of #10619, 2.5 Display controls — overlays, grids & misc
Signed-off-by: Peter Gadfort <gadfort@zeroasic.com>
pad: remove unused variable
pdn: dont rely on just the intersection for via insertion, check actual layer shape if initial ensure does not yield valid vias
…ction-highlight-inspection

master brought in the display-controls/overlays/grids web work, which
touched the same files as the selection/highlight/inspection work here.
Conflicts resolved in:

  src/web/src/inspector.js
  src/web/src/main.js
  src/web/src/request_handler.cpp
  src/web/src/request_handler.h
  src/web/src/style.css
  src/web/src/ui-utils.js
  src/web/test/cpp/TestRequestHandler.cpp
  src/web/test/js/test-ui-utils.js

Beyond the textual conflicts:

- ScopedDbuFormat takes master's dbDatabase* (multi-die: a hierarchical
  top chip owns no dbBlock) and keeps this branch's convert_string
  installation; all call sites updated.
- Highlight collection goes through master's clearSelectionHighlights /
  setSelectionHighlights / setSelectionSetHighlights helpers so
  highlight_source stays in sync and a "Flywires only" flip re-derives
  from the right source.  appendHighlightShapes also appends the
  ShapeCollector flight lines this branch added.
- writeInspectPayload combines both signatures; use_dbu and the logger
  are threaded through this branch's writeInspectTrailer helper.
- handleOverlayTile keeps master's error handling, coordinate
  validation, flywire re-derive and highlight_selected gate, plus this
  branch's stale-selection drop and highlight-group shapes.
- applyBounds picks up master's tileSizeCss() and maxUsefulZoom() cap so
  both the boot and resync paths get them.

src/web/test/BUILD merged cleanly but both sides had added a js_test
named ui_utils_test; dropped the duplicate.

Also drops two no-op apply lambdas in the set_property test descriptor
that only discarded a nodiscard any_cast, and switches the marshalling
assertions to pointer-form any_cast so a regression reports as a named
assertion instead of an escaping bad_any_cast.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
Do not collect an unrouted net's flywires twice.  This branch's
ShapeCollector captures drawLine, and for a net with no wire and no
guides DbNetDescriptor::highlight draws the driver->sink fan itself, so
the descriptor's copy landed on top of the one collectNetFlightLines
derives.  Keep the derived copy, which honours kMaxFlywires, and drop
the descriptor's.

Derive highlight-group shapes through appendHighlightShapes instead of
calling sel.highlight() directly, so a net parked in a persistent group
honours "Flywires only" the way the current selection does, and rebuild
the group shapes when the toggle flips.

Rebuild highlight geometry after an object moves.  A set_property edit
only rebuilt the editing session's shapes; every other session was told
to redraw, and redrew from its own cache of the old placement.  The
session's odb callbacks now raise highlight_geometry_stale on
inDbPostMoveInst / inDbInstSwapMasterAfter, which fire in all sessions,
and the overlay handler re-derives both the selection and the group
shapes from it.

Re-run a selection-browser refresh that was skipped because a
list_selection was already in flight.  The outstanding response predates
the mutation, so dropping the refresh left the table -- and the row
indices inspect/deselect send back -- describing the old set until the
next mutation.

Each fix has a regression test confirmed to fail without it.

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
…ebGUI-selection-highlight-inspection

Addresses a portion of #10619, 2.6 Selection, highlight & inspection
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.