The-OpenROAD-Project / The-OpenROAD-Project/OpenROAD
mpl: reportLocations prints "invalid format specifier" instead of macro locations
@joaomai is already working on this.
Since Aug 26, 2026.
- Dominant language
- Verilog
- Stars
- 3.1k
- Forks
- 1k
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 136
Description
Describe the bug
SimulatedAnnealingCore<T>::reportLocations() formats integer database units with a floating-point
specifier, so every row of the location table fails to format. The table header and rule are
printed, then the body is replaced by a logger error.
This is debug-output only — placement results are unaffected.
Expected Behavior
The location table lists each macro's position and size, in microns, matching the Outline: line
printed immediately above it by HierRTLMP::printPlacementResult.
Environment
Observed at 945a9f48dc6e5cc91d865daa92c45a1094cb682c.
To Reproduce
Any src/mpl/test design, with the placement channel at level 2:
set_debug_level MPL hierarchical_macro_placement 2
source "centralization1.tcl"
Relevant log output
Cluster Id | Location
-----------------------------------------------------
[*** LOG ERROR #0001 ***] [logger] invalid format specifier
Across all 34 designs in src/mpl/test, every one produces this error and no location row is
emitted in any of them.
Cause
In both loops of reportLocations (src/mpl/src/SimulatedAnnealingCore.cpp):
logger_->report("{:>11d} | ({:^8.2f} {:^8.2f}) ({:^8.2f} {:^8.2f})",
display_id,
macro.getX(), // int
macro.getY(), // int
macro.getWidth(), // int
macro.getHeight()); // int
getX(), getY(), getWidth() and getHeight() return int, while {:^8.2f} requires a
floating-point argument, so fmt rejects the call.
The intended form appears in HierRTLMP::printPlacementResult, which uses the same specifiers and
converts first — and prints correctly in the same output:
logger_->report("Outline: ({:^8.2f} {:^8.2f}) ({:^8.2f} {:^8.2f})",
block_->dbuToMicrons(outline.xMin()),
...
Outline: ( 0.00 0.00 ) ( 302.10 302.40 ) <- same specifiers, converted, prints fine
Suggested fix
Wrap the four values in block_->dbuToMicrons(...) in both loops, matching
printPlacementResult.
A second point in the same function, unverified
The fixed-terminal loop appears to skip one entry:
const int number_of_moveable_macros = static_cast<int>(pos_seq_.size());
for (int i = 0; i < macros_.size(); ++i) {
if (i <= number_of_moveable_macros) {
continue;
}
The movable macros occupy indices 0 .. pos_seq_.size() - 1, so the first fixed terminal is at
index pos_seq_.size(); with <= that entry is skipped and < looks intended.
I have not been able to observe this, since no row prints at all today — flagging it as a reading
of the source rather than something measured, in case it is worth fixing in the same pass.
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.