Skip to content

dpl: avoid improve_placement crashes on no-site macros( improve_placement core dump)#9863

Open
duckkkkkkkkking wants to merge 1 commit intoThe-OpenROAD-Project:masterfrom
duckkkkkkkkking:fix/improve-placement-no-site-crash
Open

dpl: avoid improve_placement crashes on no-site macros( improve_placement core dump)#9863
duckkkkkkkkking wants to merge 1 commit intoThe-OpenROAD-Project:masterfrom
duckkkkkkkkking:fix/improve-placement-no-site-crash

Conversation

@duckkkkkkkkking
Copy link

@duckkkkkkkkking duckkkkkkkkking commented Mar 20, 2026

Summary

This change fixes a crash in improve_placement when the design contains placed macros whose LEF masters do not define a row SITE.

Before this fix, those instances could be collected as movable multi-height cells based on geometry alone. Later, the row-based detailed placement flow assumed that every movable cell had a valid row SITE and unconditionally queried its row orientation, which could dereference an empty optional and terminate with bad optional access.

The failure is reproducible with the related issue attachment issue_improve_placement_core_dump.tar, which captures the crash on mempool_tile_wrap and NV_NVDLA_partition_c.

The fix makes improve_placement treat no-SITE instances conservatively:

  • exclude them from the movable single-height and multi-height detailed-placement sets
  • keep them as fixed obstacles so legalization still respects their occupied area
  • guard orientation/grid-height helper paths against missing SITE
  • add a regression test covering a placed no-SITE macro

Type of Change

  • Bug Fix
  • New Feature
  • Refactor
  • Documentation
  • Other

Impact

This change removes a correctness bug in detailed placement and prevents improve_placement from crashing on designs that contain placed macros without row sites.

Behaviorally, standard row-based movable cells are unchanged. The only affected instances are placed masters without a row SITE, which are not legal row-based detailed-placement candidates. After this change they are handled as fixed blockages instead of movable multi-height cells, so the detailed placer continues to optimize standard cells while still honoring macro occupancy.

This was also validated on real failing designs. After the fix:
detailed_explanation.md

  • mempool_tile_wrap completes successfully with exit code 0
  • NV_NVDLA_partition_c completes successfully with exit code 0

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 signed my commits (DCO).

Related Issues

#9862
There is a dropbox link in the issue that provides the files to reporduce and test the bug and fixed version.

Signed-off-by: hyx <2153478753@qq.com>
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses a crash in improve_placement caused by macros without a defined SITE. The approach of treating these instances as fixed obstacles is robust, and the added null-pointer checks prevent the crash. The inclusion of a regression test is excellent. My review includes a couple of suggestions to reduce code duplication, which would improve the long-term maintainability of the code.

Comment on lines +29 to +34
namespace {
bool usesRowSites(const Node* node)
{
return node->getSite() != nullptr;
}
} // namespace
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This usesRowSites helper function is also defined in src/dpl/src/optimization/detailed_manager.cxx. To avoid code duplication, consider moving this logic into a method on the Node class itself, for example bool Node::hasSite() const in Objects.h. This would improve code reuse and maintainability.

References
  1. Encapsulate logic to avoid code duplication.

Comment on lines +26 to +32
auto* site = node->getSite();
if (site == nullptr) {
return;
}
if (const auto orientation = grid->getSiteOrientation(grid_x, grid_y, site)) {
node->adjustCurrOrient(*orientation);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This logic for safely updating a node's orientation is also implemented in src/dpl/src/optimization/detailed_manager.cxx as the syncOrientToRowSite helper function. To avoid this duplication, you could move syncOrientToRowSite to a shared utility header (e.g., in src/dpl/src/util/) and call it from both locations.

References
  1. Encapsulate logic to avoid code duplication.

@maliberty
Copy link
Member

Macros are generally fixed and shouldn't be movable by dpl. What is your flow?

@duckkkkkkkkking
Copy link
Author

Macros are generally fixed and shouldn't be movable by dpl. What is your flow?

I didn't mean to move the macros.
Here is the script that can trigger the problem, The related test case can be found at
https://www.dropbox.com/scl/fo/371p7r6he6d7neyx3xwml/ANPwpEIKcSwK77Aw5r6TsUQ?rlkey=zhzysjc23acsae6evh7irs4xz&e=1&st=8mz2u4gi&dl=0

set script_dir [file dirname [file normalize [info script]]]
set design_name $::env(DESIGN_NAME)

proc first_existing_dir {candidates} {
foreach candidate $candidates {
if {[file isdirectory $candidate]} {
return [file normalize $candidate]
}
}

error "Unable to find directory; tried [join $candidates {, }]"

}

if {[info exists ::env(PLATFORM_DIR)]} {
set platform_dir [file normalize $::env(PLATFORM_DIR)]
} else {
set platform_dir [first_existing_dir [list [file join $script_dir platform]]]
}

if {[info exists ::env(BENCHMARK_ROOT)]} {
set input_root [file normalize $::env(BENCHMARK_ROOT)]
} else {
set input_root [first_existing_dir [list [file join $script_dir platform benchmark] [file join $script_dir benchmark]]]
}

if {[info exists ::env(INPUT_DIR)]} {
set input_dir [file normalize $::env(INPUT_DIR)]
} else {
set input_dir [file join $input_root $design_name]
}

proc resolve_input_file {env_var input_dir candidates} {
if {[info exists ::env($env_var)] &amp;&amp; [file readable $::env($env_var)]} {
return $::env($env_var)
}

foreach candidate $candidates {
    set path "${input_dir}/${candidate}"
    if {[file readable $path]} {
        return $path
    }
}

error "Unable to find ${env_var} under ${input_dir}; tried [join $candidates {, }]"

}

if {![file isdirectory $input_dir]} {
error "Unable to find testcase directory for ${design_name}: ${input_dir}"
}

set def_file [resolve_input_file INPUT_DEF $input_dir [list "contest.def" "${design_name}.def"]]
set sdc_file [resolve_input_file INPUT_SDC $input_dir [list "contest.sdc" "${design_name}.sdc"]]

puts "reading lib.."
foreach libFile [glob "${platform_dir}/lib/*.lib"] {
# puts "lib: $libFile"
read_liberty $libFile
}

puts "reading lef.."
read_lef "${platform_dir}/lef/asap7_tech_1x_201209.lef"
foreach lef [glob "${platform_dir}/lef/*.lef"] {
read_lef $lef
}

puts "read def.."
read_def $def_file

read_sdc $sdc_file

source "${platform_dir}/util/setRC.tcl"

detailed_placement
improve_placement

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants