diff --git a/include/sta/Search.hh b/include/sta/Search.hh index 2c1f2504..5b3d6772 100644 --- a/include/sta/Search.hh +++ b/include/sta/Search.hh @@ -238,25 +238,26 @@ public: const RiseFall *to_rf, const MinMax *min_max, const PathAnalysisPt *path_ap); - virtual Tag *thruTag(Tag *from_tag, - Edge *edge, - const RiseFall *to_rf, - const MinMax *min_max, - const PathAnalysisPt *path_ap); - virtual Tag *thruClkTag(PathVertex *from_path, - Tag *from_tag, - bool to_propagates_clk, - Edge *edge, - const RiseFall *to_rf, - const MinMax *min_max, - const PathAnalysisPt *path_ap); + Tag *thruTag(Tag *from_tag, + Edge *edge, + const RiseFall *to_rf, + const MinMax *min_max, + const PathAnalysisPt *path_ap); + Tag *thruClkTag(PathVertex *from_path, + Tag *from_tag, + bool to_propagates_clk, + Edge *edge, + const RiseFall *to_rf, + const MinMax *min_max, + const PathAnalysisPt *path_ap); ClkInfo *thruClkInfo(PathVertex *from_path, - ClkInfo *from_tag_clk, - Edge *edge, - Vertex *to_vertex, - const Pin *to_pin, - const MinMax *min_max, - const PathAnalysisPt *path_ap); + ClkInfo *from_clk_info, + bool from_is_clk, + Edge *edge, + const Pin *to_pin, + bool to_is_clk, + const MinMax *min_max, + const PathAnalysisPt *path_ap); ClkInfo *clkInfoWithCrprClkPath(ClkInfo *from_clk_info, PathVertex *from_path, const PathAnalysisPt *path_ap); diff --git a/search/ClkInfo.hh b/search/ClkInfo.hh index 2e4c198e..3989f368 100644 --- a/search/ClkInfo.hh +++ b/search/ClkInfo.hh @@ -54,8 +54,8 @@ public: const Arrival &insertion() const { return insertion_; } ClockUncertainties *uncertainties() const { return uncertainties_; } PathAPIndex pathAPIndex() const { return path_ap_index_; } - // Clock path for the last driver in the clock network used for - // crpr resolution. + // Clock path used for crpr resolution. + // Null for clocks because the path cannot point to itself. PathVertexRep &crprClkPath() { return crpr_clk_path_; } const PathVertexRep &crprClkPath() const { return crpr_clk_path_; } VertexId crprClkVertexId() const; diff --git a/search/Crpr.cc b/search/Crpr.cc index af1b14e8..92bae4b9 100644 --- a/search/Crpr.cc +++ b/search/Crpr.cc @@ -46,20 +46,20 @@ CheckCrpr::CheckCrpr(StaState *sta) : { } -PathVertex * +void CheckCrpr::clkPathPrev(const PathVertex *path, - PathVertex &tmp) + PathVertex &prev) { Vertex *vertex = path->vertex(this); int arrival_index; bool exists; path->arrivalIndex(arrival_index, exists); - tmp = clkPathPrev(vertex, arrival_index); - if (tmp.isNull()) - return nullptr; + PathVertexRep *prevs = graph_->prevPaths(vertex); + if (prevs) + prev.init(prevs[arrival_index], this); else - return &tmp; + criticalError(2200, "missing prev paths"); } PathVertex @@ -70,7 +70,7 @@ CheckCrpr::clkPathPrev(Vertex *vertex, if (prevs) return PathVertex(prevs[arrival_index], this); else { - criticalError(248, "missing prev paths"); + criticalError(2201, "missing prev paths"); return PathVertex(); } } @@ -152,13 +152,22 @@ CheckCrpr::checkCrpr1(const Path *src_path, { crpr = 0.0; crpr_pin = nullptr; - ClkInfo *src_clk_info = src_path->tag(this)->clkInfo(); + const Tag *src_tag = src_path->tag(this); + ClkInfo *src_clk_info = src_tag->clkInfo(); ClkInfo *tgt_clk_info = tgt_clk_path->tag(this)->clkInfo(); const Clock *src_clk = src_clk_info->clock(); const Clock *tgt_clk = tgt_clk_info->clock(); - const PathVertex src_clk_path1(src_clk_info->crprClkPath(), this); - const PathVertex *src_clk_path = - src_clk_path1.isNull() ? nullptr : &src_clk_path1; + PathVertex src_clk_path1; + PathVertexRep &src_crpr_clk_path = src_clk_info->crprClkPath(); + const PathVertex *src_clk_path = nullptr; + if (src_tag->isClock()) { + src_clk_path1.init(src_path->vertex(this), src_path->tag(this), this); + src_clk_path = &src_clk_path1; + } + else if (!src_crpr_clk_path.isNull()) { + src_clk_path1.init(src_crpr_clk_path, this); + src_clk_path = &src_clk_path1; + } const MinMax *src_clk_min_max = src_clk_path ? src_clk_path->minMax(this) : src_path->minMax(this); if (src_clk && tgt_clk @@ -242,20 +251,30 @@ CheckCrpr::findCrpr(const PathVertex *src_clk_path, } const PathVertex *src_clk_path2 = src_clk_path1; const PathVertex *tgt_clk_path2 = tgt_clk_path1; - PathVertex tmp1, tmp2; + PathVertex src_prev, tgt_prev; // src_clk_path and tgt_clk_path are now in the same (gen)clk src path. // Use the vertex levels to back up the deeper path to see if they // overlap. - while (src_clk_path2 && tgt_clk_path2 - && src_clk_path2->pin(this) != tgt_clk_path2->pin(this)) { - Level src_level = src_clk_path2->vertex(this)->level(); - Level tgt_level = tgt_clk_path2->vertex(this)->level(); - if (src_level >= tgt_level) - src_clk_path2 = clkPathPrev(src_clk_path2, tmp1); - if (tgt_level >= src_level) - tgt_clk_path2 = clkPathPrev(tgt_clk_path2, tmp2); + int src_level = src_clk_path2->vertex(this)->level(); + int tgt_level = tgt_clk_path2->vertex(this)->level(); + while (src_clk_path2->pin(this) != tgt_clk_path2->pin(this)) { + int level_diff = src_level - tgt_level; + if (level_diff >= 0) { + clkPathPrev(src_clk_path2, src_prev); + if (src_prev.isNull()) + break; + src_clk_path2 = &src_prev; + src_level = src_clk_path2->vertex(this)->level(); + } + if (level_diff <= 0) { + clkPathPrev(tgt_clk_path2, tgt_prev); + if (tgt_prev.isNull()) + break; + tgt_clk_path2 = &tgt_prev; + tgt_level = tgt_clk_path2->vertex(this)->level(); + } } - if (src_clk_path2 && tgt_clk_path2 + if (!src_clk_path2->isNull() && !tgt_clk_path2->isNull() && (src_clk_path2->transition(this) == tgt_clk_path2->transition(this) || same_pin)) { debugPrint(debug_, "crpr", 2, "crpr pin %s", diff --git a/search/Crpr.hh b/search/Crpr.hh index 62999a33..114a362c 100644 --- a/search/Crpr.hh +++ b/search/Crpr.hh @@ -56,8 +56,8 @@ public: int arrival_index); private: - PathVertex *clkPathPrev(const PathVertex *path, - PathVertex &tmp); + void clkPathPrev(const PathVertex *path, + PathVertex &prev); Arrival otherMinMaxArrival(const PathVertex *path); void checkCrpr1(const Path *src_path, const PathVertex *tgt_clk_path, diff --git a/search/Search.cc b/search/Search.cc index 0a22323e..9cc3d1df 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -2417,8 +2417,9 @@ Search::thruClkTag(PathVertex *from_path, && to_propagates_clk && (role->isWire() || role == TimingRole::combinational())); - ClkInfo *to_clk_info = thruClkInfo(from_path, from_clk_info, - edge, to_vertex, to_pin, min_max, path_ap); + ClkInfo *to_clk_info = thruClkInfo(from_path, from_clk_info, from_is_clk, + edge, to_pin, to_is_clk, + min_max, path_ap); Tag *to_tag = mutateTag(from_tag,from_pin,from_rf,from_is_clk,from_clk_info, to_pin, to_rf, to_is_clk, to_is_reg_clk, false, to_clk_info, nullptr, min_max, path_ap); @@ -2429,9 +2430,10 @@ Search::thruClkTag(PathVertex *from_path, ClkInfo * Search::thruClkInfo(PathVertex *from_path, ClkInfo *from_clk_info, + bool from_is_clk, Edge *edge, - Vertex *to_vertex, const Pin *to_pin, + bool to_is_clk, const MinMax *min_max, const PathAnalysisPt *path_ap) { @@ -2462,7 +2464,7 @@ Search::thruClkInfo(PathVertex *from_path, PathVertex *to_crpr_clk_path = nullptr; if (sdc_->crprActive() - && to_vertex->isRegClk()) { + && from_is_clk && !to_is_clk) { to_crpr_clk_path = from_path; changed = true; }