Merge remote-tracking branch 'parallax/master'

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
Matt Liberty 2025-05-02 01:41:58 +00:00
commit 6acb2f9fc3
25 changed files with 211 additions and 145 deletions

View File

@ -431,7 +431,7 @@ GraphDelayCalc::seedNoDrvrSlew(Vertex *drvr_vertex,
load_pin_index_map, dcalc_ap); load_pin_index_map, dcalc_ap);
annotateLoadDelays(drvr_vertex, rf, dcalc_result, load_pin_index_map, delay_zero, annotateLoadDelays(drvr_vertex, rf, dcalc_result, load_pin_index_map, delay_zero,
false, dcalc_ap); false, dcalc_ap);
arc_delay_calc_->finishDrvrPin(); arc_delay_calc->finishDrvrPin();
} }
void void
@ -713,7 +713,7 @@ GraphDelayCalc::findDriverDelays(Vertex *drvr_vertex,
for (Vertex *drvr : multi_drvr->drvrs()) for (Vertex *drvr : multi_drvr->drvrs())
findDriverDelays1(drvr, multi_drvr, arc_delay_calc, load_pin_index_map); findDriverDelays1(drvr, multi_drvr, arc_delay_calc, load_pin_index_map);
} }
arc_delay_calc_->finishDrvrPin(); arc_delay_calc->finishDrvrPin();
} }
MultiDrvrNet * MultiDrvrNet *

Binary file not shown.

View File

@ -177,6 +177,13 @@ arrivals_clk(const RiseFall *rf,
return arrivals; return arrivals;
} }
float
arrival(const MinMax *min_max)
{
Sta *sta = Sta::sta();
return delayAsFloat(sta->vertexArrival(self, min_max));
}
StringSeq StringSeq
arrivals_clk_delays(const RiseFall *rf, arrivals_clk_delays(const RiseFall *rf,
Clock *clk, Clock *clk,

View File

@ -25,6 +25,7 @@
#pragma once #pragma once
#include <cstdarg> #include <cstdarg>
#include <mutex>
#include "Map.hh" #include "Map.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
@ -49,11 +50,12 @@ public:
int statsLevel() const { return stats_level_; } int statsLevel() const { return stats_level_; }
void reportLine(const char *what, void reportLine(const char *what,
const char *fmt, const char *fmt,
...) const ...)
__attribute__((format (printf, 3, 4))); __attribute__((format (printf, 3, 4)));
protected: protected:
Report *report_; Report *report_;
std::mutex buffer_lock_;
bool debug_on_; bool debug_on_;
DebugMap *debug_map_; DebugMap *debug_map_;
int stats_level_; int stats_level_;

View File

@ -217,15 +217,14 @@ private:
void findNext(); void findNext();
const Search *search_; const Search *search_;
//bool filtered_; bool filtered_;
const RiseFall *rf_; const RiseFall *rf_;
const PathAnalysisPt *path_ap_; const PathAnalysisPt *path_ap_;
const MinMax *min_max_; const MinMax *min_max_;
Path *paths_; Path *paths_;
size_t path_count_; size_t path_count_;
//size_t path_index_; size_t path_index_;
Path *next_; Path *next_;
PathIndexMap::Iterator path_iter_;
}; };
} // namespace } // namespace

View File

@ -85,7 +85,7 @@ public:
Type type() const { return type_; } Type type() const { return type_; }
const Unit *unit() const { return unit_; } const Unit *unit() const { return unit_; }
const char *asString(const Network *network) const; std::string to_string(const Network *network) const;
const char *stringValue() const; // valid for type string const char *stringValue() const; // valid for type string
float floatValue() const; // valid for type float float floatValue() const; // valid for type float
bool boolValue() const; // valid for type bool bool boolValue() const; // valid for type bool

View File

