You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
dpl: negotiation legalizer blocks the unrotated master footprint for R90/R270/MXR90/MYR90 fixed macros #11735
With the default negotiation legalizer, detailed_placement blocks a fixed macro placed R90, R270, MXR90 or MYR90 using the master's unrotated width and height, anchored at the instance's bbox lower-left. The blocked area on the legalizer grid is the wrong shape:
The part of the unrotated footprint that lies outside the real bbox is treated as blocked. Standard cells there are evicted even when they are already legal, and the legalizer moves them into the neighbouring rows.
The part of the real bbox outside the unrotated footprint is treated as free. When rows run under the macro, cells are left overlapping it and check_placement fails with DPL-0033.
DPL-0393 shows the cause: the macro's height in rows is the master height in every orientation (81 rows for a 152.57 x 113.4 um macro, where R90 should give 109).
detailed_placement -use_diamond_legalizer handles the same placements correctly.
In NegotiationLegalizer::initFromDb() (src/dpl/src/NegotiationLegalizer.cpp, lines 421-425 at c4d317e; the file is identical on master eb14e40), every cell is sized from the master:
buildGrid() then sets capacity 0 over x .. x + width and y .. y + height for each fixed cell. Opendp::getBbox() in dbToOpendp.cpp swaps width and height for these orientations (swapWidthHeight()); the negotiation legalizer does not.
Expected Behavior
The negotiation legalizer blocks each fixed instance's oriented bbox, as the diamond legalizer does. In the reproducer below that means:
no outside cell moves;
no cell overlaps the macro;
check_placement passes in every orientation.
Environment
OpenROAD 26Q4 (c4d317e4f), CMake Release build, gcc 12.3.0
Rocky Linux 8.10, kernel 4.18.0-553
NegotiationLegalizer.cpp is unchanged on master (eb14e40b7b)
To Reproduce
Save the script below as src/dpl/test/rotated_macro.tcl, then:
cd src/dpl/test
openroad -no_init -exit rotated_macro.tcl | grep RESULT
The script puts one fakeram45_512x64 at (100, 100) um, FIRM, in each orientation. It pre-places INV_X1 cells, every fourth site of each row, in one of two regions:
outside: legal sites in a strip to the right of the macro's real bbox;
inside: sites on the part of the real bbox that the unrotated footprint misses. This region is empty for R0 and MX.
# Run from src/dpl/test. One fixed fakeram45_512x64 (152.57 x 113.4 um) in# each orientation, with INV_X1 cells pre-placed in one of two regions:# outside: legal sites in a strip right of the macro's real bbox# inside: sites on the part of the real bbox that the unrotated# master footprint (anchored at the bbox lower-left) misses# A correct legalizer moves no "outside" cell and leaves no "inside" cell# overlapping the macro.
read_lef Nangate45/Nangate45.lef
read_lef Nangate45/fakeram45_512x64.lef
set f [open rotated_macro.v w]
puts$f"module top (); fakeram45_512x64 ram (); endmodule"close$f
read_verilog rotated_macro.v
link_design top
initialize_floorplan -die_area {0 0 400 400} -core_area {10 10 390 390} \
-site FreePDK45_38x28_10R_NP_162NW_34O
set block [ord::get_db_block]
set dbu [$block getDbUnitsPerMicron]
set ram [$block findInst ram]
set mw [[$ram getMaster] getWidth]
set mh [[$ram getMaster] getHeight]
set inv [[ord::get_db] findMaster INV_X1]
set site_w [[lindex [$block getRows] 0] getSpacing]
procfill {x0 y0 x1 y1} {
set cells {}
foreach row [$::block getRows] {
lassign [$row getOrigin] rx ry
if {$ry < $y0 || $ry + [[$row getSite] getHeight] > $y1} { continue }
set k0 [expr {int(ceil(double($x0 - $rx) / $::site_w)) + 1}]
for {set k $k0} {$rx + ($k + 2) * $::site_w <= $x1} {incr k 4} {
set c [odb::dbInst_create $::block$::inv"c[llength$cells]"]
$c setOrient [$row getOrient]
$c setLocation [expr {$rx + $k * $::site_w}] $ry$c setPlacementStatus PLACED
lappend cells [list$c [$c getLocation]]
}
}
return$cells
}
# -use_diamond_legalizer persists for the rest of the session, so it runs last.foreach legalizer {negotiation diamond} {
foreach orient {R0 MX R90 MXR90 R270 MYR90} {
foreach region {outside inside} {
foreach i [$block getInsts] {
if {[$i getMaster] eq $inv} { odb::dbInst_destroy $i }
}
$ram setPlacementStatus PLACED
$ram setOrient $orient$ram setLocation [expr {100 * $dbu}] [expr {100 * $dbu}]
$ram setPlacementStatus FIRM
set bb [$ram getBBox]
if {$region eq "outside"} {
set cells [fill [$bb xMax] [$bb yMin] \
[expr {[$bb xMax] + abs($mw - $mh)}] [expr {[$bb yMin] + min($mw, $mh)}]]
} else {
set cells [fill [$bb xMin] [expr {[$bb yMin] + min($mw, $mh)}] \
[$bb xMax] [$bb yMax]]
}
if {$legalizer eq "diamond"} {
detailed_placement -use_diamond_legalizer
} else {
detailed_placement
}
set moved 0
set over 0
foreach entry $cells {
lassign $entry c loc
if {[$c getLocation] ne $loc} { incr moved }
set cb [$c getBBox]
if {[$cb xMax] > [$bb xMin] && [$cb xMin] < [$bb xMax]
&& [$cb yMax] > [$bb yMin] && [$cb yMin] < [$bb yMax]} {
incr over
}
}
set check [expr {[catch {check_placement}] ? "FAIL" : "pass"}]
puts [format"RESULT %-11s %-5s %-7s cells %4d moved %4d overlapping macro %4d check_placement %s"\$legalizer$orient$region [llength$cells] $moved$over$check]
}
}
}
Relevant log output
RESULT negotiation R0 outside cells 4080 moved 0 overlapping macro 0 check_placement pass
RESULT negotiation R0 inside cells 0 moved 0 overlapping macro 0 check_placement pass
RESULT negotiation MX outside cells 4080 moved 0 overlapping macro 0 check_placement pass
RESULT negotiation MX inside cells 0 moved 0 overlapping macro 0 check_placement pass
RESULT negotiation R90 outside cells 4080 moved 4080 overlapping macro 13 check_placement FAIL
RESULT negotiation R90 inside cells 4023 moved 4023 overlapping macro 330 check_placement FAIL
RESULT negotiation MXR90 outside cells 4080 moved 4080 overlapping macro 13 check_placement FAIL
RESULT negotiation MXR90 inside cells 4023 moved 4023 overlapping macro 330 check_placement FAIL
RESULT negotiation R270 outside cells 4080 moved 4080 overlapping macro 13 check_placement FAIL
RESULT negotiation R270 inside cells 4023 moved 4023 overlapping macro 330 check_placement FAIL
RESULT negotiation MYR90 outside cells 4080 moved 4080 overlapping macro 13 check_placement FAIL
RESULT negotiation MYR90 inside cells 4023 moved 4023 overlapping macro 330 check_placement FAIL
RESULT diamond R0 outside cells 4080 moved 0 overlapping macro 0 check_placement pass
RESULT diamond R0 inside cells 0 moved 0 overlapping macro 0 check_placement pass
RESULT diamond MX outside cells 4080 moved 0 overlapping macro 0 check_placement pass
RESULT diamond MX inside cells 0 moved 0 overlapping macro 0 check_placement pass
RESULT diamond R90 outside cells 4080 moved 0 overlapping macro 0 check_placement pass
RESULT diamond R90 inside cells 4023 moved 4023 overlapping macro 0 check_placement pass
RESULT diamond MXR90 outside cells 4080 moved 0 overlapping macro 0 check_placement pass
RESULT diamond MXR90 inside cells 4023 moved 4023 overlapping macro 0 check_placement pass
RESULT diamond R270 outside cells 4080 moved 0 overlapping macro 0 check_placement pass
RESULT diamond R270 inside cells 4023 moved 4023 overlapping macro 0 check_placement pass
RESULT diamond MYR90 outside cells 4080 moved 0 overlapping macro 0 check_placement pass
RESULT diamond MYR90 inside cells 4023 moved 4023 overlapping macro 0 check_placement pass
# every negotiation run, all orientations:
[INFO DPL-0393] height 1 row(s): 4080 cells
[INFO DPL-0393] height 81 row(s): 1 cells
# negotiation, R90, outside (4080 cells that were already legal):
0 | 39141 | 3617 | 7230
74 | 25 | 13 | 12
[WARNING DPL-0700] Negotiation phase 1: violations stuck at 25 for 3 consecutive iterations.
[WARNING DPL-0701] NegotiationLegalizer did not fully converge. Violations remain: 5
max displacement 53.1 u
[WARNING DPL-0005] Overlap check failed (1).
[ERROR DPL-0033] detailed placement checks failed during check placement.
Additional Context
Found on a sky130hd block with OpenRAM SRAM macros placed MXR90 in a column. The legalizer emptied a strip beside each macro, as wide as the macro's width minus its height. It pushed those cells into the next strip at about 80% local utilization, and detailed routing then stalled on that strip. A rotated column at the die edge hides the problem, because the phantom area falls outside the core.
Workarounds: -use_diamond_legalizer, or placement blockages over the phantom area during global placement only, removed before detailed_placement.
Activity