diff --git a/include/sta/PathGroup.hh b/include/sta/PathGroup.hh index 418238bf..954bc2cc 100644 --- a/include/sta/PathGroup.hh +++ b/include/sta/PathGroup.hh @@ -29,7 +29,6 @@ #include #include -#include "BoundedHeap.hh" #include "SdcClass.hh" #include "StaState.hh" #include "SearchClass.hh" @@ -70,7 +69,7 @@ public: ~PathGroup(); const std::string &name() const { return name_; } const MinMax *minMax() const { return min_max_;} - PathEndSeq pathEnds() const; + PathEndSeq pathEnds() const { return path_ends_; } void insert(PathEnd *path_end); // Push group_path_count into path_ends. void pushEnds(PathEndSeq &path_ends); @@ -93,6 +92,9 @@ protected: bool cmp_slack, const MinMax *min_max, const StaState *sta); + void ensureSortedMaxPaths(); + void prune(); + void sort(); std::string name_; int group_path_count_; @@ -101,9 +103,11 @@ protected: bool unique_edges_; float slack_min_; float slack_max_; + PathEndSeq path_ends_; const MinMax *min_max_; bool cmp_slack_; - BoundedHeap heap_; + float threshold_; + std::mutex lock_; const StaState *sta_; }; diff --git a/search/PathGroup.cc b/search/PathGroup.cc index 47086f3b..a60b6c42 100644 --- a/search/PathGroup.cc +++ b/search/PathGroup.cc @@ -100,41 +100,42 @@ PathGroup::PathGroup(const char *name, slack_max_(slack_max), min_max_(min_max), cmp_slack_(cmp_slack), - heap_(group_path_count, PathEndLess(cmp_slack, sta)), + threshold_(min_max->initValue()), sta_(sta) { } PathGroup::~PathGroup() { - PathEndSeq path_ends = heap_.extract(); - deleteContents(path_ends); -} - -PathEndSeq -PathGroup::pathEnds() const -{ - return heap_.contents(); + deleteContents(path_ends_); } bool PathGroup::saveable(PathEnd *path_end) { + float threshold; + { + LockGuard lock(lock_); + threshold = threshold_; + } if (cmp_slack_) { // Crpr increases the slack, so check the slack // without crpr first because it is expensive to find. - Slack slack = path_end->slackNoCrpr(sta_); - if (!delayIsInitValue(slack, min_max_) - && delayLessEqual(slack, slack_max_, sta_)) { + Slack slack_no_crpr = path_end->slackNoCrpr(sta_); + if (!delayIsInitValue(slack_no_crpr, min_max_) + && delayLessEqual(slack_no_crpr, threshold, sta_) + && delayLessEqual(slack_no_crpr, slack_max_, sta_)) { // Now check with crpr. - slack = path_end->slack(sta_); - return delayLessEqual(slack, slack_max_, sta_) + Slack slack = path_end->slack(sta_); + return delayLessEqual(slack, threshold, sta_) + && delayLessEqual(slack, slack_max_, sta_) && delayGreaterEqual(slack, slack_min_, sta_); } } else { const Arrival &arrival = path_end->dataArrivalTime(sta_); - return !delayIsInitValue(arrival, min_max_); + return !delayIsInitValue(arrival, min_max_) + && delayGreaterEqual(arrival, threshold, min_max_, sta_); } return false; } @@ -176,33 +177,72 @@ void PathGroup::insert(PathEnd *path_end) { LockGuard lock(lock_); - auto [inserted, displaced] = heap_.insert(path_end); - if (inserted) - path_end->setPathGroup(this); + path_ends_.push_back(path_end); + path_end->setPathGroup(this); + if (group_path_count_ != group_path_count_max + && path_ends_.size() > static_cast(group_path_count_) * 2) + prune(); +} + +void +PathGroup::prune() +{ + sort(); + VertexPathCountMap path_counts; + size_t end_count = 0; + for (unsigned i = 0; i < path_ends_.size(); i++) { + PathEnd *path_end = path_ends_[i]; + Vertex *vertex = path_end->vertex(sta_); + // Squish up to endpoint_path_count path ends per vertex + // up to the front of path_ends_. + if (end_count < static_cast(group_path_count_) + && path_counts[vertex] < static_cast(endpoint_path_count_)) { + path_ends_[end_count++] = path_end; + path_counts[vertex]++; + } + else + delete path_end; + } + path_ends_.resize(end_count); + + // Set a threshold to the bottom of the sorted list that future + // inserts need to beat. + PathEnd *last_end = path_ends_[end_count - 1]; + if (cmp_slack_) + threshold_ = delayAsFloat(last_end->slack(sta_)); else - delete path_end; - if (displaced) - delete *displaced; + threshold_ = delayAsFloat(last_end->dataArrivalTime(sta_)); } void PathGroup::pushEnds(PathEndSeq &path_ends) { - if (!heap_.empty()) { - PathEndSeq ends = heap_.contents(); - path_ends.reserve(path_ends.size() + ends.size()); - // Append heap path ends to path_ends. - path_ends.insert(path_ends.end(), - std::make_move_iterator(ends.begin()), - std::make_move_iterator(ends.end())); - } + ensureSortedMaxPaths(); + for (PathEnd *path_end : path_ends_) + path_ends.push_back(path_end); +} + +void +PathGroup::ensureSortedMaxPaths() +{ + if (path_ends_.size() > static_cast(group_path_count_)) + prune(); + else + sort(); +} + +void +PathGroup::sort() +{ + sta::sort(path_ends_, PathEndLess(cmp_slack_, sta_)); } void PathGroup::clear() { + threshold_ = min_max_->initValue(); LockGuard lock(lock_); - heap_.clear(); + path_ends_.clear(); } //////////////////////////////////////////////////////////////// @@ -857,8 +897,11 @@ PathGroups::enumPathEnds(PathGroup *group, // enumerator. PathEnum path_enum(group_path_count, endpoint_path_count, unique_pins, unique_edges, cmp_slack, this); - for (PathEnd *end : group->pathEnds()) - path_enum.insert(end); + for (PathEnd *end : group->pathEnds()) { + if (group->saveable(end) + || group->enumMinSlackUnderMin(end)) + path_enum.insert(end); + } group->clear(); // Parallel path enumeratation to find the endpoint_path_count/max path ends.