@ -115,7 +115,7 @@ typedef StringSet PathGroupNameSet;
typedef Vector<PathEnd*> PathEndSeq; typedef Vector<PathEnd*> PathEndSeq;
typedef Vector<Arrival> ArrivalSeq; typedef Vector<Arrival> ArrivalSeq;
typedef Map<Vertex*, size_t> VertexPathCountMap; typedef Map<Vertex*, size_t> VertexPathCountMap;
typedef UnorderedMap<Tag*, size_t, TagMatchHash, TagMatchEqual> PathIndexMap; typedef Map<Tag*, size_t, TagMatchLess> PathIndexMap;
typedef Vector<Slack> SlackSeq; typedef Vector<Slack> SlackSeq;
typedef Delay Crpr; typedef Delay Crpr;
typedef Vector<Path*> PathSeq; typedef Vector<Path*> PathSeq;

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

@ -309,9 +309,9 @@ TimingArcSet::arcsFrom(const RiseFall *from_rf,
TimingArc *&arc1, TimingArc *&arc1,
TimingArc *&arc2) const TimingArc *&arc2) const
{ {
int tr_index = from_rf->index(); int rf_index = from_rf->index();
arc1 = from_arc1_[tr_index]; arc1 = from_arc1_[rf_index];
arc2 = from_arc2_[tr_index]; arc2 = from_arc2_[rf_index];
} }
TimingArc * TimingArc *
@ -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

@ -1227,12 +1227,13 @@ filter_objects(const char *property,
bool not_pattern_match = stringEq(op, "!~"); bool not_pattern_match = stringEq(op, "!~");
for (T *object : *objects) { for (T *object : *objects) {
PropertyValue value(getProperty(object, property, sta)); PropertyValue value(getProperty(object, property, sta));
const char *prop = value.asString(sta->network()); string prop_str = value.to_string(sta->network());
if (prop && const char *prop = prop_str.c_str();
((exact_match && stringEq(prop, pattern)) if (!prop_str.empty()
|| (not_match && !stringEq(prop, pattern)) && ((exact_match && stringEq(prop, pattern))
|| (pattern_match && patternMatch(pattern, prop)) || (not_match && !stringEq(prop, pattern))
|| (not_pattern_match && !patternMatch(pattern, prop)))) || (pattern_match && patternMatch(pattern, prop))
|| (not_pattern_match && !patternMatch(pattern, prop))))
filtered_objects.push_back(object); filtered_objects.push_back(object);
} }
delete objects; delete objects;

View File

@ -217,6 +217,7 @@ BfsIterator::visitParallel(Level to_level,
} }
visitor->levelFinished(); visitor->levelFinished();
level_vertices.clear(); level_vertices.clear();
visit_count += vertex_count;
} }
} }
for (VertexVisitor *visitor : visitors) for (VertexVisitor *visitor : visitors)

View File

@ -128,8 +128,8 @@ ClkInfo::crprClkPath(const StaState *sta) const
return Path::vertexPath(crpr_clk_path_, sta); return Path::vertexPath(crpr_clk_path_, sta);
} }
const char * std::string
ClkInfo::asString(const StaState *sta) const ClkInfo::to_string(const StaState *sta) const
{ {
Network *network = sta->network(); Network *network = sta->network();
Corners *corners = sta->corners(); Corners *corners = sta->corners();
@ -160,9 +160,7 @@ ClkInfo::asString(const StaState *sta) const
if (is_gen_clk_src_path_) if (is_gen_clk_src_path_)
result += " genclk"; result += " genclk";
char *tmp = makeTmpString(result.size() + 1); return result;
strcpy(tmp, result.c_str());
return tmp;
} }
const Clock * const Clock *

View File

@ -49,7 +49,7 @@ public:
Path *crpr_clk_path, Path *crpr_clk_path,
const StaState *sta); const StaState *sta);
~ClkInfo(); ~ClkInfo();
const char *asString(const StaState *sta) const; std::string to_string(const StaState *sta) const;
const ClockEdge *clkEdge() const { return clk_edge_; } const ClockEdge *clkEdge() const { return clk_edge_; }
const Clock *clock() const; const Clock *clock() const;
const Pin *clkSrc() const { return clk_src_; } const Pin *clkSrc() const { return clk_src_; }

View File

