path enum rm duplicate paths

commit 0e13dae22d52d61b0d8d91b1a499d9dea9d23a9b
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Apr 23 11:18:50 2025 -0700

    path enum

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 8871e3653178e84aec4142819c9bac0556f52e29
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Apr 22 16:30:35 2025 -0700

    path enum w/crpr rm duplicate paths

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 4da0d520762cb8bcc858398bceea62169ac9ad8a
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Apr 22 16:26:52 2025 -0700

    TimingArc::to_string

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit d2e6f218f58bf67dfd6f8d2c48a24f92ed32b849
Author: James Cherry <cherry@parallaxsw.com>
Date:   Fri Apr 18 18:44:31 2025 -0700

    comment

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 7c673dfdfc6e18c154a1a9011b59a6406f2439f4
Author: James Cherry <cherry@parallaxsw.com>
Date:   Fri Apr 18 16:52:36 2025 -0700

    path enum debug

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2025-04-23 11:38:44 -07:00
parent 400c473fe3
commit cba0cf5cc4
6 changed files with 70 additions and 40 deletions

View File

@ -236,6 +236,7 @@ public:
const Transition *to_rf, const Transition *to_rf,
TimingModel *model); TimingModel *model);
~TimingArc(); ~TimingArc();
std::string to_string() const;
LibertyPort *from() const { return set_->from(); } LibertyPort *from() const { return set_->from(); }
LibertyPort *to() const { return set_->to(); } LibertyPort *to() const { return set_->to(); }
const Transition *fromEdge() const { return from_rf_; } const Transition *fromEdge() const { return from_rf_; }

View File

@ -33,9 +33,10 @@ class Variables
{ {
public: public:
Variables(); Variables();
// TCL variable sta_propagate_gated_clock_enable. // TCL variable sta_crpr_enabled.
bool crprEnabled() const { return crpr_enabled_; } bool crprEnabled() const { return crpr_enabled_; }
void setCrprEnabled(bool enabled); void setCrprEnabled(bool enabled);
// TCL variable sta_crpr_mode.
CrprMode crprMode() const { return crpr_mode_; } CrprMode crprMode() const { return crpr_mode_; }
void setCrprMode(CrprMode mode); void setCrprMode(CrprMode mode);
// Propagate gated clock enable arrivals. // Propagate gated clock enable arrivals.

View File

@ -555,6 +555,19 @@ TimingArc::~TimingArc()
delete scaled_models_; 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 * GateTimingModel *
TimingArc::gateModel(const DcalcAnalysisPt *dcalc_ap) const TimingArc::gateModel(const DcalcAnalysisPt *dcalc_ap) const
{ {

View File

@ -40,8 +40,6 @@
namespace sta { namespace sta {
////////////////////////////////////////////////////////////////
// A diversion is an alternate path formed by changing the previous // A diversion is an alternate path formed by changing the previous
// path/arc of before_div to after_div/div_arc in path. // path/arc of before_div to after_div/div_arc in path.
// //
@ -178,16 +176,17 @@ PathEnum::findNext()
div_queue_.pop(); div_queue_.pop();
PathEnd *path_end = div->pathEnd(); PathEnd *path_end = div->pathEnd();
Vertex *vertex = path_end->vertex(this); Vertex *vertex = path_end->vertex(this);
path_counts_[vertex]++;
if (debug_->check("path_enum", 2)) { if (debug_->check("path_enum", 2)) {
Path *path = path_end->path(); 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(), path->to_string(this).c_str(),
delayAsString(path_end->dataArrivalTime(this), this), delayAsString(path_end->dataArrivalTime(this), this),
delayAsString(path_end->slack(this), this)); delayAsString(path_end->slack(this), this));
reportDiversionPath(div); reportDiversionPath(div);
} }
path_counts_[vertex]++;
if (path_counts_[vertex] <= endpoint_path_count_) { if (path_counts_[vertex] <= endpoint_path_count_) {
// Add diversions for all arcs converging on the path up to the // Add diversions for all arcs converging on the path up to the
// diversion. // diversion.
@ -213,14 +212,14 @@ PathEnum::reportDiversionPath(Diversion *div)
{ {
PathEnd *path_end = div->pathEnd(); PathEnd *path_end = div->pathEnd();
Path *path = path_end->path(); Path *path = path_end->path();
Path *p = path->prevPath(); Path *p = path_end->path();
Path *after_div = div->divPath(); Path *after_div = div->divPath();
while (p) { while (p) {
report_->reportLine("path_enum: %s %s%s", report_->reportLine("path_enum: %s %s%s",
p->to_string(this).c_str(), p->to_string(this).c_str(),
delayAsString(p->arrival(), this), delayAsString(p->arrival(), this),
Path::equal(p, after_div, this) ? " <-diversion" : ""); Path::equal(p, after_div, this) ? " <-after diversion" : "");
if (network_->isLatchData(p->pin(this))) if (p != path && network_->isLatchData(p->pin(this)))
break; break;
p = p->prevPath(); p = p->prevPath();
} }
@ -228,6 +227,8 @@ PathEnum::reportDiversionPath(Diversion *div)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
typedef std::set<std::pair<const Vertex*, const TimingArc*>> VisitedFanins;
class PathEnumFaninVisitor : public PathVisitor class PathEnumFaninVisitor : public PathVisitor
{ {
public: public:
@ -271,14 +272,13 @@ private:
Slack path_end_slack_; Slack path_end_slack_;
Path *before_div_; Path *before_div_;
bool unique_pins_; bool unique_pins_;
int before_div_rf_index_;
Tag *before_div_tag_; Tag *before_div_tag_;
PathAPIndex before_div_ap_index_;
Arrival before_div_arrival_; Arrival before_div_arrival_;
TimingArc *prev_arc_; TimingArc *prev_arc_;
Vertex *prev_vertex_; Vertex *prev_vertex_;
PathEnum *path_enum_; PathEnum *path_enum_;
bool crpr_active_; bool crpr_active_;
VisitedFanins visited_fanins_;
}; };
PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end, PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end,
@ -290,9 +290,7 @@ PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end,
path_end_slack_(path_end->slack(this)), path_end_slack_(path_end->slack(this)),
before_div_(before_div), before_div_(before_div),
unique_pins_(unique_pins), unique_pins_(unique_pins),
before_div_rf_index_(before_div_->rfIndex(this)),
before_div_tag_(before_div_->tag(this)), before_div_tag_(before_div_->tag(this)),
before_div_ap_index_(before_div_->pathAnalysisPtIndex(this)),
before_div_arrival_(before_div_->arrival()), before_div_arrival_(before_div_->arrival()),
path_enum_(path_enum), path_enum_(path_enum),
crpr_active_(crprActive()) crpr_active_(crprActive())
@ -305,12 +303,11 @@ PathEnumFaninVisitor::visitFaninPathsThru(Path *before_div,
TimingArc *prev_arc) TimingArc *prev_arc)
{ {
before_div_ = before_div; before_div_ = before_div;
before_div_rf_index_ = before_div_->rfIndex(this);
before_div_tag_ = before_div_->tag(this); before_div_tag_ = before_div_->tag(this);
before_div_ap_index_ = before_div_->pathAnalysisPtIndex(this);
before_div_arrival_ = before_div_->arrival(); before_div_arrival_ = before_div_->arrival();
prev_arc_ = prev_arc; prev_arc_ = prev_arc;
prev_vertex_ = prev_vertex; prev_vertex_ = prev_vertex;
visited_fanins_.clear();
visitFaninPaths(before_div_->vertex(this)); visitFaninPaths(before_div_->vertex(this));
} }
@ -338,32 +335,38 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap) 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. // These paths fanin to before_div_ so we know to_vertex matches.
if (to_rf->index() == before_div_rf_index_ if ((!unique_pins_ || from_vertex != prev_vertex_)
&& path_ap->index() == before_div_ap_index_
&& arc != prev_arc_ && arc != prev_arc_
&& (!unique_pins_ || from_vertex != prev_vertex_)
&& tagMatchNoCrpr(to_tag, before_div_tag_)) { && 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_) { if (crpr_active_) {
PathEnd *div_end; // Ingore paths that only differ by crpr from same vertex/edge.
Path *after_div_copy; if (visited_fanins_.find({from_vertex, arc}) == visited_fanins_.end()) {
// Make the diverted path end to check slack with from_path crpr. PathEnd *div_end;
makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy); Path *after_div_copy;
if (div_end) { // Make the diverted path end to check slack with from_path crpr.
// Only enumerate paths with greater slack. makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy);
if (delayGreaterEqual(div_end->slack(this), path_end_slack_, this)) { if (div_end) {
reportDiversion(edge, arc, from_path); // Only enumerate paths with greater slack.
path_enum_->makeDiversion(div_end, after_div_copy); 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. // Only enumerate slower/faster paths.
else if (delayLessEqual(to_arrival, before_div_arrival_, min_max, this)) { else if (delayLessEqual(to_arrival, before_div_arrival_, min_max, this)) {
@ -468,11 +471,8 @@ PathEnum::pruneDiversionQueue()
} }
// Add the top diversions back. // Add the top diversions back.
DiversionSeq::Iterator div_iter(divs); for (Diversion *div : divs)
while (div_iter.hasNext()) {
Diversion *div = div_iter.next();
div_queue_.push(div); div_queue_.push(div);
}
} }
Arrival Arrival

View File

@ -733,7 +733,7 @@ MakePathEndsAll::vertexEnd(Vertex *)
// Only save the worst path end for each crpr tag. // Only save the worst path end for each crpr tag.
// PathEnum will peel the others. // PathEnum will peel the others.
if (!unique_ends.hasKey(path_end)) { 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->vertex(sta_)->to_string(sta_).c_str(),
path_end->typeName(), path_end->typeName(),
path_end->transition(sta_)->to_string().c_str(), path_end->transition(sta_)->to_string().c_str(),
@ -748,7 +748,7 @@ MakePathEndsAll::vertexEnd(Vertex *)
} }
} }
else 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->vertex(sta_)->to_string(sta_).c_str(),
path_end->typeName(), path_end->typeName(),
path_end->transition(sta_)->to_string().c_str(), path_end->transition(sta_)->to_string().c_str(),

View File

@ -31,6 +31,7 @@
#include "Search.hh" #include "Search.hh"
#include "search/Levelize.hh" #include "search/Levelize.hh"
#include "search/ReportPath.hh" #include "search/ReportPath.hh"
#include "PathExpanded.hh"
#include "Sta.hh" #include "Sta.hh"
using namespace sta; using namespace sta;
@ -1248,6 +1249,7 @@ bool is_data_check() { return self->isDataCheck(); }
bool is_output_delay() { return self->isOutputDelay(); } bool is_output_delay() { return self->isOutputDelay(); }
bool is_path_delay() { return self->isPathDelay(); } bool is_path_delay() { return self->isPathDelay(); }
bool is_gated_clock() { return self->isGatedClock(); } bool is_gated_clock() { return self->isGatedClock(); }
Pin *pin() { return self->vertex(Sta::sta())->pin(); }
Vertex *vertex() { return self->vertex(Sta::sta()); } Vertex *vertex() { return self->vertex(Sta::sta()); }
Path *path() { return self->path(); } Path *path() { return self->path(); }
RiseFall *end_transition() RiseFall *end_transition()
@ -1313,6 +1315,12 @@ pin()
return self->pin(sta); return self->pin(sta);
} }
const RiseFall *
edge()
{
return self->transition(Sta::sta());
}
string string
tag() tag()
{ {
@ -1334,6 +1342,13 @@ pins()
return pins; return pins;
} }
const Path *
start_path()
{
PathExpanded expanded(self, Sta::sta());
return expanded.startPath();
}
} }
%extend VertexPathIterator { %extend VertexPathIterator {