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

mpl: reportLocations prints "invalid format specifier" instead of macro locations

Open
#11,241 1 comment 0 reactions 1 assignee View on GitHub

@joaomai is already working on this.

Since Aug 26, 2026.

mpl
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

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.