diff --git a/include/sta/BoundedHeap.hh b/include/sta/BoundedHeap.hh index 45bfdeed..af934e0c 100644 --- a/include/sta/BoundedHeap.hh +++ b/include/sta/BoundedHeap.hh @@ -60,7 +60,6 @@ public: comp_(comp), min_heap_comp_(comp) { - heap_.reserve(max_size); } // Copy constructor @@ -107,7 +106,12 @@ public: setMaxSize(size_t max_size) { max_size_ = max_size; - heap_.reserve(max_size); + } + + void + reserve(size_t size) + { + heap_.reserve(size); } // Insert an element into the heap. @@ -172,8 +176,6 @@ public: { // Convert heap to sorted vector (best to worst) std::sort_heap(heap_.begin(), heap_.end(), min_heap_comp_); - // Reverse to get best first (according to user's comparison) - std::reverse(heap_.begin(), heap_.end()); std::vector result = std::move(heap_); heap_.clear(); return result; @@ -181,11 +183,10 @@ public: // Extract all elements sorted from best to worst (const version). // Creates a copy since we can't modify the heap. - std::vector extract() const + std::vector contents() const { std::vector temp_heap = heap_; std::sort_heap(temp_heap.begin(), temp_heap.end(), min_heap_comp_); - std::reverse(temp_heap.begin(), temp_heap.end()); return temp_heap; } @@ -245,7 +246,7 @@ private: Compare comp_; explicit MinHeapCompare(const Compare& c) : comp_(c) {} bool operator()(const T& a, const T& b) const { - return comp_(b, a); // Inverted: worst is at root + return comp_(a, b); // comp = less puts largest at root (worst) } }; diff --git a/include/sta/PathEnd.hh b/include/sta/PathEnd.hh index 4f974f3f..ee8deb39 100644 --- a/include/sta/PathEnd.hh +++ b/include/sta/PathEnd.hh @@ -153,9 +153,13 @@ public: static bool less(const PathEnd *path_end1, const PathEnd *path_end2, + // Compare slack (if constrained), or arrival when false. + bool cmp_slack, const StaState *sta); static int cmp(const PathEnd *path_end1, const PathEnd *path_end2, + // Compare slack (if constrained), or arrival when false. + bool cmp_slack, const StaState *sta); static int cmpSlack(const PathEnd *path_end1, const PathEnd *path_end2, @@ -611,11 +615,13 @@ protected: class PathEndLess { public: - PathEndLess(const StaState *sta); + PathEndLess(bool cmp_slack, + const StaState *sta); bool operator()(const PathEnd *path_end1, const PathEnd *path_end2) const; protected: + bool cmp_slack_; const StaState *sta_; }; @@ -623,11 +629,13 @@ protected: class PathEndSlackLess { public: - PathEndSlackLess(const StaState *sta); + PathEndSlackLess(bool cmp_slack, + const StaState *sta); bool operator()(const PathEnd *path_end1, const PathEnd *path_end2) const; protected: + bool cmp_slack_; const StaState *sta_; }; diff --git a/include/sta/PathGroup.hh b/include/sta/PathGroup.hh index 58bb84d9..03bcb0c5 100644 --- a/include/sta/PathGroup.hh +++ b/include/sta/PathGroup.hh @@ -29,10 +29,12 @@ #include #include +#include "BoundedHeap.hh" #include "SdcClass.hh" #include "StaState.hh" #include "SearchClass.hh" #include "StringUtil.hh" +#include "PathEnd.hh" namespace sta { @@ -48,7 +50,6 @@ using PathGroupSeq = std::vector; class PathGroup { public: - ~PathGroup(); // Path group that compares compare slacks. static PathGroup *makePathGroupArrival(const char *name, int group_path_count, @@ -68,7 +69,7 @@ public: const StaState *sta); const std::string &name() const { return name_; } const MinMax *minMax() const { return min_max_;} - const PathEndSeq &pathEnds() const { return path_ends_; } + PathEndSeq pathEnds() const; void insert(PathEnd *path_end); // Push group_path_count into path_ends. void pushEnds(PathEndSeq &path_ends); @@ -76,15 +77,14 @@ public: bool saveable(PathEnd *path_end); bool enumMinSlackUnderMin(PathEnd *path_end); int maxPaths() const { return group_path_count_; } - PathEndSeq &pathEnds() { return path_ends_; } // This does NOT delete the path ends. void clear(); - static size_t group_path_count_max; + static int group_path_count_max; protected: PathGroup(const char *name, - size_t group_path_count, - size_t endpoint_path_count, + int group_path_count, + int endpoint_path_count, bool unique_pins, bool unique_edges, float min_slack, @@ -92,21 +92,17 @@ protected: bool cmp_slack, const MinMax *min_max, const StaState *sta); - void ensureSortedMaxPaths(); - void prune(); - void sort(); std::string name_; - size_t group_path_count_; - size_t endpoint_path_count_; + int group_path_count_; + int endpoint_path_count_; bool unique_pins_; bool unique_edges_; float slack_min_; float slack_max_; - PathEndSeq path_ends_; const MinMax *min_max_; - bool compare_slack_; - float threshold_; + bool cmp_slack_; + BoundedHeap heap_; std::mutex lock_; const StaState *sta_; }; diff --git a/include/sta/Search.hh b/include/sta/Search.hh index bc516502..ba4f8d0d 100644 --- a/include/sta/Search.hh +++ b/include/sta/Search.hh @@ -100,8 +100,8 @@ public: bool unconstrained, const SceneSeq &scenes, const MinMaxAll *min_max, - size_t group_path_count, - size_t endpoint_path_count, + int group_path_count, + int endpoint_path_count, bool unique_pins, bool unique_edges, float slack_min, diff --git a/search/PathEnd.cc b/search/PathEnd.cc index 7e72e6fb..33b6e1cd 100644 --- a/search/PathEnd.cc +++ b/search/PathEnd.cc @@ -2030,32 +2030,22 @@ PathEndPathDelay::exceptPathCmp(const PathEnd *path_end, //////////////////////////////////////////////////////////////// -PathEndLess::PathEndLess(const StaState *sta) : - sta_(sta) -{ -} - -bool -PathEndLess::operator()(const PathEnd *path_end1, - const PathEnd *path_end2) const -{ - return PathEnd::less(path_end1, path_end2, sta_); -} - bool PathEnd::less(const PathEnd *path_end1, const PathEnd *path_end2, + bool cmp_slack, const StaState *sta) { - return cmp(path_end1, path_end2, sta) < 0; + return cmp(path_end1, path_end2, cmp_slack, sta) < 0; } int PathEnd::cmp(const PathEnd *path_end1, const PathEnd *path_end2, + bool cmp_slack, const StaState *sta) { - int cmp = path_end1->isUnconstrained() + int cmp = !cmp_slack || path_end1->isUnconstrained() ? -cmpArrival(path_end1, path_end2, sta) : cmpSlack(path_end1, path_end2, sta); if (cmp == 0) { @@ -2139,7 +2129,25 @@ PathEnd::cmpNoCrpr(const PathEnd *path_end1, //////////////////////////////////////////////////////////////// -PathEndSlackLess::PathEndSlackLess(const StaState *sta) : +PathEndLess::PathEndLess(bool cmp_slack, + const StaState *sta) : + cmp_slack_(cmp_slack), + sta_(sta) +{ +} + +bool +PathEndLess::operator()(const PathEnd *path_end1, + const PathEnd *path_end2) const +{ + return PathEnd::less(path_end1, path_end2, cmp_slack_, sta_); +} + +//////////////////////////////////////////////////////////////// + +PathEndSlackLess::PathEndSlackLess(bool cmp_slack, + const StaState *sta) : + cmp_slack_(cmp_slack), sta_(sta) { } diff --git a/search/PathEnum.cc b/search/PathEnum.cc index 8cc8c9c9..67465a1b 100644 --- a/search/PathEnum.cc +++ b/search/PathEnum.cc @@ -91,7 +91,7 @@ DiversionGreater::operator()(Diversion *div1, { PathEnd *path_end1 = div1->pathEnd(); PathEnd *path_end2 = div2->pathEnd(); - return PathEnd::cmp(path_end1, path_end2, sta_) > 0; + return PathEnd::cmp(path_end1, path_end2, true, sta_) > 0; } static void diff --git a/search/PathGroup.cc b/search/PathGroup.cc index 794d2c6e..8f3738c6 100644 --- a/search/PathGroup.cc +++ b/search/PathGroup.cc @@ -50,7 +50,7 @@ namespace sta { -size_t PathGroup::group_path_count_max = std::numeric_limits::max(); +int PathGroup::group_path_count_max = std::numeric_limits::max(); PathGroup * PathGroup::makePathGroupSlack(const char *name, @@ -82,8 +82,8 @@ PathGroup::makePathGroupArrival(const char *name, } PathGroup::PathGroup(const char *name, - size_t group_path_count, - size_t endpoint_path_count, + int group_path_count, + int endpoint_path_count, bool unique_pins, bool unique_edges, float slack_min, @@ -99,43 +99,36 @@ PathGroup::PathGroup(const char *name, slack_min_(slack_min), slack_max_(slack_max), min_max_(min_max), - compare_slack_(cmp_slack), - threshold_(min_max->initValue()), + cmp_slack_(cmp_slack), + heap_(group_path_count, PathEndLess(cmp_slack, sta)), sta_(sta) { } -PathGroup::~PathGroup() +PathEndSeq +PathGroup::pathEnds() const { - deleteContents(path_ends_); + return heap_.contents(); } bool PathGroup::saveable(PathEnd *path_end) { - float threshold; - { - LockGuard lock(lock_); - threshold = threshold_; - } - if (compare_slack_) { + 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, threshold, sta_) && delayLessEqual(slack, slack_max_, sta_)) { // Now check with crpr. slack = path_end->slack(sta_); - return delayLessEqual(slack, threshold, sta_) - && delayLessEqual(slack, slack_max_, sta_) + return delayLessEqual(slack, slack_max_, sta_) && delayGreaterEqual(slack, slack_min_, sta_); } } else { const Arrival &arrival = path_end->dataArrivalTime(sta_); - return !delayIsInitValue(arrival, min_max_) - && delayGreaterEqual(arrival, threshold, min_max_, sta_); + return !delayIsInitValue(arrival, min_max_); } return false; } @@ -148,7 +141,7 @@ PathGroup::saveable(PathEnd *path_end) bool PathGroup::enumMinSlackUnderMin(PathEnd *path_end) { - if (compare_slack_ + if (cmp_slack_ && endpoint_path_count_ > 1 && slack_min_ > -INF) { const Path *path = path_end->path(); @@ -177,72 +170,28 @@ void PathGroup::insert(PathEnd *path_end) { LockGuard lock(lock_); - path_ends_.push_back(path_end); + heap_.insert(path_end); path_end->setPathGroup(this); - if (group_path_count_ != group_path_count_max - && path_ends_.size() > 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 < group_path_count_ - && path_counts[vertex] < 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 (compare_slack_) - threshold_ = delayAsFloat(last_end->slack(sta_)); - else - threshold_ = delayAsFloat(last_end->dataArrivalTime(sta_)); } void PathGroup::pushEnds(PathEndSeq &path_ends) { - ensureSortedMaxPaths(); - for (PathEnd *path_end : path_ends_) - path_ends.push_back(path_end); -} - -void -PathGroup::ensureSortedMaxPaths() -{ - if (path_ends_.size() > group_path_count_) - prune(); - else - sort(); -} - -void -PathGroup::sort() -{ - sta::sort(path_ends_, PathEndLess(sta_)); + if (!heap_.empty()) { + PathEndSeq ends = heap_.extract(); + 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())); + } } void PathGroup::clear() { LockGuard lock(lock_); - threshold_ = min_max_->initValue(); - path_ends_.clear(); + heap_.clear(); } //////////////////////////////////////////////////////////////// @@ -632,9 +581,8 @@ PathGroups::makePathEnds(ExceptionTo *to, unique_pins_, unique_edges_, scenes, min_max); pushEnds(path_ends); - if (sort_by_slack) { - sort(path_ends, PathEndLess(this)); - } + if (sort_by_slack) + sort(path_ends, PathEndLess(true, this)); if (unconstrained_paths && path_ends.empty()) @@ -663,12 +611,12 @@ private: PathGroups *path_groups_; PathGroupEndMap ends_; - PathEndLess cmp_; + PathEndLess less_; }; MakePathEnds1::MakePathEnds1(PathGroups *path_groups) : path_groups_(path_groups), - cmp_(path_groups) + less_(true, path_groups) { } @@ -693,7 +641,7 @@ MakePathEnds1::visitPathEnd(PathEnd *path_end, // Only keep the path end with the smallest slack/latest arrival. PathEnd *worst_end = findKey(ends_, group); if (worst_end) { - if (cmp_(path_end, worst_end)) { + if (less_(path_end, worst_end)) { ends_[group] = path_end->copy(); delete worst_end; } @@ -741,8 +689,8 @@ private: PathGroups *path_groups_; const StaState *sta_; PathGroupEndsMap ends_; - PathEndSlackLess slack_cmp_; - PathEndNoCrprLess path_no_crpr_cmp_; + PathEndSlackLess less_; + PathEndNoCrprLess path_no_crpr_less_; }; MakePathEndsAll::MakePathEndsAll(int endpoint_path_count, @@ -750,8 +698,8 @@ MakePathEndsAll::MakePathEndsAll(int endpoint_path_count, endpoint_path_count_(endpoint_path_count), path_groups_(path_groups), sta_(path_groups), - slack_cmp_(path_groups), - path_no_crpr_cmp_(path_groups) + less_(true, path_groups), + path_no_crpr_less_(path_groups) { } @@ -792,8 +740,8 @@ MakePathEndsAll::vertexEnd(Vertex *) Debug *debug = sta_->debug(); for (auto [group, ends] : ends_) { if (ends) { - sort(ends, slack_cmp_); - PathEndNoCrprSet unique_ends(path_no_crpr_cmp_); + sort(ends, less_); + PathEndNoCrprSet unique_ends(path_no_crpr_less_); auto end_iter = ends->begin(); int n = 0; while (end_iter != ends->end() @@ -898,11 +846,8 @@ 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()) { - if (group->saveable(end) - || group->enumMinSlackUnderMin(end)) - path_enum.insert(end); - } + for (PathEnd *end : group->pathEnds()) + path_enum.insert(end); group->clear(); // Parallel path enumeratation to find the endpoint_path_count/max path ends. diff --git a/search/Search.cc b/search/Search.cc index c7cc2a58..871b0e0d 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -497,8 +497,8 @@ Search::findPathEnds(ExceptionFrom *from, bool unconstrained, const SceneSeq &scenes, const MinMaxAll *min_max, - size_t group_path_count, - size_t endpoint_path_count, + int group_path_count, + int endpoint_path_count, bool unique_pins, bool unique_edges, float slack_min,