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,
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_; }

View File

@ -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.

View File

@ -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
{

View File

@ -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<std::pair<const Vertex*, const TimingArc*>> 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,33 +335,39 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
const MinMax *min_max,
const PathAnalysisPt *path_ap)
{
// These paths fanin to before_div_ so we know to_vertex matches.
if ((!unique_pins_ || from_vertex != prev_vertex_)
&& arc != prev_arc_
&& 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));
// 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_
&& arc != prev_arc_
&& (!unique_pins_ || from_vertex != prev_vertex_)
&& tagMatchNoCrpr(to_tag, before_div_tag_)) {
if (crpr_active_) {
// 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 (delayGreaterEqual(div_end->slack(this), path_end_slack_, this)) {
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
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)) {
PathEnd *div_end;
@ -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

View File

@ -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(),

View File

@ -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 {