@ -697,19 +697,18 @@ Path::lessAll(const Path *path1,
VertexPathIterator::VertexPathIterator(Vertex *vertex, VertexPathIterator::VertexPathIterator(Vertex *vertex,
const StaState *sta) : const StaState *sta) :
search_(sta->search()), search_(sta->search()),
//filtered_(false), filtered_(false),
rf_(nullptr), rf_(nullptr),
path_ap_(nullptr), path_ap_(nullptr),
min_max_(nullptr), min_max_(nullptr),
paths_(vertex->paths()), paths_(vertex->paths()),
path_count_(0), path_count_(0),
//path_index_(0), path_index_(0),
next_(nullptr) next_(nullptr)
{ {
TagGroup *tag_group = search_->tagGroup(vertex); TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) { if (tag_group) {
path_count_ = tag_group->pathCount(); path_count_ = tag_group->pathCount();
path_iter_.init(tag_group->pathIndexMap());
findNext(); findNext();
} }
} }
@ -721,19 +720,18 @@ VertexPathIterator::VertexPathIterator(Vertex *vertex,
const PathAnalysisPt *path_ap, const PathAnalysisPt *path_ap,
const StaState *sta) : const StaState *sta) :
search_(sta->search()), search_(sta->search()),
//filtered_(true), filtered_(true),
rf_(rf), rf_(rf),
path_ap_(path_ap), path_ap_(path_ap),
min_max_(nullptr), min_max_(nullptr),
paths_(vertex->paths()), paths_(vertex->paths()),
//path_count_(0), path_count_(0),
//path_index_(0), path_index_(0),
next_(nullptr) next_(nullptr)
{ {
TagGroup *tag_group = search_->tagGroup(vertex); TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) { if (tag_group) {
path_count_ = tag_group->pathCount(); path_count_ = tag_group->pathCount();
path_iter_.init(tag_group->pathIndexMap());
findNext(); findNext();
} }
} }
@ -743,19 +741,18 @@ VertexPathIterator::VertexPathIterator(Vertex *vertex,
const MinMax *min_max, const MinMax *min_max,
const StaState *sta) : const StaState *sta) :
search_(sta->search()), search_(sta->search()),
//filtered_(true), filtered_(true),
rf_(rf), rf_(rf),
path_ap_(nullptr), path_ap_(nullptr),
min_max_(min_max), min_max_(min_max),
paths_(vertex->paths()), paths_(vertex->paths()),
//path_count_(0), path_count_(0),
//path_index_(0), path_index_(0),
next_(nullptr) next_(nullptr)
{ {
TagGroup *tag_group = search_->tagGroup(vertex); TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) { if (tag_group) {
path_count_ = tag_group->pathCount(); path_count_ = tag_group->pathCount();
path_iter_.init(tag_group->pathIndexMap());
findNext(); findNext();
} }
} }
@ -766,34 +763,22 @@ VertexPathIterator::VertexPathIterator(Vertex *vertex,
const MinMax *min_max, const MinMax *min_max,
const StaState *sta) : const StaState *sta) :
search_(sta->search()), search_(sta->search()),
//filtered_(true), filtered_(true),
rf_(rf), rf_(rf),
path_ap_(path_ap), path_ap_(path_ap),
min_max_(min_max), min_max_(min_max),
paths_(vertex->paths()), paths_(vertex->paths()),
//path_count_(0), path_count_(0),
//path_index_(0), path_index_(0),
next_(nullptr) next_(nullptr)
{ {
TagGroup *tag_group = search_->tagGroup(vertex); TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) { if (tag_group) {
path_count_ = tag_group->pathCount(); path_count_ = tag_group->pathCount();
path_iter_.init(tag_group->pathIndexMap());
findNext(); findNext();
} }
} }
VertexPathIterator::~VertexPathIterator()
{
}
bool
VertexPathIterator::hasNext()
{
return next_ != nullptr;
}
#if 0
void void
VertexPathIterator::findNext() VertexPathIterator::findNext()
{ {
@ -818,26 +803,15 @@ VertexPathIterator::findNext()
} }
next_ = nullptr; next_ = nullptr;
} }
#endif
void VertexPathIterator::~VertexPathIterator()
VertexPathIterator::findNext()
{ {
while (path_iter_.hasNext()) { }
Tag *tag;
size_t path_index; bool
path_iter_.next(tag, path_index); VertexPathIterator::hasNext()
if ((rf_ == nullptr {
|| tag->rfIndex() == rf_->index()) return next_ != nullptr;
&& (path_ap_ == nullptr
|| tag->pathAPIndex() == path_ap_->index())
&& (min_max_ == nullptr
|| tag->pathAnalysisPt(search_)->pathMinMax() == min_max_)) {
next_ = &paths_[path_index];
return;
}
}
next_ = nullptr;
} }
Path * Path *

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:
@ -235,8 +236,7 @@ public:
Path *before_div, Path *before_div,
bool unique_pins, bool unique_pins,
PathEnum *path_enum); PathEnum *path_enum);
virtual VertexVisitor *copy() const; virtual VertexVisitor *copy() const override;
virtual void visit(Vertex *) {} // Not used.
void visitFaninPathsThru(Path *before_div, void visitFaninPathsThru(Path *before_div,
Vertex *prev_vertex, Vertex *prev_vertex,
TimingArc *prev_arc); TimingArc *prev_arc);
@ -254,7 +254,7 @@ public:
Tag *to_tag, Tag *to_tag,
Arrival &to_arrival, Arrival &to_arrival,
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap) override;
private: private:
void makeDivertedPathEnd(Path *after_div, void makeDivertedPathEnd(Path *after_div,
@ -263,22 +263,30 @@ private:
// Return values. // Return values.
PathEnd *&div_end, PathEnd *&div_end,
Path *&after_div_copy); Path *&after_div_copy);
bool visitEdge(const Pin *from_pin,
Vertex *from_vertex,
Edge *edge,
const Pin *to_pin,
Vertex *to_vertex) override;
virtual void visit(Vertex *) override {} // Not used.
void reportDiversion(const Edge *edge, void reportDiversion(const Edge *edge,
const TimingArc *div_arc, const TimingArc *div_arc,
Path *after_div); Path *after_div);
PathEnd *path_end_; PathEnd *path_end_;
Slack path_end_slack_;
Path *before_div_; Path *before_div_;
bool unique_pins_; bool unique_pins_;
int before_div_rf_index_; PathEnum *path_enum_;
Slack path_end_slack_;
Tag *before_div_tag_; Tag *before_div_tag_;
int before_div_rf_index_;
PathAPIndex before_div_ap_index_; 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_;
bool crpr_active_; bool crpr_active_;
VisitedFanins visited_fanins_;
}; };
PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end, PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end,
@ -287,14 +295,15 @@ PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end,
PathEnum *path_enum) : PathEnum *path_enum) :
PathVisitor(path_enum), PathVisitor(path_enum),
path_end_(path_end), path_end_(path_end),
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_ap_index_(before_div_->pathAnalysisPtIndex(this)),
before_div_arrival_(before_div_->arrival()),
path_enum_(path_enum), path_enum_(path_enum),
path_end_slack_(path_end->slack(this)),
before_div_tag_(before_div_->tag(this)),
before_div_rf_index_(before_div_tag_->rfIndex()),
before_div_ap_index_(before_div_tag_->pathAPIndex()),
before_div_arrival_(before_div_->arrival()),
crpr_active_(crprActive()) crpr_active_(crprActive())
{ {
} }
@ -305,15 +314,56 @@ 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();
before_div_rf_index_ = before_div_tag_->rfIndex();
before_div_ap_index_ = before_div_tag_->pathAPIndex();
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));
} }
// Specialize PathVisitor::visitEdge to filter paths/arcs to
// reduce tag mutations.
bool
PathEnumFaninVisitor::visitEdge(const Pin *from_pin,
Vertex *from_vertex,
Edge *edge,
const Pin *to_pin,
Vertex *to_vertex)
{
TagGroup *from_tag_group = search_->tagGroup(from_vertex);
if (from_tag_group) {
TimingArcSet *arc_set = edge->timingArcSet();
VertexPathIterator from_iter(from_vertex, search_);
while (from_iter.hasNext()) {
Path *from_path = from_iter.next();
PathAnalysisPt *path_ap = from_path->pathAnalysisPt(this);
if (path_ap->index() == before_div_ap_index_) {
const MinMax *min_max = path_ap->pathMinMax();
const RiseFall *from_rf = from_path->transition(this);
TimingArc *arc1, *arc2;
arc_set->arcsFrom(from_rf, arc1, arc2);
if (arc1 && arc1->toEdge()->asRiseFall()->index() == before_div_rf_index_) {
if (!visitArc(from_pin, from_vertex, from_rf, from_path,
edge, arc1, to_pin, to_vertex,
min_max, path_ap))
return false;
}
if (arc2 && arc2->toEdge()->asRiseFall()->index() == before_div_rf_index_) {
if (!visitArc(from_pin, from_vertex, from_rf, from_path,
edge, arc2, to_pin, to_vertex,
min_max, path_ap))
return false;
}
}
}
}
return true;
}
VertexVisitor * VertexVisitor *
PathEnumFaninVisitor::copy() const PathEnumFaninVisitor::copy() const
{ {
@ -338,32 +388,43 @@ 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); // fuzz for difference in updatePathHeadDelays and accumulated arrivals.
float fuzz = .001;
float slack_limit = path_end_slack_ > 0
? path_end_slack_ * (1.0 - fuzz)
: path_end_slack_ * (1.0 + fuzz);
if (delayGreaterEqual(div_end->slack(this), slack_limit, this)) {
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 +529,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

@ -613,8 +613,8 @@ PropertyValue::operator=(PropertyValue &&value)
return *this; return *this;
} }
const char * string
PropertyValue::asString(const Network *network) const PropertyValue::to_string(const Network *network) const
{ {
switch (type_) { switch (type_) {
case Type::type_string: case Type::type_string:
@ -652,9 +652,9 @@ PropertyValue::asString(const Network *network) const
case Type::type_clks: case Type::type_clks:
case Type::type_paths: case Type::type_paths:
case Type::type_pwr_activity: case Type::type_pwr_activity:
return nullptr; return "";
} }
return nullptr; return "";
} }
const char * const char *

View File

@ -2965,7 +2965,7 @@ Search::reportClkInfos() const
clk_infos.push_back(clk_info); clk_infos.push_back(clk_info);
sort(clk_infos, ClkInfoLess(this)); sort(clk_infos, ClkInfoLess(this));
for (ClkInfo *clk_info : clk_infos) for (ClkInfo *clk_info : clk_infos)
report_->reportLine("%s", clk_info->asString(this)); report_->reportLine("%s", clk_info->to_string(this).c_str());
report_->reportLine("%zu clk infos", clk_info_set_->size()); report_->reportLine("%zu clk infos", clk_info_set_->size());
} }
@ -3421,10 +3421,13 @@ RequiredCmp::requiredsSave(Vertex *vertex,
size_t path_index = path->pathIndex(sta); size_t path_index = path->pathIndex(sta);
Required req = requireds_[path_index]; Required req = requireds_[path_index];
Required &prev_req = path->required(); Required &prev_req = path->required();
debugPrint(debug, "search", 3, "required save %s -> %s", bool changed = !delayEqual(prev_req, req);
debugPrint(debug, "search", 3, "required %s save %s -> %s%s",
path->to_string(sta).c_str(),
delayAsString(prev_req, sta), delayAsString(prev_req, sta),
delayAsString(req, sta)); delayAsString(req, sta),
requireds_changed |= !delayEqual(prev_req, req); changed ? " changed" : "");
requireds_changed |= changed;
path->setRequired(req); path->setRequired(req);
} }
return requireds_changed; return requireds_changed;

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 {

View File

@ -541,7 +541,7 @@ Sta::~Sta()
delete clk_skews_; delete clk_skews_;
delete check_timing_; delete check_timing_;
delete report_path_; delete report_path_;
// Constraints reference search filter, so delete search first. // Sdc references search filter, so delete search first.
delete search_; delete search_;
delete latches_; delete latches_;
delete parasitics_; delete parasitics_;
@ -2875,7 +2875,7 @@ Arrival
Sta::vertexArrival(Vertex *vertex, Sta::vertexArrival(Vertex *vertex,
const MinMax *min_max) const MinMax *min_max)
{ {
return vertexArrival(vertex, nullptr, nullptr, nullptr, min_max); return vertexArrival(vertex, nullptr, clk_edge_wildcard, nullptr, min_max);
} }
Arrival Arrival
@ -4598,7 +4598,7 @@ Sta::deletePinBefore(const Pin *pin)
Edge *edge = in_edge_iter.next(); Edge *edge = in_edge_iter.next();
if (edge->role()->isWire()) { if (edge->role()->isWire()) {
Vertex *from = edge->from(graph_); Vertex *from = edge->from(graph_);
// Only notify from vertex (to vertex will be deleted). // Only notify to_vertex (from_vertex will be deleted).
search_->requiredInvalid(from); search_->requiredInvalid(from);
} }
levelize_->deleteEdgeBefore(edge); levelize_->deleteEdgeBefore(edge);

View File

@ -293,25 +293,22 @@ bool
TagLess::operator()(const Tag *tag1, TagLess::operator()(const Tag *tag1,
const Tag *tag2) const const Tag *tag2) const
{ {
return tagCmp(tag1, tag2, true) < 0; return tagCmp(tag1, tag2) < 0;
} }
int int
tagCmp(const Tag *tag1, tagCmp(const Tag *tag1,
const Tag *tag2, const Tag *tag2)
bool cmp_rf)
{ {
if (tag1 == tag2) if (tag1 == tag2)
return 0; return 0;
if (cmp_rf) { int rf_index1 = tag1->rfIndex();
int rf_index1 = tag1->rfIndex(); int rf_index2 = tag2->rfIndex();
int rf_index2 = tag2->rfIndex(); if (rf_index1 < rf_index2)
if (rf_index1 < rf_index2) return -1;
return -1; if (rf_index1 > rf_index2)
if (rf_index1 > rf_index2) return 1;
return 1;
}
PathAPIndex path_ap_index1 = tag1->pathAPIndex(); PathAPIndex path_ap_index1 = tag1->pathAPIndex();
PathAPIndex path_ap_index2 = tag2->pathAPIndex(); PathAPIndex path_ap_index2 = tag2->pathAPIndex();

View File

@ -138,8 +138,7 @@ public:
int int
tagCmp(const Tag *tag1, tagCmp(const Tag *tag1,
const Tag *tag2, const Tag *tag2);
bool cmp_rf);
// Match tag clock edge, clock driver and exception states but not clk info. // Match tag clock edge, clock driver and exception states but not clk info.
bool bool

View File

@ -131,9 +131,7 @@ TagGroupBldr::TagGroupBldr(bool match_crpr_clk_pin,
default_path_count_(sta->corners()->count() default_path_count_(sta->corners()->count()
* RiseFall::index_count * RiseFall::index_count
* MinMax::index_count), * MinMax::index_count),
path_index_map_(default_path_count_, path_index_map_(TagMatchLess(match_crpr_clk_pin, sta)),
TagMatchHash(match_crpr_clk_pin, sta),
TagMatchEqual(match_crpr_clk_pin, sta)),
paths_(default_path_count_), paths_(default_path_count_),
has_clk_tag_(false), has_clk_tag_(false),
has_genclk_src_tag_(false), has_genclk_src_tag_(false),
@ -284,9 +282,7 @@ TagGroupBldr::makeTagGroup(TagGroupIndex index,
PathIndexMap * PathIndexMap *
TagGroupBldr::makePathIndexMap(const StaState *sta) TagGroupBldr::makePathIndexMap(const StaState *sta)
{ {
PathIndexMap *path_index_map = new PathIndexMap(path_index_map_.size(), PathIndexMap *path_index_map = new PathIndexMap(TagMatchLess(true, sta));
TagMatchHash(true, sta),
TagMatchEqual(true, sta));
size_t path_index = 0; size_t path_index = 0;
for (auto const [tag, path_index1] : path_index_map_) { for (auto const [tag, path_index1] : path_index_map_) {

View File

@ -114,10 +114,11 @@ Debug::setLevel(const char *what,
void void
Debug::reportLine(const char *what, Debug::reportLine(const char *what,
const char *fmt, const char *fmt,
...) const ...)
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
std::unique_lock<std::mutex> lock(buffer_lock_);
report_->printToBuffer("%s", what); report_->printToBuffer("%s", what);
report_->printToBufferAppend(": "); report_->printToBufferAppend(": ");
report_->printToBufferAppend(fmt, args); report_->printToBufferAppend(fmt, args);