@@ -169,21 +169,53 @@ RepairHold::repairHold(Pin *end_pin,
169169 resizer_->incrementalParasiticsEnd ();
170170}
171171
172- // Find the buffer with the most delay in the fastest corner .
172+ // Find a good hold buffer using delay/area as the metric .
173173LibertyCell *
174174RepairHold::findHoldBuffer ()
175175{
176- LibertyCell *max_buffer = nullptr ;
177- float max_delay = 0.0 ;
176+ // Build a vector of buffers sorted by the metric
177+ struct MetricBuffer {
178+ float metric;
179+ LibertyCell* cell;
180+ };
181+ std::vector<MetricBuffer> buffers;
178182 for (LibertyCell *buffer : resizer_->buffer_cells_ ) {
179- float buffer_min_delay = bufferHoldDelay (buffer);
180- if (max_buffer == nullptr
181- || buffer_min_delay > max_delay) {
182- max_buffer = buffer;
183- max_delay = buffer_min_delay;
183+ const float buffer_area = buffer->area ();
184+ if (buffer_area != 0.0 ) {
185+ float buffer_cost = bufferHoldDelay (buffer) / buffer_area;
186+ buffers.push_back ({buffer_cost, buffer});
184187 }
185188 }
186- return max_buffer;
189+
190+ std::sort (buffers.begin (),
191+ buffers.end (),
192+ [this ](const MetricBuffer& lhs, const MetricBuffer& rhs) {
193+ return lhs.metric < rhs.metric ;
194+ });
195+
196+ if (buffers.empty ()) {
197+ return nullptr ;
198+ }
199+
200+ // Select the highest metric
201+ MetricBuffer& best_buffer = *buffers.rbegin ();
202+ const MetricBuffer& highest_metric = best_buffer;
203+
204+ // See if there is a smaller choice with nearly as good a metric.
205+ const float margin = 0.95 ;
206+ for (auto itr = buffers.rbegin () + 1 ; itr != buffers.rend (); itr++) {
207+ if (itr->metric >= margin * highest_metric.metric ) {
208+ // buffer within margin, so check if area is smaller
209+ const float best_buffer_area = best_buffer.cell ->area ();
210+ const float buffer_area = itr->cell ->area ();
211+
212+ if (buffer_area < best_buffer_area) {
213+ best_buffer = *itr;
214+ }
215+ }
216+ }
217+
218+ return best_buffer.cell ;
187219}
188220
189221float
0 commit comments