diff --git a/CMakeLists.txt b/CMakeLists.txt index e80a0ba3..41ac2c80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,6 +126,7 @@ set(STA_SOURCE parasitics/SpefReader.cc parasitics/SpefReaderPvt.hh + sdc/SdcClass.cc sdc/Clock.cc sdc/ClockGatingCheck.cc sdc/ClockGroups.cc diff --git a/include/sta/Sdc.hh b/include/sta/Sdc.hh index 75403ca0..e7a94d1b 100644 --- a/include/sta/Sdc.hh +++ b/include/sta/Sdc.hh @@ -993,27 +993,27 @@ public: const Clock *clk, const RiseFall *clk_rf, const MinMax *min_max, - ExceptionStateSet *&states) const; + ExceptionStates &states) const; bool exceptionFromStates(const Pin *pin, const RiseFall *rf, const Clock *clk, const RiseFall *clk_rf, const MinMax *min_max, bool include_filter, - ExceptionStateSet *&states) const; + ExceptionStates &states) const; void exceptionFromClkStates(const Pin *pin, const RiseFall *rf, const Clock *clk, const RiseFall *clk_rf, const MinMax *min_max, - ExceptionStateSet *&states) const; + ExceptionStates &states) const; void filterRegQStates(const Pin *to_pin, const RiseFall *to_rf, const MinMax *min_max, - ExceptionStateSet *&states) const; + ExceptionStates &states) const; // Return hierarchical -thru exceptions that start between // from_pin and to_pin. - ExceptionStateSet *exceptionThruStates(const Pin *from_pin, + ExceptionStates exceptionThruStates(const Pin *from_pin, const Pin *to_pin, const RiseFall *to_rf, const MinMax *min_max) const; @@ -1176,12 +1176,12 @@ protected: const RiseFall *rf, const MinMax *min_max, bool include_filter, - ExceptionStateSet *&states) const; + ExceptionStates &states) const; void exceptionThruStates(const ExceptionPathSet *exceptions, const RiseFall *to_rf, const MinMax *min_max, // Return value. - ExceptionStateSet *&states) const; + ExceptionStates &states) const; void exceptionTo(const ExceptionPathSet *to_exceptions, ExceptionPathType type, const Pin *pin, diff --git a/include/sta/SdcClass.hh b/include/sta/SdcClass.hh index 68f1ef14..4e32f4ea 100644 --- a/include/sta/SdcClass.hh +++ b/include/sta/SdcClass.hh @@ -16,6 +16,7 @@ #pragma once +#include #include "Map.hh" #include "Set.hh" #include "Vector.hh" @@ -112,7 +113,83 @@ public: }; class ExceptionPath; -typedef Set ExceptionStateSet; +class ExceptionStates { +public: + typedef Set Super; + ExceptionStates() : holder_(nullptr), hasLoopPath_(false), hasFilterPath_(false) {} + ExceptionStates(ExceptionStates&& o) noexcept : holder_(o.holder_), hasLoopPath_(o.hasLoopPath_), hasFilterPath_(o.hasFilterPath_) { + o.holder_ = nullptr; + } + ExceptionStates(const ExceptionStates& o) = delete; + ExceptionStates& operator=(const ExceptionStates & o) = delete; + ~ExceptionStates() { delete holder_; } + explicit operator bool () const { return holder_; } + bool hasLoopPath() const { return hasLoopPath_; } + bool hasFilterPath() const { return hasFilterPath_; } + + void insert(ExceptionState* state); + void clear(); + + void to(Super& s) { if (holder_) s.swap(*holder_); } + void takeOver(ExceptionStates&& o) { + clear(); + holder_ = o.holder_; + hasLoopPath_ = o.hasLoopPath_; + hasFilterPath_ = o.hasFilterPath_; + o.holder_ = nullptr; + } +private: + Super *holder_; + bool hasLoopPath_; + bool hasFilterPath_; +}; + +class ExceptionStateSet { + struct Impl : public Set { + typedef Set Super; + Impl(ExceptionStates & tmp) : Super(), hash_(hash_init_value), refcount(0), hasLoopPath_(tmp.hasLoopPath()), hasFilterPath_(tmp.hasFilterPath()) { tmp.to(super()); rehash(); } + size_t hash() const { return hash_; } + bool operator == (Impl const & i) const; + + size_t hash_; + unsigned refcount :30; + bool hasLoopPath_ :1; + bool hasFilterPath_:1; + protected: + Super& super() { return *this; } + void rehash(); + }; + Impl* impl; +public: + ExceptionStateSet(ExceptionStates & tmp) : impl(create(tmp)) { incr(impl); } + ExceptionStateSet(const ExceptionStateSet & o) : impl(o.impl) { incr(impl); } + ExceptionStateSet& operator=(const ExceptionStateSet & o) { + Impl* i = o.impl; incr(i); decr(impl); impl = i; return *this; + } + explicit operator bool () const { return impl; } + bool operator==(const ExceptionStateSet& o) const; + bool empty() const { return !impl; } + size_t size() const { return impl ? impl->size() : 0; } + struct ConstIterator : public Impl::Super::ConstIterator { + ConstIterator(const ExceptionStateSet& set) : Impl::Super::ConstIterator(set.impl) {} + }; + Impl::Super::const_iterator begin() const { return impl->begin(); } + Impl::Super::const_iterator end() const { return impl->end(); } + int cmp(ExceptionStateSet const & o) const; + bool hasLoopPath() const { return impl && impl->hasLoopPath_; } + bool hasFilterPath() const { return impl && impl->hasFilterPath_; } + size_t hash() const { return impl ? impl->hash() : 0; } +private: + void incr(Impl* i) { if (i) ++i->refcount; } + void decr(Impl* i) { if (i && --i->refcount == 0) { mgr.erase(i); delete i; } } + Impl* create(ExceptionStates & tmp); + + struct ImplHash { size_t operator()(Impl* i) const { return i ? i->hash() : 0; } }; + struct ImplEqual { bool operator()(Impl* a, Impl* b) const { return a == b || (a && b && *a == *b); } }; + typedef std::unordered_set Manager; + static Impl* unique(Impl* i); + static thread_local Manager mgr; +}; enum class CrprMode { same_pin, same_transition }; diff --git a/include/sta/Search.hh b/include/sta/Search.hh index 8dce6775..7a4f7231 100644 --- a/include/sta/Search.hh +++ b/include/sta/Search.hh @@ -312,8 +312,7 @@ public: bool is_clk, InputDelay *input_delay, bool is_segment_start, - ExceptionStateSet *states, - bool own_states); + const ExceptionStateSet& states); void reportTags() const; void reportClkInfos() const; virtual ClkInfo *findClkInfo(const ClockEdge *clk_edge, diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index 99db7c8a..990a4cfa 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -5126,7 +5126,7 @@ Sdc::exceptionFromStates(const Pin *pin, const Clock *clk, const RiseFall *clk_rf, const MinMax *min_max, - ExceptionStateSet *&states) const + ExceptionStates &states) const { return exceptionFromStates(pin, rf, clk, clk_rf, min_max, true, states); } @@ -5138,7 +5138,7 @@ Sdc::exceptionFromStates(const Pin *pin, const RiseFall *clk_rf, const MinMax *min_max, bool include_filter, - ExceptionStateSet *&states) const + ExceptionStates &states) const { bool srch_from = true; if (pin) { @@ -5170,8 +5170,7 @@ Sdc::exceptionFromStates(const Pin *pin, pin, clk_rf, min_max, include_filter, states); if (!srch_from) { - delete states; - states = nullptr; + states.clear(); } return srch_from; } @@ -5182,7 +5181,7 @@ Sdc::exceptionFromStates(const ExceptionPathSet *exceptions, const RiseFall *rf, const MinMax *min_max, bool include_filter, - ExceptionStateSet *&states) const + ExceptionStates &states) const { if (exceptions) { for (ExceptionPath *exception : *exceptions) { @@ -5201,17 +5200,13 @@ Sdc::exceptionFromStates(const ExceptionPathSet *exceptions, // Leave the completed false path state as a marker on the tag, // but flush all other exception states because they are lower // priority. - if (states == nullptr) - states = new ExceptionStateSet(); - states->clear(); - states->insert(state); + states.clear(); + states.insert(state); // No need to examine other exceptions from this // pin/clock/instance. return false; } - if (states == nullptr) - states = new ExceptionStateSet(); - states->insert(state); + states.insert(state); } } } @@ -5224,7 +5219,7 @@ Sdc::exceptionFromClkStates(const Pin *pin, const Clock *clk, const RiseFall *clk_rf, const MinMax *min_max, - ExceptionStateSet *&states) const + ExceptionStates &states) const { if (pin) { if (!first_from_pin_exceptions_.empty()) @@ -5247,7 +5242,7 @@ void Sdc::filterRegQStates(const Pin *to_pin, const RiseFall *to_rf, const MinMax *min_max, - ExceptionStateSet *&states) const + ExceptionStates &states) const { if (!first_from_pin_exceptions_.empty()) { const ExceptionPathSet *exceptions = @@ -5258,22 +5253,20 @@ Sdc::filterRegQStates(const Pin *to_pin, if (exception->isFilter() && exception->matchesFirstPt(to_rf, min_max)) { ExceptionState *state = exception->firstState(); - if (states == nullptr) - states = new ExceptionStateSet(); - states->insert(state); + states.insert(state); } } } } } -ExceptionStateSet * +ExceptionStates Sdc::exceptionThruStates(const Pin *from_pin, const Pin *to_pin, const RiseFall *to_rf, const MinMax *min_max) const { - ExceptionStateSet *states = nullptr; + ExceptionStates states; exceptionThruStates(first_thru_pin_exceptions_.findKey(to_pin), to_rf, min_max, states); if (!first_thru_edge_exceptions_.empty()) { @@ -5296,15 +5289,13 @@ Sdc::exceptionThruStates(const ExceptionPathSet *exceptions, const RiseFall *to_rf, const MinMax *min_max, // Return value. - ExceptionStateSet *&states) const + ExceptionStates &states) const { if (exceptions) { for (ExceptionPath *exception : *exceptions) { if (exception->matchesFirstPt(to_rf, min_max)) { ExceptionState *state = exception->firstState(); - if (states == nullptr) - states = new ExceptionStateSet(); - states->insert(state); + states.insert(state); } } } diff --git a/sdc/SdcClass.cc b/sdc/SdcClass.cc new file mode 100644 index 00000000..2aa81f1c --- /dev/null +++ b/sdc/SdcClass.cc @@ -0,0 +1,76 @@ +#include "SdcClass.hh" +#include "Sdc.hh" + +namespace sta { + +void +ExceptionStates::insert(ExceptionState* state) { + if (!holder_) holder_ = new Super; + holder_->insert(state); + if (!hasLoopPath_ && state->exception()->isLoop()) hasLoopPath_ = true; + if (!hasFilterPath_ && state->exception()->isFilter()) hasFilterPath_ = true; +} + +void +ExceptionStates::clear() { + delete holder_; + holder_ = nullptr; + hasLoopPath_ = false; +} + +bool +ExceptionStateSet::Impl::operator == (Impl const & i) const { + return (*(Super*)this) == (*(Super*)&i); +} + +void +ExceptionStateSet::Impl::rehash() { + hash_ = hash_init_value; + for(auto* state : *this) { + hashIncr(hash_, state->hash()); + } +} + +bool +ExceptionStateSet::operator==(const ExceptionStateSet& o) const { + return impl == o.impl; +} + +thread_local ExceptionStateSet::Manager +ExceptionStateSet::mgr; + +ExceptionStateSet::Impl* +ExceptionStateSet::unique(Impl* i) { + if (i->empty()) { + delete i; + return nullptr; + } + auto r = mgr.insert(i); + if (!r.second) { + delete i; + i = *r.first; + } + return i; +} + +ExceptionStateSet::Impl* +ExceptionStateSet::create(ExceptionStates & tmp) { + return tmp ? unique(new Impl(tmp)) : nullptr; +} + +int +ExceptionStateSet::cmp (const ExceptionStateSet & o) const { + size_t sz1 = size(); + size_t sz2 = o.size(); + if (sz1 != sz2) return sz1 < sz2 ? 1 : -1; + if (!sz1) return true; + auto it1 = begin(); + auto it2 = o.begin(); + while (*it1 == *it2) { + ++it1, ++it2; + } + if (it1 == end()) return 0; + return *it1 < *it2 ? 1 : -1; +} + +} // end namespace sta \ No newline at end of file diff --git a/search/CheckMinPulseWidths.cc b/search/CheckMinPulseWidths.cc index f1835b39..5f5713a0 100644 --- a/search/CheckMinPulseWidths.cc +++ b/search/CheckMinPulseWidths.cc @@ -337,7 +337,7 @@ MinPulseWidthCheck::closePath(const StaState *sta, open_tag->inputDelay(), open_tag->isSegmentStart(), open_tag->states(), - false, sta); + sta); debugPrint(sta->debug(), "mpw", 3, " open %s", open_tag->asString(sta)); debugPrint(sta->debug(), "mpw", 3, " close %s", diff --git a/search/Genclks.cc b/search/Genclks.cc index 7d264770..0340ec95 100644 --- a/search/Genclks.cc +++ b/search/Genclks.cc @@ -703,14 +703,14 @@ Genclks::makeTag(const Clock *gclk, // from the get go. if (master_pin == gclk->srcPin()) state = state->nextState(); - ExceptionStateSet *states = new ExceptionStateSet(); - states->insert(state); + ExceptionStates states; + states.insert(state); ClkInfo *clk_info = search_->findClkInfo(master_clk->edge(master_rf), master_pin, true, nullptr, true, nullptr, 0.0, 0.0, nullptr, path_ap, nullptr); return search_->findTag(master_rf, path_ap, clk_info, false, nullptr, false, - states, true); + states); } class GenClkArrivalSearchPred : public EvalPred @@ -948,19 +948,16 @@ Genclks::matchesSrcFilter(Path *path, const Clock *gclk) const { Tag *tag = path->tag(this); - const ExceptionStateSet *states = tag->states(); - if (tag->isGenClkSrcPath() - && states) { - ExceptionStateSet::ConstIterator state_iter(states); - while (state_iter.hasNext()) { - ExceptionState *state = state_iter.next(); - ExceptionPath *except = state->exception(); - if (except->isFilter() - && state->nextThru() == nullptr - && except->to() - && except->to()->matches(gclk)) - return true; - } + const ExceptionStateSet& states = tag->states(); + if (!tag->isGenClkSrcPath() || !states || !states.hasFilterPath()) + return false; + for (ExceptionState* state : states) { + ExceptionPath *except = state->exception(); + if (except->isFilter() + && state->nextThru() == nullptr + && except->to() + && except->to()->matches(gclk)) + return true; } return false; } diff --git a/search/Latches.cc b/search/Latches.cc index 3ec2dfe8..783b6df4 100644 --- a/search/Latches.cc +++ b/search/Latches.cc @@ -364,7 +364,7 @@ Latches::latchOutArrival(Path *data_path, path_ap, crpr_clk_path); RiseFall *q_rf = d_q_arc->toEdge()->asRiseFall(); - ExceptionStateSet *states = nullptr; + ExceptionStates states; // Latch data pin is a valid exception -from pin. if (sdc_->exceptionFromStates(data_path->pin(this), data_path->transition(this), @@ -377,7 +377,7 @@ Latches::latchOutArrival(Path *data_path, en_clk_edge->transition(), MinMax::max(), false, states)) q_tag = search_->findTag(q_rf, path_ap, q_clk_info, false, - nullptr, false, states, true); + nullptr, false, states); } return; } diff --git a/search/PathEnum.cc b/search/PathEnum.cc index 77621ffa..da27a706 100644 --- a/search/PathEnum.cc +++ b/search/PathEnum.cc @@ -609,7 +609,7 @@ PathEnum::updatePathHeadDelays(PathEnumedSeq &paths, tag->isClock(), tag->inputDelay(), tag->isSegmentStart(), - tag->states(), false); + tag->states()); path->setTag(updated_tag); } } diff --git a/search/PathVertex.cc b/search/PathVertex.cc index 09b53880..5f708d99 100644 --- a/search/PathVertex.cc +++ b/search/PathVertex.cc @@ -420,16 +420,14 @@ PrevPathVisitor::visitFromToPath(const Pin *, Tag * PrevPathVisitor::unfilteredTag(const Tag *tag) const { - ExceptionStateSet *unfiltered_states = nullptr; - const ExceptionStateSet *states = tag->states(); - ExceptionStateSet::ConstIterator state_iter(states); - while (state_iter.hasNext()) { - ExceptionState *state = state_iter.next(); + const ExceptionStateSet& states = tag->states(); + if (!states.hasFilterPath()) + return (Tag*)tag; + ExceptionStates unfiltered_states; + for (ExceptionState *state : states) { ExceptionPath *except = state->exception(); if (!except->isFilter()) { - if (unfiltered_states == nullptr) - unfiltered_states = new ExceptionStateSet(); - unfiltered_states->insert(state); + unfiltered_states.insert(state); } } return search_->findTag(tag->transition(), @@ -438,7 +436,7 @@ PrevPathVisitor::unfilteredTag(const Tag *tag) const tag->isClock(), tag->inputDelay(), tag->isSegmentStart(), - unfiltered_states, true); + unfiltered_states); } //////////////////////////////////////////////////////////////// diff --git a/search/Search.cc b/search/Search.cc index 9cc3d1df..a87f9b32 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -1561,9 +1561,9 @@ Search::seedClkArrival(const Pin *pin, pulse_clk_sense, insertion, latency, uncertainties, path_ap, nullptr); // Only false_paths -from apply to clock tree pins. - ExceptionStateSet *states = nullptr; + ExceptionStates states; sdc_->exceptionFromClkStates(pin,rf,clk,rf,min_max,states); - Tag *tag = findTag(rf, path_ap, clk_info, true, nullptr, false, states, true); + Tag *tag = findTag(rf, path_ap, clk_info, true, nullptr, false, states); Arrival arrival(clk_edge->time() + insertion); tag_bldr->setArrival(tag, arrival, nullptr); } @@ -1595,13 +1595,13 @@ Search::clkDataTag(const Pin *pin, const MinMax *min_max, const PathAnalysisPt *path_ap) { - ExceptionStateSet *states = nullptr; + ExceptionStates states; if (sdc_->exceptionFromStates(pin, rf, clk, rf, min_max, states)) { bool is_propagated = (clk->isPropagated() || sdc_->isPropagatedClock(pin)); ClkInfo *clk_info = findClkInfo(clk_edge, pin, is_propagated, insertion, path_ap); - return findTag(rf, path_ap, clk_info, false, nullptr, false, states, true); + return findTag(rf, path_ap, clk_info, false, nullptr, false, states); } else return nullptr; @@ -1954,14 +1954,14 @@ Search::inputDelayTag(const Pin *pin, clk_uncertainties = clk->uncertainties(); } - ExceptionStateSet *states = nullptr; + ExceptionStates states; Tag *tag = nullptr; if (sdc_->exceptionFromStates(pin,rf,clk,clk_rf,min_max,states)) { ClkInfo *clk_info = findClkInfo(clk_edge, clk_pin, is_propagated, nullptr, false, nullptr, clk_insertion, clk_latency, clk_uncertainties, path_ap, nullptr); tag = findTag(rf, path_ap, clk_info, false, input_delay, is_segment_start, - states, true); + states); } if (tag) { @@ -2321,12 +2321,12 @@ Search::fromUnclkedInputTag(const Pin *pin, bool is_segment_start, bool require_exception) { - ExceptionStateSet *states = nullptr; + ExceptionStates states; if (sdc_->exceptionFromStates(pin, rf, nullptr, nullptr, min_max, states) && (!require_exception || states)) { ClkInfo *clk_info = findClkInfo(nullptr, nullptr, false, 0.0, path_ap); return findTag(rf, path_ap, clk_info, false, nullptr, - is_segment_start, states, true); + is_segment_start, states); } return nullptr; } @@ -2342,12 +2342,12 @@ Search::fromRegClkTag(const Pin *from_pin, const MinMax *min_max, const PathAnalysisPt *path_ap) { - ExceptionStateSet *states = nullptr; + ExceptionStates states; if (sdc_->exceptionFromStates(from_pin, from_rf, clk, clk_rf, min_max, states)) { // Hack for filter -from reg/Q. sdc_->filterRegQStates(to_pin, to_rf, min_max, states); - return findTag(to_rf, path_ap, clk_info, false, nullptr, false, states, true); + return findTag(to_rf, path_ap, clk_info, false, nullptr, false, states); } else return nullptr; @@ -2541,12 +2541,12 @@ Search::mutateTag(Tag *from_tag, const MinMax *min_max, const PathAnalysisPt *path_ap) { - ExceptionStateSet *new_states = nullptr; - ExceptionStateSet *from_states = from_tag->states(); + ExceptionStates new_states; + ExceptionStateSet from_states = from_tag->states(); if (from_states) { // Check for state changes in from_tag (but postpone copying state set). bool state_change = false; - for (auto state : *from_states) { + for (auto state : from_states) { ExceptionPath *exception = state->exception(); // One edge may traverse multiple hierarchical thru pins. while (state->matchesNextThru(from_pin,to_pin,to_rf,min_max,network_)) { @@ -2581,13 +2581,11 @@ Search::mutateTag(Tag *from_tag, } // Get the set of -thru exceptions starting at to_pin/edge. - new_states = sdc_->exceptionThruStates(from_pin, to_pin, to_rf, min_max); + new_states.takeOver(sdc_->exceptionThruStates(from_pin, to_pin, to_rf, min_max)); if (new_states || state_change) { // Second pass to apply state changes and add updated existing // states to new states. - if (new_states == nullptr) - new_states = new ExceptionStateSet(); - for (auto state : *from_states) { + for (auto state : from_states) { ExceptionPath *exception = state->exception(); // One edge may traverse multiple hierarchical thru pins. while (state->matchesNextThru(from_pin,to_pin,to_rf,min_max,network_)) @@ -2603,7 +2601,6 @@ Search::mutateTag(Tag *from_tag, // to_pin/edge completes a loop path. || (exception->isLoop() && state->isComplete())) { - delete new_states; return nullptr; } @@ -2613,18 +2610,18 @@ Search::mutateTag(Tag *from_tag, // Kill loop tags at register clock pins. || (to_is_reg_clk && exception->isLoop()))) - new_states->insert(state); + new_states.insert(state); } } } else // Get the set of -thru exceptions starting at to_pin/edge. - new_states = sdc_->exceptionThruStates(from_pin, to_pin, to_rf, min_max); + new_states.takeOver(sdc_->exceptionThruStates(from_pin, to_pin, to_rf, min_max)); if (new_states) return findTag(to_rf, path_ap, to_clk_info, to_is_clk, from_tag->inputDelay(), to_is_segment_start, - new_states, true); + new_states); else { // No state change. if (to_clk_info == from_clk_info @@ -2636,7 +2633,7 @@ Search::mutateTag(Tag *from_tag, else return findTag(to_rf, path_ap, to_clk_info, to_is_clk, to_input_delay, to_is_segment_start, - from_states, false); + from_states); } } @@ -2873,16 +2870,13 @@ Search::findTag(const RiseFall *rf, bool is_clk, InputDelay *input_delay, bool is_segment_start, - ExceptionStateSet *states, - bool own_states) + const ExceptionStateSet& states) { Tag probe(0, rf->index(), path_ap->index(), clk_info, is_clk, input_delay, - is_segment_start, states, false, this); + is_segment_start, states, this); LockGuard lock(tag_lock_); Tag *tag = tag_set_->findKey(&probe); if (tag == nullptr) { - ExceptionStateSet *new_states = !own_states && states - ? new ExceptionStateSet(*states) : states; TagIndex tag_index; if (tag_free_indices_.empty()) tag_index = tag_next_++; @@ -2892,8 +2886,7 @@ Search::findTag(const RiseFall *rf, } tag = new Tag(tag_index, rf->index(), path_ap->index(), clk_info, is_clk, input_delay, is_segment_start, - new_states, true, this); - own_states = false; + states, this); // Make sure tag can be indexed in tags_ before it is visible to // other threads via tag_set_. tags_[tag_index] = tag; @@ -2916,8 +2909,6 @@ Search::findTag(const RiseFall *rf, if (tag_next_ == tag_index_max) report_->critical(1511, "max tag index exceeded"); } - if (own_states) - delete states; return tag; } @@ -3613,9 +3604,9 @@ Search::matchesFilter(Path *path, // -from pins|inst // -thru // Path has to be tagged by traversing the filter exception points. - ExceptionStateSet *states = path->tag(this)->states(); + const ExceptionStateSet& states = path->tag(this)->states(); if (states) { - for (auto state : *states) { + for (auto state : states) { if (state->exception() == filter_ && state->nextThru() == nullptr && matchesFilterTo(path, to_clk_edge)) @@ -3674,9 +3665,9 @@ Search::exceptionTo(ExceptionPathType type, // Find the highest priority exception carried by the path's tag. int hi_priority = -1; ExceptionPath *hi_priority_exception = nullptr; - const ExceptionStateSet *states = path->tag(this)->states(); + const ExceptionStateSet& states = path->tag(this)->states(); if (states) { - for (auto state : *states) { + for (auto state : states) { ExceptionPath *exception = state->exception(); int priority = exception->priority(min_max); if ((type == ExceptionPathType::any diff --git a/search/Tag.cc b/search/Tag.cc index 9cb73b5f..653bf141 100644 --- a/search/Tag.cc +++ b/search/Tag.cc @@ -34,8 +34,8 @@ static int tagStateCmp(const Tag *tag1, const Tag *tag2); static bool -tagStateEqual(ExceptionStateSet *states1, - ExceptionStateSet *states2); +tagStateEqual(const ExceptionStateSet &states1, + const ExceptionStateSet &states2); static bool tagStateEqualCrpr(const Tag *tag1, const Tag *tag2); @@ -47,8 +47,7 @@ Tag::Tag(TagIndex index, bool is_clk, InputDelay *input_delay, bool is_segment_start, - ExceptionStateSet *states, - bool own_states, + const ExceptionStateSet& states, const StaState *sta) : clk_info_(clk_info), input_delay_(input_delay), @@ -58,14 +57,13 @@ Tag::Tag(TagIndex index, is_filter_(false), is_loop_(false), is_segment_start_(is_segment_start), - own_states_(own_states), rf_index_(rf_index), path_ap_index_(path_ap_index) { findHash(); if (states_) { FilterPath *filter = sta->search()->filter(); - for (ExceptionState *state : *states_) { + for (ExceptionState *state : states_) { ExceptionPath *exception = state->exception(); if (exception->isLoop()) is_loop_ = true; @@ -77,8 +75,6 @@ Tag::Tag(TagIndex index, Tag::~Tag() { - if (own_states_ && states_) - delete states_; } const char * @@ -155,7 +151,7 @@ Tag::asString(bool report_index, result += " segment_start"; if (states_) { - for (ExceptionState *state : *states_) { + for (ExceptionState *state : states_) { ExceptionPath *exception = state->exception(); result += " "; result += exception->asString(network); @@ -190,7 +186,7 @@ Tag::pathAnalysisPt(const StaState *sta) const } void -Tag::setStates(ExceptionStateSet *states) +Tag::setStates(const ExceptionStateSet& states) { states_ = states; } @@ -225,7 +221,7 @@ Tag::genClkSrcPathClk(const StaState *sta) const if (clk_info_->isGenClkSrcPath() && states_) { FilterPath *filter = sta->search()->filter(); - for (ExceptionState *state : *states_) { + for (ExceptionState *state : states_) { ExceptionPath *except = state->exception(); if (except->isFilter() && except != filter) { @@ -254,8 +250,7 @@ Tag::findHash() hashIncr(hash_, is_clk_); hashIncr(hash_, is_segment_start_); if (states_) { - for (ExceptionState *state : *states_) - hashIncr(hash_, state->hash()); + hashIncr(hash_, states_.hash()); } match_hash_ = hash_; @@ -536,39 +531,9 @@ static int tagStateCmp(const Tag *tag1, const Tag *tag2) { - ExceptionStateSet *states1 = tag1->states(); - ExceptionStateSet *states2 = tag2->states(); - bool states_null1 = (states1 == nullptr || states1->empty()); - bool states_null2 = (states2 == nullptr || states2->empty()); - if (states_null1 - && states_null2) - return 0; - if (states_null1 - && !states_null2) - return -1; - if (!states_null1 - && states_null2) - return 1; - - size_t state_size1 = states1->size(); - size_t state_size2 = states2->size(); - if (state_size1 < state_size2) - return -1; - if (state_size1 > state_size2) - return 1; - - ExceptionStateSet::Iterator state_iter1(states1); - ExceptionStateSet::Iterator state_iter2(states2); - while (state_iter1.hasNext() - && state_iter2.hasNext()) { - ExceptionState *state1 = state_iter1.next(); - ExceptionState *state2 = state_iter2.next(); - if (state1 < state2) - return -1; - if (state1 > state2) - return 1; - } - return 0; + const ExceptionStateSet &states1 = tag1->states(); + const ExceptionStateSet &states2 = tag2->states(); + return states1.cmp(states2); } bool @@ -579,32 +544,10 @@ tagStateEqual(const Tag *tag1, } static bool -tagStateEqual(ExceptionStateSet *states1, - ExceptionStateSet *states2) -{ - bool states_null1 = (states1 == nullptr || states1->empty()); - bool states_null2 = (states2 == nullptr || states2->empty()); - if (states_null1 && states_null2) - return true; - else if (states_null1 != states_null2) - return false; - - size_t state_size1 = states1->size(); - size_t state_size2 = states2->size(); - if (state_size1 == state_size2) { - ExceptionStateSet::Iterator state_iter1(states1); - ExceptionStateSet::Iterator state_iter2(states2); - while (state_iter1.hasNext() - && state_iter2.hasNext()) { - ExceptionState *state1 = state_iter1.next(); - ExceptionState *state2 = state_iter2.next(); - if (state1 != state2) - return false; - } - return true; - } - else - return false; +tagStateEqual(const ExceptionStateSet& states1, + const ExceptionStateSet& states2) +{ + return states1 == states2; } // Match loop exception states only for crpr min/max paths. @@ -612,10 +555,12 @@ static bool tagStateEqualCrpr(const Tag *tag1, const Tag *tag2) { - ExceptionStateSet *states1 = tag1->states(); - ExceptionStateSet *states2 = tag2->states(); - ExceptionStateSet::Iterator state_iter1(states1); - ExceptionStateSet::Iterator state_iter2(states2); + const ExceptionStateSet& states1 = tag1->states(); + const ExceptionStateSet& states2 = tag2->states(); + if (!states1.hasLoopPath() && !states2.hasLoopPath()) return true; + if (states1.hasLoopPath() != states2.hasLoopPath()) return false; + ExceptionStateSet::ConstIterator state_iter1(states1); + ExceptionStateSet::ConstIterator state_iter2(states2); ExceptionState *state1, *state2; do { state1 = nullptr; diff --git a/search/Tag.hh b/search/Tag.hh index 55a27103..65cd6de8 100644 --- a/search/Tag.hh +++ b/search/Tag.hh @@ -50,8 +50,7 @@ public: bool is_clk, InputDelay *input_delay, bool is_segment_start, - ExceptionStateSet *states, - bool own_states, + const ExceptionStateSet& states, const StaState *sta); ~Tag(); const char *asString(const StaState *sta) const; @@ -68,8 +67,8 @@ public: PathAnalysisPt *pathAnalysisPt(const StaState *sta) const; PathAPIndex pathAPIndex() const { return path_ap_index_; } TagIndex index() const { return index_; } - ExceptionStateSet *states() const { return states_; } - void setStates(ExceptionStateSet *states); + const ExceptionStateSet& states() const { return states_; } + void setStates(const ExceptionStateSet& states); bool isGenClkSrcPath() const; const Clock *genClkSrcPathClk(const StaState *sta) const; // Input delay at search startpoint (not propagated). @@ -86,7 +85,7 @@ protected: private: ClkInfo *clk_info_; InputDelay *input_delay_; - ExceptionStateSet *states_; + ExceptionStateSet states_; size_t hash_; size_t match_hash_; TagIndex index_;