diff --git a/include/sta/MinMaxValues.hh b/include/sta/MinMaxValues.hh index 85741be9..aa302071 100644 --- a/include/sta/MinMaxValues.hh +++ b/include/sta/MinMaxValues.hh @@ -166,8 +166,8 @@ public: == values2->values_[MinMax::maxIndex()])); } - static bool less(const MinMaxValues *values1, - const MinMaxValues *values2) + static int cmp(const MinMaxValues *values1, + const MinMaxValues *values2) { if (!values1->exists_[MinMax::minIndex()] && values2->exists_[MinMax::minIndex()]) diff --git a/search/ClkInfo.cc b/search/ClkInfo.cc index bae9b5b3..3c254284 100644 --- a/search/ClkInfo.cc +++ b/search/ClkInfo.cc @@ -24,6 +24,7 @@ #include "ClkInfo.hh" +#include "Units.hh" #include "Network.hh" #include "Graph.hh" #include "Sdc.hh" @@ -55,6 +56,7 @@ ClkInfo::ClkInfo(const ClockEdge *clk_edge, latency_(latency), is_propagated_(is_propagated), is_gen_clk_src_path_(is_gen_clk_src_path), + crpr_path_refs_filter_(crpr_clk_path ? crpr_clk_path->tag(sta)->isFilter() : false), is_pulse_clk_(pulse_clk_sense != nullptr), pulse_clk_sense_(pulse_clk_sense ? pulse_clk_sense->index() : 0), path_ap_index_(path_ap_index) @@ -78,7 +80,12 @@ ClkInfo::findHash(const StaState *sta) hashIncr(hash_, network->vertexId(clk_src_)); if (gen_clk_src_) hashIncr(hash_, network->vertexId(gen_clk_src_)); - hashIncr(hash_, crprClkVertexId(sta)); + if (crpr_clk_path_.isNull()) + hashIncr(hash_, vertex_id_null); + else { + hashIncr(hash_, crpr_clk_path_.vertexId(sta)); + hashIncr(hash_, crpr_clk_path_.tag(sta)->hash(false, sta)); + } if (uncertainties_) { float uncertainty; bool exists; @@ -101,19 +108,13 @@ ClkInfo::findHash(const StaState *sta) VertexId ClkInfo::crprClkVertexId(const StaState *sta) const { - if (crpr_clk_path_.isNull()) - return vertex_id_null; - else - return crpr_clk_path_.vertexId(sta); + return crpr_clk_path_.vertexId(sta); } Path * ClkInfo::crprClkPath(const StaState *sta) { - if (crpr_clk_path_.isNull()) - return nullptr; - else - return Path::vertexPath(crpr_clk_path_, sta); + return Path::vertexPath(crpr_clk_path_, sta); } const Path * @@ -125,6 +126,15 @@ ClkInfo::crprClkPath(const StaState *sta) const return Path::vertexPath(crpr_clk_path_, sta); } +const Path * +ClkInfo::crprClkPathRaw() const +{ + if (crpr_clk_path_.isNull()) + return nullptr; + else + return &crpr_clk_path_; +} + std::string ClkInfo::to_string(const StaState *sta) const { @@ -150,13 +160,37 @@ ClkInfo::to_string(const StaState *sta) const if (!crpr_clk_path_.isNull()) { const Pin *crpr_clk_pin = crpr_clk_path_.vertex(sta)->pin(); - result += " crpr_pin "; + result += " crpr "; result += network->pathName(crpr_clk_pin); + result += "/"; + result += std::to_string(crpr_clk_path_.tag(sta)->index()); } if (is_gen_clk_src_path_) result += " genclk"; + if (gen_clk_src_) { + result += " "; + result += network->pathName(gen_clk_src_); + } + if (insertion_ > 0.0) { + result += " insert"; + result += std::to_string(insertion_); + } + + if (uncertainties_) { + result += " uncertain "; + float uncertainty; + bool exists; + uncertainties_->value(MinMax::min(), uncertainty, exists); + if (exists) + result += sta->units()->timeUnit()->asString(uncertainty); + uncertainties_->value(MinMax::max(), uncertainty, exists); + if (exists) { + result += ":"; + result += sta->units()->timeUnit()->asString(uncertainty); + } + } return result; } @@ -178,13 +212,6 @@ ClkInfo::pulseClkSense() const return nullptr; } -bool -ClkInfo::refsFilter(const StaState *sta) const -{ - return !crpr_clk_path_.isNull() - && crpr_clk_path_.tag(sta)->isFilter(); -} - //////////////////////////////////////////////////////////////// size_t @@ -204,13 +231,13 @@ bool ClkInfoEqual::operator()(const ClkInfo *clk_info1, const ClkInfo *clk_info2) const { - return clkInfoEqual(clk_info1, clk_info2, sta_); + return ClkInfo::equal(clk_info1, clk_info2, sta_); } bool -clkInfoEqual(const ClkInfo *clk_info1, - const ClkInfo *clk_info2, - const StaState *sta) +ClkInfo::equal(const ClkInfo *clk_info1, + const ClkInfo *clk_info2, + const StaState *sta) { bool crpr_on = sta->crprActive(); ClockUncertainties *uncertainties1 = clk_info1->uncertainties(); @@ -220,14 +247,13 @@ clkInfoEqual(const ClkInfo *clk_info1, && clk_info1->clkSrc() == clk_info2->clkSrc() && clk_info1->genClkSrc() == clk_info2->genClkSrc() && (!crpr_on - || Path::equal(clk_info1->crprClkPath(sta), - clk_info2->crprClkPath(sta), + || Path::equal(clk_info1->crprClkPathRaw(), + clk_info2->crprClkPathRaw(), sta)) && ((uncertainties1 == nullptr && uncertainties2 == nullptr) || (uncertainties1 && uncertainties2 - && MinMaxValues::equal(uncertainties1, - uncertainties2))) + && ClockUncertainties::equal(uncertainties1, uncertainties2))) && clk_info1->insertion() == clk_info2->insertion() && clk_info1->latency() == clk_info2->latency() && clk_info1->isPropagated() == clk_info2->isPropagated() @@ -247,13 +273,13 @@ bool ClkInfoLess::operator()(const ClkInfo *clk_info1, const ClkInfo *clk_info2) const { - return clkInfoCmp(clk_info1, clk_info2, sta_) < 0; + return ClkInfo::cmp(clk_info1, clk_info2, sta_) < 0; } int -clkInfoCmp(const ClkInfo *clk_info1, - const ClkInfo *clk_info2, - const StaState *sta) +ClkInfo::cmp(const ClkInfo *clk_info1, + const ClkInfo *clk_info2, + const StaState *sta) { const ClockEdge *clk_edge1 = clk_info1->clkEdge(); const ClockEdge *clk_edge2 = clk_info2->clkEdge(); @@ -292,8 +318,8 @@ clkInfoCmp(const ClkInfo *clk_info1, bool crpr_on = sta->crprActive(); if (crpr_on) { - const Path *crpr_path1 = clk_info1->crprClkPath(sta); - const Path *crpr_path2 = clk_info2->crprClkPath(sta); + const Path *crpr_path1 = clk_info1->crprClkPathRaw(); + const Path *crpr_path2 = clk_info2->crprClkPathRaw(); int path_cmp = Path::cmp(crpr_path1, crpr_path2, sta); if (path_cmp != 0) return path_cmp; @@ -305,13 +331,11 @@ clkInfoCmp(const ClkInfo *clk_info1, return -1; if (uncertainties1 && uncertainties2 == nullptr) return 1; - if (uncertainties1 && uncertainties2 - && MinMaxValues::less(uncertainties1, uncertainties2)) - return -1; - if (uncertainties1 && uncertainties2 - && MinMaxValues::less(uncertainties2, uncertainties1)) - return 1; - + if (uncertainties1 && uncertainties2) { + int uncertain_cmp = ClockUncertainties::cmp(uncertainties1, uncertainties2); + if (uncertain_cmp != 0) + return uncertain_cmp; + } const Arrival &insert1 = clk_info1->insertion(); const Arrival &insert2 = clk_info2->insertion(); if (delayLess(insert1, insert2, sta)) diff --git a/search/ClkInfo.hh b/search/ClkInfo.hh index 825a182c..582d9dbb 100644 --- a/search/ClkInfo.hh +++ b/search/ClkInfo.hh @@ -69,13 +69,20 @@ public: const Path *crprClkPath(const StaState *sta) const; VertexId crprClkVertexId(const StaState *sta) const; bool hasCrprClkPin() const { return !crpr_clk_path_.isNull(); } - bool refsFilter(const StaState *sta) const; // This clk_info/tag is used for a generated clock source path. bool isGenClkSrcPath() const { return is_gen_clk_src_path_; } size_t hash() const { return hash_; } + bool crprPathRefsFilter() const { return crpr_path_refs_filter_; } + static int cmp(const ClkInfo *clk_info1, + const ClkInfo *clk_info2, + const StaState *sta); + static bool equal(const ClkInfo *clk_info1, + const ClkInfo *clk_info2, + const StaState *sta); protected: void findHash(const StaState *sta); + const Path *crprClkPathRaw() const; private: const ClockEdge *clk_edge_; @@ -88,20 +95,14 @@ private: size_t hash_; bool is_propagated_:1; bool is_gen_clk_src_path_:1; + // This is used to break a circular dependency in Search::deleteFilteredArrival + // between tags and clk infos that reference a filter. + bool crpr_path_refs_filter_:1; bool is_pulse_clk_:1; unsigned int pulse_clk_sense_:RiseFall::index_bit_count; unsigned int path_ap_index_:path_ap_index_bit_count; }; -int -clkInfoCmp(const ClkInfo *clk_info1, - const ClkInfo *clk_info2, - const StaState *sta); -bool -clkInfoEqual(const ClkInfo *clk_info1, - const ClkInfo *clk_info2, - const StaState *sta); - class ClkInfoLess { public: diff --git a/search/Crpr.cc b/search/Crpr.cc index 5cf041a5..62d6d94f 100644 --- a/search/Crpr.cc +++ b/search/Crpr.cc @@ -361,7 +361,7 @@ CheckCrpr::outputDelayCrpr1(const Path *src_path, Path *tgt_genclk_path = portClkPath(tgt_clk_edge, tgt_clk_edge->clock()->defaultPin(), tgt_path_ap); - Path *src_clk_path = src_path->clkInfo(this)->crprClkPath(this); + const Path *src_clk_path = src_path->clkInfo(this)->crprClkPath(this); if (src_clk_path) findCrpr(src_clk_path, tgt_genclk_path, same_pin, crpr, crpr_pin); } diff --git a/search/Path.cc b/search/Path.cc index 2aad3bc1..21640562 100644 --- a/search/Path.cc +++ b/search/Path.cc @@ -608,10 +608,20 @@ Path::cmp(const Path *path1, const Path *path2, const StaState *sta) { - if (path1 && path2) { + if (path1 == path2) + return 0; + else if (path1 == nullptr && path2) + return 1; + else if (path1 && path2 == nullptr) + return -1; + else { VertexId vertex_id1 = path1->vertexId(sta); VertexId vertex_id2 = path2->vertexId(sta); - if (vertex_id1 == vertex_id2) { + if (vertex_id1 < vertex_id2) + return -1; + else if (vertex_id1 > vertex_id2) + return 1; + else { TagIndex tag_index1 = path1->tagIndex(sta); TagIndex tag_index2 = path2->tagIndex(sta); if (tag_index1 == tag_index2) @@ -621,18 +631,7 @@ Path::cmp(const Path *path1, else return 1; } - else if (vertex_id1 < vertex_id2) - return -1; - else - return 1; } - else if (path1 == nullptr - && path2 == nullptr) - return 0; - else if (path1 == nullptr) - return -1; - else - return 1; } int diff --git a/search/Search.cc b/search/Search.cc index 82664cae..6ad6394a 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -235,7 +235,7 @@ Search::init(StaState *sta) arrival_iter_ = new BfsFwdIterator(BfsIndex::arrival, nullptr, sta); required_iter_ = new BfsBkwdIterator(BfsIndex::required, search_adj_, sta); tag_capacity_ = 128; - tag_set_ = new TagSet(tag_capacity_); + tag_set_ = new TagSet(tag_capacity_, TagHash(sta), TagEqual(sta)); clk_info_set_ = new ClkInfoSet(ClkInfoLess(sta)); tag_next_ = 0; tags_ = new Tag*[tag_capacity_]; @@ -543,8 +543,8 @@ Search::deleteFilteredArrivals() } filtered_arrivals_->clear(); deleteFilterTagGroups(); - deleteFilterClkInfos(); deleteFilterTags(); + deleteFilterClkInfos(); } deleteFilter(); } @@ -590,7 +590,7 @@ Search::deleteFilterClkInfos() { for (auto itr = clk_info_set_->cbegin(); itr != clk_info_set_->cend(); ) { ClkInfo *clk_info = *itr; - if (clk_info->refsFilter(this)) { + if (clk_info->crprPathRefsFilter()) { itr = clk_info_set_->erase(itr); delete clk_info; } @@ -614,8 +614,7 @@ Search::findFilteredArrivals(bool thru_latches) if (thru_latches) enqueuePendingLatchOutputs(); debugPrint(debug_, "search", 1, "find arrivals pass %d", pass); - int arrival_count = arrival_iter_->visitParallel(max_level, - arrival_visitor_); + int arrival_count = arrival_iter_->visitParallel(max_level, arrival_visitor_); deleteTagsPrev(); debugPrint(debug_, "search", 1, "found %d arrivals", arrival_count); } @@ -2727,7 +2726,7 @@ Search::mutateTag(Tag *from_tag, TagGroup * Search::findTagGroup(TagGroupBldr *tag_bldr) { - TagGroup probe(tag_bldr); + TagGroup probe(tag_bldr, this); LockGuard lock(tag_group_lock_); TagGroup *tag_group = tag_group_set_->findKey(&probe); if (tag_group == nullptr) { diff --git a/search/Tag.cc b/search/Tag.cc index 3db771b3..3c3fe930 100644 --- a/search/Tag.cc +++ b/search/Tag.cc @@ -262,26 +262,32 @@ Tag::findHash() for (ExceptionState *state : *states_) hashIncr(hash_, state->hash()); } + hashIncr(hash_, clk_info_->hash()); match_hash_ = hash_; // Finish hash_. - hashIncr(hash_, clk_info_->hash()); if (input_delay_) hashIncr(hash_, input_delay_->index()); // Finish match_hash_. - const ClockEdge *clk_edge = clk_info_->clkEdge(); - if (clk_edge) - hashIncr(match_hash_, clk_edge->index()); hashIncr(match_hash_, clk_info_->isGenClkSrcPath()); } +size_t +Tag::hash(bool match_crpr_clk_pin, + const StaState *sta) const +{ + if (match_crpr_clk_pin) + return hashSum(hash_, clk_info_->crprClkVertexId(sta)); + else + return hash_; +} + size_t Tag::matchHash(bool match_crpr_clk_pin, const StaState *sta) const { if (match_crpr_clk_pin) - // match_hash_ with crpr clk pin thrown in. return hashSum(match_hash_, clk_info_->crprClkVertexId(sta)); else return match_hash_; @@ -311,7 +317,7 @@ tagCmp(const Tag *tag1, ClkInfo *clk_info1 = tag1->clkInfo(); ClkInfo *clk_info2 = tag2->clkInfo(); - int clk_cmp = clkInfoCmp(clk_info1, clk_info2, sta); + int clk_cmp = ClkInfo::cmp(clk_info1, clk_info2, sta); if (clk_cmp != 0) return clk_cmp; @@ -357,12 +363,13 @@ tagCmp(const Tag *tag1, bool tagEqual(const Tag *tag1, - const Tag *tag2) + const Tag *tag2, + const StaState *sta) { return tag1 == tag2 || (tag1->rfIndex() == tag2->rfIndex() && tag1->pathAPIndex() == tag2->pathAPIndex() - && tag1->clkInfo() == tag2->clkInfo() + && ClkInfo::equal(tag1->clkInfo(), tag2->clkInfo(), sta) && tag1->isClock() == tag2->isClock() && tag1->inputDelay() == tag2->inputDelay() && tag1->isSegmentStart() == tag2->isSegmentStart() @@ -653,17 +660,28 @@ tagStateEqualCrpr(const Tag *tag1, //////////////////////////////////////////////////////////////// +TagHash::TagHash(const StaState *sta) : + sta_(sta) +{ +} + size_t TagHash::operator()(const Tag *tag) const { - return tag->hash(); + bool crpr_on = sta_->crprActive(); + return tag->matchHash(crpr_on, sta_); +} + +TagEqual::TagEqual(const StaState *sta) : + sta_(sta) +{ } bool TagEqual::operator()(const Tag *tag1, const Tag *tag2) const { - return tagEqual(tag1, tag2); + return tagEqual(tag1, tag2, sta_); } TagMatchHash::TagMatchHash(bool match_crpr_clk_pin, diff --git a/search/Tag.hh b/search/Tag.hh index d0e44506..6f9cccbd 100644 --- a/search/Tag.hh +++ b/search/Tag.hh @@ -85,7 +85,8 @@ public: bool isLoop() const { return is_loop_; } bool isFilter() const { return is_filter_; } bool isSegmentStart() const { return is_segment_start_; } - size_t hash() const { return hash_; } + size_t hash(bool match_crpr_clk_pin, + const StaState *sta) const; size_t matchHash(bool match_crpr_clk_pin, const StaState *sta) const; @@ -130,19 +131,28 @@ public: class TagHash { public: + TagHash(const StaState *sta); size_t operator()(const Tag *tag) const; + +private: + const StaState *sta_; }; class TagEqual { public: + TagEqual(const StaState *sta); bool operator()(const Tag *tag1, const Tag *tag2) const; + +private: + const StaState *sta_; }; bool tagEqual(const Tag *tag1, - const Tag *tag2); + const Tag *tag2, + const StaState *sta); int tagCmp(const Tag *tag1, const Tag *tag2, diff --git a/search/TagGroup.cc b/search/TagGroup.cc index 5a79f7de..aed495e5 100644 --- a/search/TagGroup.cc +++ b/search/TagGroup.cc @@ -41,9 +41,10 @@ TagGroup::TagGroup(TagGroupIndex index, bool has_clk_tag, bool has_genclk_src_tag, bool has_filter_tag, - bool has_loop_tag) : + bool has_loop_tag, + const StaState *sta) : path_index_map_(path_index_map), - hash_(pathIndexMapHash(path_index_map)), + hash_(hash(path_index_map, sta)), ref_count_(0), index_(index), has_clk_tag_(has_clk_tag), @@ -54,9 +55,10 @@ TagGroup::TagGroup(TagGroupIndex index, { } -TagGroup::TagGroup(TagGroupBldr *tag_bldr) : +TagGroup::TagGroup(TagGroupBldr *tag_bldr, + const StaState *sta) : path_index_map_(&tag_bldr->pathIndexMap()), - hash_(pathIndexMapHash(path_index_map_)), + hash_(hash(path_index_map_, sta)), ref_count_(0), own_path_map_(false) { @@ -81,11 +83,13 @@ TagGroup::decrRefCount() } size_t -TagGroup::pathIndexMapHash(PathIndexMap *path_index_map) +TagGroup::hash(PathIndexMap *path_index_map, + const StaState *sta) { + bool crpr_on = sta->crprActive(); size_t hash = 0; for (auto const [tag, path_index] : *path_index_map) - hash += tag->hash(); + hash += tag->hash(crpr_on, sta); return hash; } @@ -268,7 +272,7 @@ TagGroupBldr::insertPath(Tag *tag, if (tag->isGenClkSrcPath()) has_genclk_src_tag_ = true; if (tag->isFilter() - || tag->clkInfo()->refsFilter(sta_)) + || tag->clkInfo()->crprPathRefsFilter()) has_filter_tag_ = true; if (tag->isLoop()) has_loop_tag_ = true; @@ -289,7 +293,7 @@ TagGroupBldr::makeTagGroup(TagGroupIndex index, { return new TagGroup(index, makePathIndexMap(sta), has_clk_tag_, has_genclk_src_tag_, has_filter_tag_, - has_loop_tag_); + has_loop_tag_, sta); } diff --git a/search/TagGroup.hh b/search/TagGroup.hh index 5039bd5e..88722d5f 100644 --- a/search/TagGroup.hh +++ b/search/TagGroup.hh @@ -47,9 +47,11 @@ public: bool has_clk_tag, bool has_genclk_src_tag, bool has_filter_tag, - bool has_loop_tag); + bool has_loop_tag, + const StaState *sta); // For Search::findTagGroup to probe. - TagGroup(TagGroupBldr *tag_bldr); + TagGroup(TagGroupBldr *tag_bldr, + const StaState *sta); ~TagGroup(); TagGroupIndex index() const { return index_; } size_t hash() const { return hash_; } @@ -72,7 +74,8 @@ public: int refCount() const { return ref_count_; } protected: - static size_t pathIndexMapHash(PathIndexMap *path_index_map); + static size_t hash(PathIndexMap *path_index_map, + const StaState *sta); // tag -> path index PathIndexMap *path_index_map_;