Skip to content

Rebuffering in TD global placement #7485

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

openroad-ci
Copy link
Collaborator

This is "do not merge" but please do review

We can merge once port buffer locking gets in: #7457

@povik povik requested a review from maliberty June 3, 2025 18:43
@@ -21,6 +21,7 @@ add_library(rsz_lib
RepairHold.cc
RepairSetup.cc
Rebuffer.cc
Rebuffer2.cc
Copy link
Contributor

Choose a reason for hiding this comment

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

There's duplication between Rebuffer.cc and Rebuffer2.cc which can get resolved later. The former is used in repair_timing and the latter is used for TD gpl.

Copy link
Contributor

github-actions bot commented Jun 3, 2025

clang-tidy review says "All clean, LGTM! 👍"

@@ -221,7 +221,7 @@ void RepairDesign::repairDesign(
print_interval_ = min_print_interval_;
}
printProgress(print_iteration, false, false, repaired_net_count);
int max_length = resizer_->metersToDbu(max_wire_length);
int max_length = std::numeric_limits<int>::max();

This comment was marked as outdated.

Comment on lines +300 to +314
if (length() == 0) {
res = 0;
cap = 0;
} else {
const double dx
= resizer->dbuToMeters(std::abs(location_.x() - ref_->location().x()))
/ resizer->dbuToMeters(length());
const double dy
= resizer->dbuToMeters(std::abs(location_.y() - ref_->location().y()))
/ resizer->dbuToMeters(length());
res = dx * resizer->wireSignalHResistance(corner)
+ dy * resizer->wireSignalVResistance(corner);
cap = dx * resizer->wireSignalHCapacitance(corner)
+ dy * resizer->wireSignalVCapacitance(corner);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we include a helper that calculates the RCs of a wire or length of a wire and returns it to you? I think it would help clean up this code.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think so, yes, but this is pre-existing code I just fixed it for the case length() == 0

@@ -460,6 +472,120 @@ BufferedNetPtr Resizer::makeBufferedNetSteiner(const Pin* drvr_pin,
return bnet;
}

static BufferedNetPtr makeBufferedNetFromTree2(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you include a short description about what this algorithm is doing/attempting to do?

Copy link
Contributor

Choose a reason for hiding this comment

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

I've added descriptions to these new bnet builders

@@ -666,4 +792,12 @@ BufferedNetPtr Resizer::makeBufferedNetGroute(const Pin* drvr_pin,
return nullptr;
}

bool BufferedNet::fits_envelope(Metrics target)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should be camel case naming.

@@ -141,6 +141,44 @@ class BufferedNet

static constexpr int null_layer = -1;

struct Metrics
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we give this a more specific struct name? There's many classes named Metrics

Copy link
Contributor

Choose a reason for hiding this comment

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

This one is BufferedNet::Metrics so I'm thinking it's fine

Comment on lines +38 to +40
class Rebuffer : public sta::dbStaState
{
public:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this new Rebuffer class fit into @mguthaus's refactoring of rsz? Should rebuffer be a move or use Moves?

Copy link
Contributor

Choose a reason for hiding this comment

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

Does this new Rebuffer class fit into @mguthaus's refactoring of rsz?

Up to this point it's orthogonal, we coordinate

Copy link
Contributor

Choose a reason for hiding this comment

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

Should rebuffer be a move or use Moves?

It can be encapsulated as a move for repair_timing later on so that repair_timing can also benefit from this algorithm

povik added 10 commits June 4, 2025 14:16
Signed-off-by: Martin Povišer <[email protected]>
Signed-off-by: Martin Povišer <[email protected]>
Signed-off-by: Martin Povišer <[email protected]>
Signed-off-by: Martin Povišer <[email protected]>
Signed-off-by: Martin Povišer <[email protected]>
Signed-off-by: Martin Povišer <[email protected]>
Fix the `resizeWostSlackNets()` API to account for the fact that journal
restore might delete nets.

Signed-off-by: Martin Povišer <[email protected]>
Signed-off-by: Martin Povišer <[email protected]>
@openroad-ci openroad-ci force-pushed the rsz-fully-rebuffer-new branch from 18b19a8 to 5fe1090 Compare June 4, 2025 13:24
Copy link
Contributor

github-actions bot commented Jun 4, 2025

clang-tidy review says "All clean, LGTM! 👍"

} else {
set max_wire_length $min_delay_max_wire_length
set max_wire_length_fmt [format %.0f [sta::distance_sta_ui $max_wire_length]]
utl::info RSZ 58 "Using max wire length ${max_wire_length_fmt}um."
Copy link
Contributor

Choose a reason for hiding this comment

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

This disables wire length repair in repair_design unless a length is explicitly specified with -max_wire_length. The reasoning is that placement buffering finds good solutions satisfying all ERCs. These don't necessarily fit into any wire length bound so if repair_design enforces max wire length later in the flow, it potentially degrades the solution (seen to happen).

This may negatively impact users who don't use timing-driven placement. They will see different repair results unless they are specifying -max_wire_length.

@@ -86,7 +86,7 @@ void Replace::reset()
routabilityMaxInflationIter_ = 4;

timingDrivenMode_ = true;
keepResizeBelowOverflow_ = 0.3;
keepResizeBelowOverflow_ = 1.0;
Copy link
Contributor

Choose a reason for hiding this comment

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

This change should be making all TD rounds non-virtual by default

@maliberty maliberty changed the title DO NOT MERGE: Rebuffering in TD global placement Rebuffering in TD global placement Jun 5, 2025
Copy link
Member

@maliberty maliberty left a comment

Choose a reason for hiding this comment

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

Start of a review

Iter | Area | Removed | Inserted | Remaining
| | Buffers | Buffers |
-------------------------------------------------------
0 | +0.0% | 0 | 0 | 64
Copy link
Member

Choose a reason for hiding this comment

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

Why does nothing change over the 64 iterations?

Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like no buffers needed in this design

Comment on lines +117 to +120
[WARNING GPL-0092] Mismatch in #cells between central object and all regions. NesterovBaseCommon: 1, Summing all regions: 0
[INFO GPL-0107] Timing-driven: repair_design delta area: 3.724 um^2 (+0.77%)
[INFO GPL-0108] Timing-driven: repair_design, gpl cells created: 1 (+0.00%)
[WARNING GPL-0093] Buffer insertion count by rsz (0) and cells created by gpl (1) do not match.
Copy link
Member

Choose a reason for hiding this comment

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

These warnings seem concerning.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's a false warning, we're planning to remove it

@@ -791,6 +793,14 @@ void set_debug_cmd(const char* net_name,
resizer->setDebugGraphics(std::move(graphics));
}

void
fully_rebuffer(Pin *pin)
Copy link
Member

Choose a reason for hiding this comment

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

Is this just a test stub? Does this need a user control?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, for now it's meant for testing only

Comment on lines 2083 to 2085
NetSeq worst_slack_nets;
for (int i = 0; i < nets.size() * worst_slack_nets_percent_ / 100.0; i++) {
worst_slack_nets.push_back(nets[i]);
Copy link
Member

Choose a reason for hiding this comment

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

No need to copy, just resize down the nets vector to the desired size.

Copy link
Contributor

Choose a reason for hiding this comment

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

Missed that, done

using BnetPtr = BufferedNetPtr;
using BnetMetrics = BufferedNet::Metrics;

// Template magic to make it easier to write algorithms descending
Copy link
Member

Choose a reason for hiding this comment

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

Looks like a copy-paste from Rebuffer.cc.

Copy link
Contributor

Choose a reason for hiding this comment

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

We should retire Rebuffer.cc later so I'm hoping a bit of duplication in the interim is ok

return 1;
}
default:
abort();
Copy link
Member

Choose a reason for hiding this comment

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

Use critical not abort which has no info

Copy link
Contributor

Choose a reason for hiding this comment

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

Done (here and elsewhere)

Comment on lines +305 to +306
while (ptr->type() == BnetType::wire) {
ptr = ptr->ref();
Copy link
Member

Choose a reason for hiding this comment

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

Are we guaranteed the ptr will never be null (ie we can't reach the end with type wire)? Same in stripWiresAndBuffersOnBnet

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, ref() is always non-null on type wire or buffer

Comment on lines +393 to +396
const double a = wire_res * wire_cap;
const double b = wire_res * in->capacitance() + r_drvr * wire_cap;
const double c = r_drvr * in->capacitance() - max_slew / elmore_skew_factor_;
const double D = b * b - 4 * a * c;
Copy link
Member

Choose a reason for hiding this comment

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

This looks very similar to RepairDesign::repairNetWire. Make a common utility?

Copy link
Contributor

Choose a reason for hiding this comment

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

repairNetWire's version has more terms. I'm on the edge as to whether an utility is worth it

Comment on lines 118 to 119
const Pin* drvr_pin_;
Point drvr_location_;
Copy link
Member

Choose a reason for hiding this comment

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

What necessitates being non-const?

Copy link
Contributor

Choose a reason for hiding this comment

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

Made const

Comment on lines 51 to 52
std::vector<int> x,
y; // Two separate vectors of coordinates needed by flute.
Copy link
Member

Choose a reason for hiding this comment

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

Icky formatting, put the comment on the line above

Copy link
Contributor

Choose a reason for hiding this comment

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

Done

Signed-off-by: Martin Povišer <[email protected]>
Copy link
Contributor

github-actions bot commented Jun 6, 2025

clang-tidy review says "All clean, LGTM! 👍"

Copy link
Contributor

github-actions bot commented Jun 6, 2025

clang-tidy review says "All clean, LGTM! 👍"

@povik
Copy link
Contributor

povik commented Jun 9, 2025

We're now getting a CI failure on merge I believe due to #7506 changing the log output. I'm holding off regoldening until we are closer to merge.

20:57:06  The following tests FAILED:

20:57:06  	430 - gpl.simple01-td.tcl (Failed)                      IntegrationTest tcl gpl log_compare
20:57:06  	431 - gpl.simple01-td.py (Failed)                       IntegrationTest python gpl log_compare
20:57:06  	432 - gpl.simple01-td-tune.tcl (Failed)                 IntegrationTest tcl gpl log_compare
20:57:06  	433 - gpl.simple01-td-tune.py (Failed)                  IntegrationTest python gpl log_compare

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.

5 participants