Describe the bug
improve_placement crashes (std::bad_optional_access) and corrupts an already-legal placement
Summary
On the attached designs, detailed_placement legalizes the placement 100%
(check_placement reports zero violations). The very next improve_placement
call then, on that already-legal placement:
- with default settings, crashes with
std::bad_optional_access
("bad optional access"); and
- with a small
-max_displacement (e.g. {5 1}), instead displaces the legal
placement — [WARNING DPL-0200] Unexpected displacement during legalization —
and leaves it illegal (DPL-0314 site-alignment + DPL-0311 overlaps →
check_placement fails with DPL-0033).
improve_placement is a detailed-placement optimizer; given a legal input it
must return a legal placement (it should never make a legal placement illegal,
and never crash). Here it does both.
Environment
- OpenROAD:
26Q2-1164-g08f67ee5ec (please also try your current master).
- No display/X server required —
detailed_placement, improve_placement, and
check_placement are not GUI commands.
- Each attached
.odb embeds its tech LEF + liberty, so no extra files are needed.
Files
issue/
├── README.md this report
├── reproduce.sh portable runner (uses $OPENROAD or `openroad` on PATH)
├── reproduce.tcl the OpenROAD script
├── expected_output.txt sample output
└── data/
├── case1.odb nangate45 design, ~85k std cells + hard macros (post global placement)
├── case2.odb " (variant)
├── case3.odb " (variant)
└── case4.odb " (variant, most severe)
The four .odbs are variants of the same nangate45 design with increasing
severity of the symptom.
Manual reproduction (no scripts needed)
The shortest path — open any openroad session and paste these commands, with
<case>.odb being any of the four attached .odb files. The .odb embeds the
tech LEF + liberty, so nothing else needs to be set up; no display required.
A) Default improve_placement → crash
read_db <case>.odb
set_placement_padding -global -left 0 -right 0 ;# design has zero cell padding
detailed_placement ;# legalizes to 0 violations
check_placement ;# passes
improve_placement ;# CRASHES on case1 / case3 / case4
;# -> Error ... bad optional access
B) Small -max_displacement → corruption (DPL-0200 + DPL-0033)
read_db <case>.odb
set_placement_padding -global -left 0 -right 0
detailed_placement
check_placement ;# passes
improve_placement -max_displacement {5 1} ;# WARN DPL-0200 on a legal input
check_placement ;# fails: DPL-0033 (all 4 cases)
One-liner (no interactive session; catch keeps openroad from sitting at the
prompt after the C++ exception is reported as a Tcl error):
echo 'read_db case1.odb
set_placement_padding -global -left 0 -right 0
detailed_placement
check_placement
if {[catch {improve_placement} m]} { puts "BUG: $m" }
exit' | openroad -no_init
Last lines you should see (variant A — default):
[INFO DPL-0310] Assigned ... cells into segments. Movement in X-direction is 7520200.000000, ...
[WARNING DPL-0200] Unexpected displacement during legalization.
[INFO DPL-0314] Found 447 site alignment problems.
BUG: bad optional access
Steps to reproduce (scripted)
If you'd rather not paste, the attached reproduce.{sh,tcl} automate the loop
across all four .odbs — they're a convenience, not a requirement; they call
exactly the same OpenROAD commands shown above.
# openroad must be on PATH, or: export OPENROAD=/path/to/openroad
cd issue
# A) default improve_placement -> crash (std::bad_optional_access)
./reproduce.sh
# B) small displacement budget -> DPL-0200 + DPL-0033 (no crash)
DPL_MAXDISP="5 1" ./reproduce.sh
Or one case directly:
DPL_ODB=data/case1.odb openroad -no_init -exit reproduce.tcl # crash
DPL_ODB=data/case1.odb DPL_MAXDISP="5 1" openroad -no_init -exit reproduce.tcl # DPL-0033
Expected
improve_placement returns a legal placement (check_placement passes), or at
worst leaves the input untouched. It should never crash, and never turn a legal
placement into an illegal one.
Actual (OpenROAD 26Q2-1164-g08f67ee5ec)
detailed_placement legalizes every case to 0 violations. Then:
| case |
detailed_placement |
improve_placement (default) |
improve_placement -max_displacement {5 1} |
| case1 |
LEGAL (0 viol) |
CRASH bad optional access |
DPL-0033 (379 site-align) |
| case2 |
LEGAL (0 viol) |
DPL-0033 (58 site-align) |
DPL-0033 (445 site-align) |
| case3 |
LEGAL (0 viol) |
CRASH bad optional access |
DPL-0033 (1034 site-align) |
| case4 |
LEGAL (0 viol) |
CRASH bad optional access |
DPL-0033 (1732 site-align) |
In the non-crash runs, improve_placement first logs, on the legal input:
[INFO DPL-0310] Assigned N cells into segments. Movement in X-direction is 7520200, movement in Y-direction is 1545600.
[WARNING DPL-0200] Unexpected displacement during legalization.
[INFO DPL-0314] Found 447 site alignment problems.
[INFO DPL-0311] Found 194 overlaps between adjacent cells.
...
[ERROR DPL-0033] detailed placement checks failed during check placement.
i.e. it moves millions of DBU of cells while setting up on a placement that was
already legal, then cannot put them back. (Full sample in expected_output.txt.)
Likely cause (code pointers; line numbers for the tested version)
-
src/dpl/src/Optdp.cpp — Opendp::improvePlacement() runs a ShiftLegalizer
to populate its data structures; the comment there explicitly states that a
warning on a legal input means a bug:
// If it errors or prints a warning when given a legal placement, that likely means there is a bug in my code somewhere.
We hit exactly that warning (DPL-0200, emitted in
src/dpl/src/legalize_shift.cxx).
-
The crash is an unchecked std::optional dereference. improve_placement
evaluates a candidate site via
grid_->getSiteOrientation(x, y, site).value()
(src/dpl/src/Place.cpp, two call sites), and Grid::getSiteOrientation(...)
(src/dpl/src/infrastructure/Grid.cpp) returns an empty optional for a
position with no matching site — so .value() throws std::bad_optional_access.
The default displacement reaches such a position; a small -max_displacement
stays local and instead exposes the displacement/legality bug above.
Note
detailed_placement alone (i.e. improve_placement disabled) produces a fully
legal placement on all four cases — so these designs are legalizable; the failure
is specific to improve_placement.
Download files here: https://drive.google.com/file/d/1Rxcz75mDLKc7uCLHDvmXcCR276qoNRcY/view?usp=sharing
Expected Behavior
in the first prompt
Download files here: https://drive.google.com/file/d/1Rxcz75mDLKc7uCLHDvmXcCR276qoNRcY/view?usp=sharing
Environment
in the first prompt
Download files here: [https://drive.google.com/file/d/1Rxcz75mDLKc7uCLHDvmXcCR276qoNRcY/view?usp=sharing](https://drive.google.com/file/d/1Rxcz75mDLKc7uCLHDvmXcCR276qoNRcY/view?usp=sharing)
To Reproduce
Download files here: https://drive.google.com/file/d/1Rxcz75mDLKc7uCLHDvmXcCR276qoNRcY/view?usp=sharing
Relevant log output
Screenshots
No response
Additional Context
No response
Describe the bug
improve_placementcrashes (std::bad_optional_access) and corrupts an already-legal placementSummary
On the attached designs,
detailed_placementlegalizes the placement 100%(
check_placementreports zero violations). The very nextimprove_placementcall then, on that already-legal placement:
std::bad_optional_access("bad optional access"); and
-max_displacement(e.g.{5 1}), instead displaces the legalplacement —
[WARNING DPL-0200] Unexpected displacement during legalization—and leaves it illegal (
DPL-0314site-alignment +DPL-0311overlaps →check_placementfails withDPL-0033).improve_placementis a detailed-placement optimizer; given a legal input itmust return a legal placement (it should never make a legal placement illegal,
and never crash). Here it does both.
Environment
26Q2-1164-g08f67ee5ec(please also try your currentmaster).detailed_placement,improve_placement, andcheck_placementare not GUI commands..odbembeds its tech LEF + liberty, so no extra files are needed.Files
The four
.odbs are variants of the same nangate45 design with increasingseverity of the symptom.
Manual reproduction (no scripts needed)
The shortest path — open any
openroadsession and paste these commands, with<case>.odbbeing any of the four attached.odbfiles. The.odbembeds thetech LEF + liberty, so nothing else needs to be set up; no display required.
A) Default
improve_placement→ crashB) Small
-max_displacement→ corruption (DPL-0200 + DPL-0033)One-liner (no interactive session;
catchkeeps openroad from sitting at theprompt after the C++ exception is reported as a Tcl error):
Last lines you should see (variant A — default):
Steps to reproduce (scripted)
If you'd rather not paste, the attached
reproduce.{sh,tcl}automate the loopacross all four
.odbs — they're a convenience, not a requirement; they callexactly the same OpenROAD commands shown above.
Or one case directly:
Expected
improve_placementreturns a legal placement (check_placementpasses), or atworst leaves the input untouched. It should never crash, and never turn a legal
placement into an illegal one.
Actual (OpenROAD 26Q2-1164-g08f67ee5ec)
detailed_placementlegalizes every case to 0 violations. Then:-max_displacement {5 1}bad optional accessbad optional accessbad optional accessIn the non-crash runs,
improve_placementfirst logs, on the legal input:i.e. it moves millions of DBU of cells while setting up on a placement that was
already legal, then cannot put them back. (Full sample in
expected_output.txt.)Likely cause (code pointers; line numbers for the tested version)
src/dpl/src/Optdp.cpp—Opendp::improvePlacement()runs aShiftLegalizerto populate its data structures; the comment there explicitly states that a
warning on a legal input means a bug:
We hit exactly that warning (
DPL-0200, emitted insrc/dpl/src/legalize_shift.cxx).The crash is an unchecked
std::optionaldereference.improve_placementevaluates a candidate site via
grid_->getSiteOrientation(x, y, site).value()(
src/dpl/src/Place.cpp, two call sites), andGrid::getSiteOrientation(...)(
src/dpl/src/infrastructure/Grid.cpp) returns an empty optional for aposition with no matching site — so
.value()throwsstd::bad_optional_access.The default displacement reaches such a position; a small
-max_displacementstays local and instead exposes the displacement/legality bug above.
Note
detailed_placementalone (i.e.improve_placementdisabled) produces a fullylegal placement on all four cases — so these designs are legalizable; the failure
is specific to
improve_placement.Download files here: https://drive.google.com/file/d/1Rxcz75mDLKc7uCLHDvmXcCR276qoNRcY/view?usp=sharing
Expected Behavior
in the first prompt
Download files here: https://drive.google.com/file/d/1Rxcz75mDLKc7uCLHDvmXcCR276qoNRcY/view?usp=sharing
Environment
To Reproduce
Download files here: https://drive.google.com/file/d/1Rxcz75mDLKc7uCLHDvmXcCR276qoNRcY/view?usp=sharing
Relevant log output
Screenshots
No response
Additional Context
No response