Skip to content

rsz: Try multiple repairs per iteration #6262

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/odb/include/odb/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -2869,10 +2869,15 @@ class dbNet : public dbObject
///
static dbNet* getValidNet(dbBlock* block, uint oid);

///
/// True if can merge the iterms and bterms of the in_net with this net
///
bool canMergeNet(dbNet* in_net);

///
/// Merge the iterms and bterms of the in_net with this net
///
bool mergeNet(dbNet* in_net);
void mergeNet(dbNet* in_net);

dbSet<dbGuide> getGuides() const;

Expand Down
22 changes: 14 additions & 8 deletions src/odb/src/db/dbNet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3238,23 +3238,31 @@ dbNet* dbNet::getValidNet(dbBlock* block_, uint dbid_)
return (dbNet*) block->_net_tbl->getPtr(dbid_);
}

bool dbNet::mergeNet(dbNet* in_net)
bool dbNet::canMergeNet(dbNet* in_net)
{
_dbNet* net = (_dbNet*) this;
_dbBlock* block = (_dbBlock*) net->getOwner();

if (isDoNotTouch() || in_net->isDoNotTouch()) {
return false;
}

std::vector<dbITerm*> iterms;
for (dbITerm* iterm : in_net->getITerms()) {
iterms.push_back(iterm);
if (iterm->getInst()->isDoNotTouch()) {
return false;
}
}

return true;
}

void dbNet::mergeNet(dbNet* in_net)
{
_dbNet* net = (_dbNet*) this;
_dbBlock* block = (_dbBlock*) net->getOwner();

std::vector<dbITerm*> iterms;
for (dbITerm* iterm : in_net->getITerms()) {
iterms.push_back(iterm);
}

for (auto callback : block->_callbacks) {
callback->inDbNetPreMerge(this, in_net);
}
Expand All @@ -3266,8 +3274,6 @@ bool dbNet::mergeNet(dbNet* in_net)
for (dbBTerm* bterm : in_net->getBTerms()) {
bterm->connect(this);
}

return true;
}

void dbNet::markNets(std::vector<dbNet*>& nets, dbBlock* block, bool mk)
Expand Down
2 changes: 2 additions & 0 deletions src/rsz/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ repair_timing
[-skip_last_gasp]
[-repair_tns tns_end_percent]
[-max_passes passes]
[-max_repairs_per_pass max_repairs_per_pass]
[-max_utilization util]
[-max_buffer_percent buffer_percent]
[-match_cell_footprint]
Expand All @@ -335,6 +336,7 @@ repair_timing
| `-skip_buffer_removal` | Flag to skip buffer removal. The default is to perform buffer removal transform during setup fixing. |
| `-skip_last_gasp` | Flag to skip final ("last gasp") optimizations. The default is to perform greedy sizing at the end of optimization. |
| `-repair_tns` | Percentage of violating endpoints to repair (0-100). When `tns_end_percent` is zero, only the worst endpoint is repaired. When `tns_end_percent` is 100 (default), all violating endpoints are repaired. |
| `-max_repairs_per_pass` | Maximum repairs per pass, default is 1. On the worst paths, the maximum number of repairs is attempted. It gradually decreases until the final violations which only get 1 repair per pass. |
| `-max_utilization` | Defines the percentage of core area used. |
| `-max_buffer_percent` | Specify a maximum number of buffers to insert to repair hold violations as a percentage of the number of instances in the design. The default value is `20`, and the allowed values are integers `[0, 100]`. |
| `-match_cell_footprint` | Obey the Liberty cell footprint when swapping gates. |
Expand Down
9 changes: 6 additions & 3 deletions src/rsz/include/rsz/Resizer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ class Resizer : public dbStaState, public dbNetworkObserver
bool repairSetup(double setup_margin,
double repair_tns_end_percent,
int max_passes,
int max_repairs_per_pass,
bool match_cell_footprint,
bool verbose,
bool skip_pin_swap,
Expand Down Expand Up @@ -630,9 +631,11 @@ class Resizer : public dbStaState, public dbNetworkObserver
bool journal);

