Skip to content

Commit cdd9545

Browse files
committed
rsz: add pre-check for max cap sanity
The max cap on any driver should be at least as much as the minimum input cap on an buffer or inverter. If not repair is impossible. Fixes #9133 Signed-off-by: Matt Liberty <[email protected]>
1 parent 0f7807e commit cdd9545

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed

src/rsz/src/PreChecks.cc

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
#include "PreChecks.hh"
55

66
#include <algorithm>
7+
#include <memory>
78

89
#include "db_sta/dbNetwork.hh"
10+
#include "db_sta/dbSta.hh"
911
#include "rsz/Resizer.hh"
1012
#include "sta/Corner.hh"
1113
#include "sta/LibertyClass.hh"
14+
#include "sta/MinMax.hh"
15+
#include "sta/NetworkClass.hh"
1216
#include "sta/Units.hh"
1317
#include "utl/Logger.h"
1418

@@ -59,4 +63,66 @@ void PreChecks::checkSlewLimit(float ref_cap, float max_load_slew)
5963
cap_unit->scaleAbbreviation());
6064
}
6165
}
66+
67+
void PreChecks::checkCapLimit(const Pin* drvr_pin)
68+
{
69+
if (!min_cap_load_computed_) {
70+
min_cap_load_computed_ = true;
71+
// Find the smallest buffer/inverter input cap
72+
min_cap_load_ = sta::INF;
73+
dbNetwork* network = resizer_->getDbNetwork();
74+
std::unique_ptr<sta::LibertyLibraryIterator> lib_iter{
75+
network->libertyLibraryIterator()};
76+
77+
auto update_min_cap = [&](const auto& cells) {
78+
for (sta::LibertyCell* cell : cells) {
79+
sta::LibertyPort* input;
80+
sta::LibertyPort* output;
81+
cell->bufferPorts(input, output);
82+
min_cap_load_ = std::min(min_cap_load_, input->capacitance());
83+
}
84+
};
85+
86+
while (lib_iter->hasNext()) {
87+
sta::LibertyLibrary* lib = lib_iter->next();
88+
update_min_cap(*lib->buffers());
89+
update_min_cap(*lib->inverters());
90+
}
91+
}
92+
93+
float cap1, max_cap1, cap_slack1;
94+
const Corner* corner1;
95+
const RiseFall* tr1;
96+
sta_->checkCapacitance(drvr_pin,
97+
nullptr,
98+
sta::MinMax::max(),
99+
corner1,
100+
tr1,
101+
cap1,
102+
max_cap1,
103+
cap_slack1);
104+
if (max_cap1 > 0 && max_cap1 < min_cap_load_) {
105+
dbNetwork* network = resizer_->getDbNetwork();
106+
const sta::Unit* cap_unit = sta_->units()->capacitanceUnit();
107+
std::string master_name = "-";
108+
if (sta::Instance* inst = network->instance(drvr_pin)) {
109+
sta::Cell* cell = network->cell(inst);
110+
if (cell) {
111+
master_name = network->name(cell);
112+
}
113+
}
114+
logger_->error(
115+
RSZ,
116+
169,
117+
"Max cap for driver {} of type {} is unreasonably small {}{}F. "
118+
"Min buffer or inverter input cap is {}{}F",
119+
network->name(drvr_pin),
120+
master_name,
121+
cap_unit->asString(max_cap1),
122+
cap_unit->scaleAbbreviation(),
123+
cap_unit->asString(min_cap_load_),
124+
cap_unit->scaleAbbreviation());
125+
}
126+
}
127+
62128
} // namespace rsz

src/rsz/src/PreChecks.hh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class PreChecks
1515
public:
1616
PreChecks(Resizer* resizer);
1717
void checkSlewLimit(float ref_cap, float max_load_slew);
18+
void checkCapLimit(const sta::Pin* drvr_pin);
1819

1920
private:
2021
Logger* logger_ = nullptr;
@@ -25,6 +26,12 @@ class PreChecks
2526
float best_case_slew_ = -1.0;
2627
float best_case_slew_load_ = -1.0;
2728
bool best_case_slew_computed_ = false;
29+
30+
// smallest buffer/inv cap to ensure the max_cap in Liberty/SDC is reasonable
31+
float min_cap_load_ = default_min_cap_load;
32+
bool min_cap_load_computed_ = false;
33+
34+
static constexpr float default_min_cap_load = 1e-18; // 1aF
2835
};
2936

3037
} // namespace rsz

src/rsz/src/RepairDesign.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,8 @@ void RepairDesign::repairNet(Net* net,
11771177
}
11781178

11791179
if (check_cap && !resizer_->isTristateDriver(drvr_pin)) {
1180+
// Check that the max cap limit specified is within the bounds of reason.
1181+
pre_checks_->checkCapLimit(drvr_pin);
11801182
if (needRepairCap(drvr_pin, cap_violations, max_cap, corner)) {
11811183
repair_cap = true;
11821184
}

0 commit comments

Comments
 (0)