The-OpenROAD-Project / The-OpenROAD-Project/OpenROAD

gpl: Wrong buffer placement during timing-driven GPL

Open
#11,385 6 comments 0 reactions 1 assignee View on GitHub

@gudeh is already working on this.

Since Sep 10, 2026.

gpl
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.

Image
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.

Image
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.