void findResizeSlacks1();
bool removeBuffer(Instance* buffer,
bool honorDontTouchFixed = true,
bool recordJournal = false);
bool removeBufferIfPossible(Instance* buffer,
bool honorDontTouchFixed = true,
bool recordJournal = false);
bool canRemoveBuffer(Instance* buffer, bool honorDontTouchFixed = true);
void removeBuffer(Instance* buffer, bool recordJournal = false);
Instance* makeInstance(LibertyCell* cell,
const char* name,
Instance* parent,
Expand Down
68 changes: 51 additions & 17 deletions src/rsz/src/RepairSetup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ void RepairSetup::init()
bool RepairSetup::repairSetup(const float setup_slack_margin,
const double repair_tns_end_percent,
const int max_passes,
const int max_repairs_per_pass,
const bool verbose,
const bool skip_pin_swap,
const bool skip_gate_cloning,
Expand All @@ -100,6 +101,7 @@ bool RepairSetup::repairSetup(const float setup_slack_margin,
bool repaired = false;
init();
constexpr int digits = 3;
max_repairs_per_pass_ = max_repairs_per_pass;
inserted_buffer_count_ = 0;
split_load_buffer_count_ = 0;
resize_count_ = 0;
Expand Down Expand Up @@ -174,7 +176,12 @@ bool RepairSetup::repairSetup(const float setup_slack_margin,
printProgress(opto_iteration, false, false, false, num_viols);
}
float fix_rate_threshold = inc_fix_rate_threshold_;
if (!violating_ends.empty()) {
min_viol_ = -violating_ends.back().second;
max_viol_ = -violating_ends.front().second;
}
for (const auto& end_original_slack : violating_ends) {
fallback_ = false;
Vertex* end = end_original_slack.first;
Slack end_slack = sta_->vertexSlack(end, max_);
Slack worst_slack;
Expand Down Expand Up @@ -325,6 +332,7 @@ bool RepairSetup::repairSetup(const float setup_slack_margin,
// Progress, Save checkpoint so we can back up to here.
resizer_->journalBegin();
} else {
fallback_ = true;
// Allow slack to increase to get out of local minima.
// Do not update prev_end_slack so it saves the high water mark.
decreasing_slack_passes++;
Expand Down Expand Up @@ -439,6 +447,7 @@ bool RepairSetup::repairSetup(const float setup_slack_margin,
void RepairSetup::repairSetup(const Pin* end_pin)
{
init();
max_repairs_per_pass_ = 1;
inserted_buffer_count_ = 0;
resize_count_ = 0;
swap_pin_count_ = 0;
Expand Down Expand Up @@ -495,7 +504,7 @@ bool RepairSetup::repairPath(PathRef& path,
const float setup_slack_margin)
{
PathExpanded expanded(&path, sta_);
bool changed = false;
int changed = 0;

if (expanded.size() > 1) {
const int path_length = expanded.size();
Expand Down Expand Up @@ -537,7 +546,26 @@ bool RepairSetup::repairPath(PathRef& path,
|| (pair1.second == pair2.second && pair1.first > pair2.first);
});
// Attack gates with largest load delays first.
int repairs_per_pass = 1;
if (max_viol_ - min_viol_ != 0.0) {
repairs_per_pass
+= std::round((max_repairs_per_pass_ - 1) * (-path_slack - min_viol_)
/ (max_viol_ - min_viol_));
}
if (fallback_) {
repairs_per_pass = 1;
}
debugPrint(logger_,
RSZ,
"repair_setup",
3,
"Path slack: {}, repairs: {}",
delayAsString(path_slack, sta_, 3),
repairs_per_pass);
for (const auto& [drvr_index, ignored] : load_delays) {
if (changed >= repairs_per_pass) {
break;
}
const PathRef* drvr_path = expanded.path(drvr_index);
Vertex* drvr_vertex = drvr_path->vertex(sta_);
const Pin* drvr_pin = drvr_vertex->pin();
Expand All @@ -561,21 +589,21 @@ bool RepairSetup::repairPath(PathRef& path,
drvr_index,
&expanded,
setup_slack_margin)) {
changed = true;
break;
changed++;
continue;
}
}

if (upsizeDrvr(drvr_path, drvr_index, &expanded)) {
changed = true;
break;
changed++;
continue;
}

// Pin swapping
if (!skip_pin_swap) {
if (swapPins(drvr_path, drvr_index, &expanded)) {
changed = true;
break;
changed++;
continue;
}
}

Expand All @@ -597,8 +625,8 @@ bool RepairSetup::repairPath(PathRef& path,
network_->pathName(drvr_pin),
rebuffer_count);
inserted_buffer_count_ += rebuffer_count;
changed = true;
break;
changed++;
continue;
}
}

Expand All @@ -609,8 +637,8 @@ bool RepairSetup::repairPath(PathRef& path,
db_network_->instance(drvr_pin))
== resizer_->inserted_buffer_set_.end()
&& cloneDriver(drvr_path, drvr_index, path_slack, &expanded)) {
changed = true;
break;
changed++;
continue;
}

if (!skip_buffering) {
Expand All @@ -620,13 +648,17 @@ bool RepairSetup::repairPath(PathRef& path,
const int init_buffer_count = inserted_buffer_count_;
splitLoads(drvr_path, drvr_index, path_slack, &expanded);
split_load_buffer_count_ = inserted_buffer_count_ - init_buffer_count;
changed = true;
break;
changed++;
continue;
}
}
}
for (auto inst : buf_to_remove_) {
resizer_->removeBuffer(inst, /* recordJournal */ true);
}
buf_to_remove_.clear();
}
return changed;
return changed > 0;
}

void RepairSetup::debugCheckMultipleBuffers(PathRef& path,
Expand Down Expand Up @@ -858,8 +890,8 @@ bool RepairSetup::removeDrvr(const PathRef* drvr_path,
return false;
}

if (resizer_->removeBuffer(
drvr, /* honorDontTouch */ true, /* recordJournal */ true)) {
if (resizer_->canRemoveBuffer(drvr, /* honorDontTouch */ true)) {
buf_to_remove_.push_back(drvr);
removed_buffer_count_++;
return true;
}
Expand Down Expand Up @@ -977,7 +1009,7 @@ bool RepairSetup::estimatedSlackOK(const SlackEstimatorParams& params)
"because side input pin {} will have a violating slack of {}:"
" old slack={}, slack margin={}, delay_degrad={}",
db_network_->name(params.driver),
db_network_->name(side_input_pin), new_slack, old_slack,
db_network_->name(side_input_pin), new_slack, old_slack,
params.setup_slack_margin, delay_degrad);
// clang-format on
return false;
Expand Down Expand Up @@ -1918,6 +1950,7 @@ void RepairSetup::repairSetupLastGasp(const OptoParams& params, int& num_viols)
float fix_rate_threshold = inc_fix_rate_threshold_;

for (const auto& end_original_slack : violating_ends) {
fallback_ = false;
Vertex* end = end_original_slack.first;
Slack end_slack = sta_->vertexSlack(end, max_);
Slack worst_slack;
Expand Down Expand Up @@ -2002,6 +2035,7 @@ void RepairSetup::repairSetupLastGasp(const OptoParams& params, int& num_viols)
resizer_->journalEnd();
resizer_->journalBegin();
} else {
fallback_ = true;
resizer_->journalRestore(resize_count_,
inserted_buffer_count_,
cloned_gate_count_,
Expand Down
6 changes: 6 additions & 0 deletions src/rsz/src/RepairSetup.hh
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ class RepairSetup : public sta::dbStaState
// reduce tns (0.0-1.0).
double repair_tns_end_percent,
int max_passes,
int max_repairs_per_pass,
bool verbose,
bool skip_pin_swap,
bool skip_gate_cloning,
Expand Down Expand Up @@ -235,12 +236,17 @@ class RepairSetup : public sta::dbStaState
int num_endpts);
void repairSetupLastGasp(const OptoParams& params, int& num_viols);

std::vector<Instance*> buf_to_remove_;
Logger* logger_ = nullptr;
dbNetwork* db_network_ = nullptr;
Resizer* resizer_;
const Corner* corner_ = nullptr;
LibertyPort* drvr_port_ = nullptr;

bool fallback_ = false;
float min_viol_ = 0.0;
float max_viol_ = 0.0;
int max_repairs_per_pass_ = 1;
int resize_count_ = 0;
int inserted_buffer_count_ = 0;
int split_load_buffer_count_ = 0;
Expand Down
Loading