From cba0cf5cc43f5ba484bfe8e80f137a6d71dff56e Mon Sep 17 00:00:00 2001 From: James Cherry Date: Wed, 23 Apr 2025 11:38:44 -0700 Subject: [PATCH] path enum rm duplicate paths commit 0e13dae22d52d61b0d8d91b1a499d9dea9d23a9b Author: James Cherry Date: Wed Apr 23 11:18:50 2025 -0700 path enum Signed-off-by: James Cherry commit 8871e3653178e84aec4142819c9bac0556f52e29 Author: James Cherry Date: Tue Apr 22 16:30:35 2025 -0700 path enum w/crpr rm duplicate paths Signed-off-by: James Cherry commit 4da0d520762cb8bcc858398bceea62169ac9ad8a Author: James Cherry Date: Tue Apr 22 16:26:52 2025 -0700 TimingArc::to_string Signed-off-by: James Cherry commit d2e6f218f58bf67dfd6f8d2c48a24f92ed32b849 Author: James Cherry Date: Fri Apr 18 18:44:31 2025 -0700 comment Signed-off-by: James Cherry commit 7c673dfdfc6e18c154a1a9011b59a6406f2439f4 Author: James Cherry Date: Fri Apr 18 16:52:36 2025 -0700 path enum debug Signed-off-by: James Cherry Signed-off-by: James Cherry --- include/sta/TimingArc.hh | 1 + include/sta/Variables.hh | 3 +- liberty/TimingArc.cc | 13 +++++++ search/PathEnum.cc | 74 ++++++++++++++++++++-------------------- search/PathGroup.cc | 4 +-- search/Search.i | 15 ++++++++ 6 files changed, 70 insertions(+), 40 deletions(-) diff --git a/include/sta/TimingArc.hh b/include/sta/TimingArc.hh index 544f60f5..21e56c95 100644 --- a/include/sta/TimingArc.hh +++ b/include/sta/TimingArc.hh @@ -236,6 +236,7 @@ public: const Transition *to_rf, TimingModel *model); ~TimingArc(); + std::string to_string() const; LibertyPort *from() const { return set_->from(); } LibertyPort *to() const { return set_->to(); } const Transition *fromEdge() const { return from_rf_; } diff --git a/include/sta/Variables.hh b/include/sta/Variables.hh index 696347a1..1d60408e 100644 --- a/include/sta/Variables.hh +++ b/include/sta/Variables.hh @@ -33,9 +33,10 @@ class Variables { public: Variables(); - // TCL variable sta_propagate_gated_clock_enable. + // TCL variable sta_crpr_enabled. bool crprEnabled() const { return crpr_enabled_; } void setCrprEnabled(bool enabled); + // TCL variable sta_crpr_mode. CrprMode crprMode() const { return crpr_mode_; } void setCrprMode(CrprMode mode); // Propagate gated clock enable arrivals. diff --git a/liberty/TimingArc.cc b/liberty/TimingArc.cc index 1e7fd408..56af7c51 100644 --- a/liberty/TimingArc.cc +++ b/liberty/TimingArc.cc @@ -555,6 +555,19 @@ TimingArc::~TimingArc() delete scaled_models_; } +string +TimingArc::to_string() const +{ + string str = set_->from()->name(); + str += " "; + str += from_rf_->to_string(); + str += " -> "; + str += set_->to()->name(); + str += " "; + str += to_rf_->to_string(); + return str; +} + GateTimingModel * TimingArc::gateModel(const DcalcAnalysisPt *dcalc_ap) const { diff --git a/search/PathEnum.cc b/search/PathEnum.cc index dcf970e9..3b52c191 100644 --- a/search/PathEnum.cc +++ b/search/PathEnum.cc @@ -40,8 +40,6 @@ namespace sta { -//////////////////////////////////////////////////////////////// - // A diversion is an alternate path formed by changing the previous // path/arc of before_div to after_div/div_arc in path. // @@ -178,16 +176,17 @@ PathEnum::findNext() div_queue_.pop(); PathEnd *path_end = div->pathEnd(); Vertex *vertex = path_end->vertex(this); + path_counts_[vertex]++; if (debug_->check("path_enum", 2)) { Path *path = path_end->path(); - report_->reportLine("path_enum: next path %s delay %s slack %s", + report_->reportLine("path_enum: next path %zu %s delay %s slack %s", + path_counts_[vertex], path->to_string(this).c_str(), delayAsString(path_end->dataArrivalTime(this), this), delayAsString(path_end->slack(this), this)); reportDiversionPath(div); } - path_counts_[vertex]++; if (path_counts_[vertex] <= endpoint_path_count_) { // Add diversions for all arcs converging on the path up to the // diversion. @@ -213,14 +212,14 @@ PathEnum::reportDiversionPath(Diversion *div) { PathEnd *path_end = div->pathEnd(); Path *path = path_end->path(); - Path *p = path->prevPath(); + Path *p = path_end->path(); Path *after_div = div->divPath(); while (p) { report_->reportLine("path_enum: %s %s%s", p->to_string(this).c_str(), delayAsString(p->arrival(), this), - Path::equal(p, after_div, this) ? " <-diversion" : ""); - if (network_->isLatchData(p->pin(this))) + Path::equal(p, after_div, this) ? " <-after diversion" : ""); + if (p != path && network_->isLatchData(p->pin(this))) break; p = p->prevPath(); } @@ -228,6 +227,8 @@ PathEnum::reportDiversionPath(Diversion *div) //////////////////////////////////////////////////////////////// +typedef std::set> VisitedFanins; + class PathEnumFaninVisitor : public PathVisitor { public: @@ -271,14 +272,13 @@ private: Slack path_end_slack_; Path *before_div_; bool unique_pins_; - int before_div_rf_index_; Tag *before_div_tag_; - PathAPIndex before_div_ap_index_; Arrival before_div_arrival_; TimingArc *prev_arc_; Vertex *prev_vertex_; PathEnum *path_enum_; bool crpr_active_; + VisitedFanins visited_fanins_; }; PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end, @@ -290,9 +290,7 @@ PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end, path_end_slack_(path_end->slack(this)), before_div_(before_div), unique_pins_(unique_pins), - before_div_rf_index_(before_div_->rfIndex(this)), before_div_tag_(before_div_->tag(this)), - before_div_ap_index_(before_div_->pathAnalysisPtIndex(this)), before_div_arrival_(before_div_->arrival()), path_enum_(path_enum), crpr_active_(crprActive()) @@ -305,12 +303,11 @@ PathEnumFaninVisitor::visitFaninPathsThru(Path *before_div, TimingArc *prev_arc) { before_div_ = before_div; - before_div_rf_index_ = before_div_->rfIndex(this); before_div_tag_ = before_div_->tag(this); - before_div_ap_index_ = before_div_->pathAnalysisPtIndex(this); before_div_arrival_ = before_div_->arrival(); prev_arc_ = prev_arc; prev_vertex_ = prev_vertex; + visited_fanins_.clear(); visitFaninPaths(before_div_->vertex(this)); } @@ -338,32 +335,38 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *, const MinMax *min_max, const PathAnalysisPt *path_ap) { - debugPrint(debug_, "path_enum", 3, "visit fanin %s -> %s %s %s", - from_path->to_string(this).c_str(), - to_vertex->to_string(this).c_str(), - to_rf->to_string().c_str(), - delayAsString(search_->deratedDelay(from_vertex, arc, edge, - false,path_ap), this)); // These paths fanin to before_div_ so we know to_vertex matches. - if (to_rf->index() == before_div_rf_index_ - && path_ap->index() == before_div_ap_index_ + if ((!unique_pins_ || from_vertex != prev_vertex_) && arc != prev_arc_ - && (!unique_pins_ || from_vertex != prev_vertex_) && tagMatchNoCrpr(to_tag, before_div_tag_)) { + debugPrint(debug_, "path_enum", 3, "visit fanin %s -> %s %s %s", + from_path->to_string(this).c_str(), + to_vertex->to_string(this).c_str(), + to_rf->to_string().c_str(), + delayAsString(search_->deratedDelay(from_vertex, arc, edge, + false,path_ap), this)); if (crpr_active_) { - PathEnd *div_end; - Path *after_div_copy; - // Make the diverted path end to check slack with from_path crpr. - makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy); - if (div_end) { - // Only enumerate paths with greater slack. - if (delayGreaterEqual(div_end->slack(this), path_end_slack_, this)) { - reportDiversion(edge, arc, from_path); - path_enum_->makeDiversion(div_end, after_div_copy); + // Ingore paths that only differ by crpr from same vertex/edge. + if (visited_fanins_.find({from_vertex, arc}) == visited_fanins_.end()) { + PathEnd *div_end; + Path *after_div_copy; + // Make the diverted path end to check slack with from_path crpr. + makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy); + if (div_end) { + // Only enumerate paths with greater slack. + if (div_end->slack(this) >= (path_end_slack_ * (1.0-.001))) { + reportDiversion(edge, arc, from_path); + path_enum_->makeDiversion(div_end, after_div_copy); + visited_fanins_.emplace(from_vertex, arc); + } + else + delete div_end; } - else - delete div_end; } + else + debugPrint(debug_, "path_enum", 3, " pruned %s %s", + edge->to_string(this).c_str(), + arc->to_string().c_str()); } // Only enumerate slower/faster paths. else if (delayLessEqual(to_arrival, before_div_arrival_, min_max, this)) { @@ -468,11 +471,8 @@ PathEnum::pruneDiversionQueue() } // Add the top diversions back. - DiversionSeq::Iterator div_iter(divs); - while (div_iter.hasNext()) { - Diversion *div = div_iter.next(); + for (Diversion *div : divs) div_queue_.push(div); - } } Arrival diff --git a/search/PathGroup.cc b/search/PathGroup.cc index b2661fa7..2a0f7961 100644 --- a/search/PathGroup.cc +++ b/search/PathGroup.cc @@ -733,7 +733,7 @@ MakePathEndsAll::vertexEnd(Vertex *) // Only save the worst path end for each crpr tag. // PathEnum will peel the others. if (!unique_ends.hasKey(path_end)) { - debugPrint(debug, "path_enum", 5, "insert %s %s %s %d", + debugPrint(debug, "path_group", 2, "insert %s %s %s %d", path_end->vertex(sta_)->to_string(sta_).c_str(), path_end->typeName(), path_end->transition(sta_)->to_string().c_str(), @@ -748,7 +748,7 @@ MakePathEndsAll::vertexEnd(Vertex *) } } else - debugPrint(debug, "path_enum", 5, "prune %s %s %s %d", + debugPrint(debug, "path_group", 3, "prune %s %s %s %d", path_end->vertex(sta_)->to_string(sta_).c_str(), path_end->typeName(), path_end->transition(sta_)->to_string().c_str(), diff --git a/search/Search.i b/search/Search.i index 1ed6da1c..aaea04a4 100644 --- a/search/Search.i +++ b/search/Search.i @@ -31,6 +31,7 @@ #include "Search.hh" #include "search/Levelize.hh" #include "search/ReportPath.hh" +#include "PathExpanded.hh" #include "Sta.hh" using namespace sta; @@ -1248,6 +1249,7 @@ bool is_data_check() { return self->isDataCheck(); } bool is_output_delay() { return self->isOutputDelay(); } bool is_path_delay() { return self->isPathDelay(); } bool is_gated_clock() { return self->isGatedClock(); } +Pin *pin() { return self->vertex(Sta::sta())->pin(); } Vertex *vertex() { return self->vertex(Sta::sta()); } Path *path() { return self->path(); } RiseFall *end_transition() @@ -1313,6 +1315,12 @@ pin() return self->pin(sta); } +const RiseFall * +edge() +{ + return self->transition(Sta::sta()); +} + string tag() { @@ -1334,6 +1342,13 @@ pins() return pins; } +const Path * +start_path() +{ + PathExpanded expanded(self, Sta::sta()); + return expanded.startPath(); +} + } %extend VertexPathIterator {