The-OpenROAD-Project / The-OpenROAD-Project/OpenROAD
gpl: Wrong buffer placement during timing-driven GPL
@gudeh is already working on this.
Since Sep 10, 2026.
- Dominant language
- Verilog
- Stars
- 3.1k
- Forks
- 1k
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 136
Description
Describe the bug
Symptom (BASE)
Wrong buffer location during timing driven GPL, which causes more than 1ns setup timing violation in a critical path.
The buffer u_leon3/place220890 is placed far from the driver (SRAM output). Yellow line shows the driver-buffer wire.
Analysis
- In timing-driven global placement, the second non-virtual timing-driven iteration (overflow ≈ 0.19) runs repair_design, which on a large macro-heavy design replaces a large part of the netlist (≈95k GCells created/deleted out of ≈270k movable).
- After the topology change, NesterovPlace::runTimingDriven() re-seeds only the new instances via updateGCellState(), but the accelerated-gradient coefficient (
curA, giving an extrapolation coefficient of ≈0.995 at that point) and the existing cells' velocity are kept. - The placer keeps extrapolating the pre-repair trajectory on the changed objective: HPWL grows from 18.8M to 37.5M um in the ~25 remaining iterations while density overflow keeps falling, so checkDivergence() (which only fires on rising overflow) never triggers and GPL stops on the overflow < 0.10 criterion with a badly placed netlist.
Work around (TEST)
Reset curA to 1.0 after repair_design call during timing-driven GPL.
Post-GPL (3_3_place_gp) statistics, nangate45 leon3_vta_bus
BASE = OpenROAD c6c0900a16, TEST = c6c0900a16 + momentum restart. Same 3_2_place_iop.odb input, ORFS 7daaaed55, 16 threads.
| Metric | BASE | TEST | Delta |
|---|---|---|---|
| Setup WNS (ns) | -8.724 | -6.118 | +2.607 (+29.9%) |
| Setup TNS (ns) | -25135.3 | -7425.1 | +17710 (+70.5%) |
| Hold WNS / TNS (ns) | -0.108 / -0.215 | -0.107 / -0.214 | ~0 |
SRAM output r0_rd_out[7] -> first sink distance (um) |
2700.6 (u_leon3/place220890/A) |
745.7 (u_leon3/place214806/A) |
-1955 (-72.4%) |
| Macro output pins with a sink > 1000 um away | 2539 | 732 | -1807 (-71.2%) |
| Final HPWL (um) | 48,240,277 | 19,140,840 | -60.3% |
| HPWL at last non-virtual repair -> final (um) | 19.65M -> 48.24M (+145%) | 18.12M -> 19.14M (+5.6%) | divergence removed |
| Iterations after last repair / total | 17 / 559 | 62 / 609 | +45 / +50 |
| Final overflow | 0.093 | 0.100 | |
| Non-virtual TD iterations (overflow) | 2 (0.633, 0.194) | 2 (0.633, 0.194) | same |
| Buffers inserted by TD repair (iter 1 / iter 2) | 23315 / 13923 | 23315 / 11789 | -2134 |
| GCells created / deleted at repair 2 | 93505 / 99365 | 87500 / 97231 | |
| Momentum restarts (GPL-0111) | 0 | 2 | |
| TD repair area delta | +21.39% | +20.00% | -1.39 pt |
| Instance count | 499,781 | 495,910 | -3871 (-0.8%) |
| Estimated total power (W) | 3.686 | 3.605 | -2.2% |
| 3_3 runtime (wall) | 9:52 | 10:09 | +2.9% |
| Peak memory (GB) | 11.96 | 11.94 | ~0 |
How to select the target buffer
set block [ord::get_db_block]; set dbu [$block getDbUnitsPerMicron]
foreach net [$block getNets] { if {[string match {*edclramnft_r0*qs*103*} [$net getName]]} { set target_net $net; break } }
foreach it [$target_net getITerms] { if {[[$it getMTerm] getIoType] == "OUTPUT"} { set driver $it } }
set dxy [$driver getAvgXY]; set far_um -1
foreach it [$target_net getITerms] {
if {$it == $driver} continue
set sxy [$it getAvgXY]
set d [expr {(abs([lindex $sxy 1]-[lindex $dxy 1]) + abs([lindex $sxy 2]-[lindex $dxy 2])) / double($dbu)}]
if {$d > $far_um} { set far_um $d; set far_sink $it }
}
set sink_inst [[$far_sink getInst] getName]
gui::clear_selections; gui::clear_highlights -1
gui::selection_add_inst $sink_inst
gui::highlight_inst $sink_inst 0
gui::highlight_inst [[$driver getInst] getName] 1
gui::highlight_net [$target_net getName] 2
Expected Behavior
Proper placement location and the setup timing violation should be less than 1ns.
Environment
kernel: Linux 6.17.0-1018-gcp
os: Ubuntu 24.04.4 LTS (Noble Numbat)
cmake version 3.31.9
-- The C compiler identification is GNU 13.3.0
-- The CXX compiler identification is GNU 13.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- OpenROAD version: 26Q3-1953-gc6c0900a16
-- System name: Linux
-- Compiler: GNU 13.3.0
-- Build type: RELEASE
-- Install prefix: /usr/local
-- C++ Standard: 20
-- C++ Standard Required: ON
-- C++ Extensions: OFF
-- LTO/IPO is enabled
-- Performing Test C_COMPILER_SUPPORTS__-Wno-array-bounds
-- Performing Test C_COMPILER_SUPPORTS__-Wno-array-bounds - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-array-bounds
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-array-bounds - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-nonnull
-- Performing Test C_COMPILER_SUPPORTS__-Wno-nonnull - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-nonnull
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-nonnull - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-maybe-uninitialized
-- Performing Test C_COMPILER_SUPPORTS__-Wno-maybe-uninitialized - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-maybe-uninitialized
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-maybe-uninitialized - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-format-overflow
-- Performing Test C_COMPILER_SUPPORTS__-Wno-format-overflow - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-format-overflow
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-format-overflow - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-unused-variable
-- Performing Test C_COMPILER_SUPPORTS__-Wno-unused-variable - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-unused-variable
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-unused-variable - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-unused-function
-- Performing Test C_COMPILER_SUPPORTS__-Wno-unused-function - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-unused-function
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-unused-function - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-write-strings
-- Performing Test C_COMPILER_SUPPORTS__-Wno-write-strings - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-write-strings
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-write-strings - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-sign-compare
-- Performing Test C_COMPILER_SUPPORTS__-Wno-sign-compare - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-sign-compare
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-sign-compare - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-deprecated
-- Performing Test C_COMPILER_SUPPORTS__-Wno-deprecated - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-deprecated
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-deprecated - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-c++11-narrowing
-- Performing Test C_COMPILER_SUPPORTS__-Wno-c++11-narrowing - Failed
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-c++11-narrowing
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-c++11-narrowing - Failed
-- Performing Test C_COMPILER_SUPPORTS__-Wno-register
-- Performing Test C_COMPILER_SUPPORTS__-Wno-register - Failed
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-register
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-register - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-format
-- Performing Test C_COMPILER_SUPPORTS__-Wno-format - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-format
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-format - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-reserved-user-defined-literal
-- Performing Test C_COMPILER_SUPPORTS__-Wno-reserved-user-defined-literal - Failed
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-reserved-user-defined-literal
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-reserved-user-defined-literal - Failed
-- Performing Test C_COMPILER_SUPPORTS__-Wno-alloc-size-larger-than
-- Performing Test C_COMPILER_SUPPORTS__-Wno-alloc-size-larger-than - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-alloc-size-larger-than
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-alloc-size-larger-than - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-attributes
-- Performing Test C_COMPILER_SUPPORTS__-Wno-attributes - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-attributes
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-attributes - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-aggressive-loop-optimizations
-- Performing Test C_COMPILER_SUPPORTS__-Wno-aggressive-loop-optimizations - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-aggressive-loop-optimizations
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-aggressive-loop-optimizations - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-stringop-overflow
-- Performing Test C_COMPILER_SUPPORTS__-Wno-stringop-overflow - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-stringop-overflow
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-stringop-overflow - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-changes-meaning
-- Performing Test C_COMPILER_SUPPORTS__-Wno-changes-meaning - Failed
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-changes-meaning
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-changes-meaning - Success
-- Performing Test C_COMPILER_SUPPORTS__-fpermissive
-- Performing Test C_COMPILER_SUPPORTS__-fpermissive - Failed
-- Performing Test CXX_COMPILER_SUPPORTS__-fpermissive
-- Performing Test CXX_COMPILER_SUPPORTS__-fpermissive - Success
-- Performing Test C_COMPILER_SUPPORTS__-x
-- Performing Test C_COMPILER_SUPPORTS__-x - Failed
-- Performing Test CXX_COMPILER_SUPPORTS__-x
-- Performing Test CXX_COMPILER_SUPPORTS__-x - Failed
-- Performing Test C_COMPILER_SUPPORTS__c++
-- Performing Test C_COMPILER_SUPPORTS__c++ - Failed
-- Performing Test CXX_COMPILER_SUPPORTS__c++
-- Performing Test CXX_COMPILER_SUPPORTS__c++ - Failed
-- Performing Test C_COMPILER_SUPPORTS__-std=c++17
-- Performing Test C_COMPILER_SUPPORTS__-std=c++17 - Failed
-- Performing Test CXX_COMPILER_SUPPORTS__-std=c++17
-- Performing Test CXX_COMPILER_SUPPORTS__-std=c++17 - Success
-- Performing Test C_COMPILER_SUPPORTS__-fno-exceptions
-- Performing Test C_COMPILER_SUPPORTS__-fno-exceptions - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-fno-exceptions
-- Performing Test CXX_COMPILER_SUPPORTS__-fno-exceptions - Success
-- Performing Test C_COMPILER_SUPPORTS__-Wno-unused-but-set-variable
-- Performing Test C_COMPILER_SUPPORTS__-Wno-unused-but-set-variable - Success
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-unused-but-set-variable
-- Performing Test CXX_COMPILER_SUPPORTS__-Wno-unused-but-set-variable - Success
-- slang version: 10.0.150+f04e81565
-- Found Python: /home/jhkim/.local/bin/python3.14 (found version "3.14.5") found components: Interpreter
-- Build STATIC library as: svlang
-- {fmt} version: 12.1.0
-- Build type: RELEASE
-- Using remote fmt library
-- Found system boost 1.89.0 at /usr/local/include
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Performing Test COMPILER_HAS_HIDDEN_VISIBILITY
-- Performing Test COMPILER_HAS_HIDDEN_VISIBILITY - Success
-- Performing Test COMPILER_HAS_HIDDEN_INLINE_VISIBILITY
-- Performing Test COMPILER_HAS_HIDDEN_INLINE_VISIBILITY - Success
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR - Success
-- Got YOSYS_SLANG_REVISION: 82effc8d9541be69e1ed3ec44759a4449f5d9247
-- Got SLANG_REVISION: f04e81565793c768b747a8fd058f3e7aeceee1b5
-- TCL library: /usr/lib/x86_64-linux-gnu/libtcl.so
-- TCL header: /usr/include/tcl/tcl.h
-- Found SWIG: /usr/local/bin/swig (found suitable version "4.3.0", minimum required is "4.3")
-- boost: 1.89.0
-- absl: 20250512
-- Found GTest: /usr/local/lib/cmake/GTest/GTestConfig.cmake (found version "1.13.0")
-- GTest: 1.13.0
To Reproduce
Extract the linked tarballs in OpenROAD-flow-scripts/flow.
BASE flow (issue reproduction):
https://drive.google.com/file/d/17hgW565EdSGhgVcNowMr-eqfYNE7vo1Q/view?usp=sharing
cd global_place_leon3_vta_bus_nangate45_base_baseline-OR-c6c0900a16_2026-09-11_05-05
./run-me-leon3_vta_bus-nangate45-base.sh
TEST flow (work-around has been applied):
https://drive.google.com/file/d/1KodvDeyPH4Ik8hzvEGgx0gVMJYH8xxJn/view?usp=sharing
cd global_place_leon3_vta_bus_nangate45_base_momentum-restart-fix-OR-cd73f911_2026-09-11_05-05
./run-me-leon3_vta_bus-nangate45-base.sh
Relevant log output
Screenshots
No response
Additional Context
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.