PathGroup use BoundedHeap
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
9b2bdf85e1
commit
f1b33edd98
|
|
@ -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<T> 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<T> extract() const
|
||||
std::vector<T> contents() const
|
||||
{
|
||||
std::vector<T> 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)
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -29,10 +29,12 @@
|
|||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
#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<PathGroup*>;
|
|||
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<PathEnd*, PathEndLess> heap_;
|
||||
std::mutex lock_;
|
||||
const StaState *sta_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
size_t PathGroup::group_path_count_max = std::numeric_limits<size_t>::max();
|
||||
int PathGroup::group_path_count_max = std::numeric_limits<int>::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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue