Merge remote-tracking branch 'parallax/master'
Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
commit
6acb2f9fc3
|
|
@ -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 *
|
||||||
|
|
|
||||||
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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_; }
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1227,9 +1227,10 @@ 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()
|
||||||
|
&& ((exact_match && stringEq(prop, pattern))
|
||||||
|| (not_match && !stringEq(prop, pattern))
|
|| (not_match && !stringEq(prop, pattern))
|
||||||
|| (pattern_match && patternMatch(pattern, prop))
|
|| (pattern_match && patternMatch(pattern, prop))
|
||||||
|| (not_pattern_match && !patternMatch(pattern, prop))))
|
|| (not_pattern_match && !patternMatch(pattern, prop))))
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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 *
|
||||||
|
|
|
||||||
|
|
@ -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_; }
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
path_iter_.next(tag, path_index);
|
|
||||||
if ((rf_ == nullptr
|
|
||||||
|| tag->rfIndex() == rf_->index())
|
|
||||||
&& (path_ap_ == nullptr
|
|
||||||
|| tag->pathAPIndex() == path_ap_->index())
|
|
||||||
&& (min_max_ == nullptr
|
|
||||||
|| tag->pathAnalysisPt(search_)->pathMinMax() == min_max_)) {
|
|
||||||
next_ = &paths_[path_index];
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
next_ = nullptr;
|
bool
|
||||||
|
VertexPathIterator::hasNext()
|
||||||
|
{
|
||||||
|
return next_ != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Path *
|
Path *
|
||||||
|
|
|
||||||
|
|
@ -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,33 +388,44 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
|
||||||
const MinMax *min_max,
|
const MinMax *min_max,
|
||||||
const PathAnalysisPt *path_ap)
|
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",
|
debugPrint(debug_, "path_enum", 3, "visit fanin %s -> %s %s %s",
|
||||||
from_path->to_string(this).c_str(),
|
from_path->to_string(this).c_str(),
|
||||||
to_vertex->to_string(this).c_str(),
|
to_vertex->to_string(this).c_str(),
|
||||||
to_rf->to_string().c_str(),
|
to_rf->to_string().c_str(),
|
||||||
delayAsString(search_->deratedDelay(from_vertex, arc, edge,
|
delayAsString(search_->deratedDelay(from_vertex, arc, edge,
|
||||||
false,path_ap), this));
|
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_) {
|
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;
|
PathEnd *div_end;
|
||||||
Path *after_div_copy;
|
Path *after_div_copy;
|
||||||
// Make the diverted path end to check slack with from_path crpr.
|
// Make the diverted path end to check slack with from_path crpr.
|
||||||
makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy);
|
makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy);
|
||||||
if (div_end) {
|
if (div_end) {
|
||||||
// Only enumerate paths with greater slack.
|
// Only enumerate paths with greater slack.
|
||||||
if (delayGreaterEqual(div_end->slack(this), path_end_slack_, this)) {
|
// 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);
|
reportDiversion(edge, arc, from_path);
|
||||||
path_enum_->makeDiversion(div_end, after_div_copy);
|
path_enum_->makeDiversion(div_end, after_div_copy);
|
||||||
|
visited_fanins_.emplace(from_vertex, arc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
delete div_end;
|
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)) {
|
||||||
PathEnd *div_end;
|
PathEnd *div_end;
|
||||||
|
|
@ -468,12 +529,9 @@ 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
|
||||||
PathEnum::divSlack(Path *before_div,
|
PathEnum::divSlack(Path *before_div,
|
||||||
|
|
|
||||||
|
|
@ -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(),
|
||||||
|
|
|
||||||
|
|
@ -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 *
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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_) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue