Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Matt Liberty 2025-11-05 19:53:18 +00:00
commit 96101312a2
21 changed files with 1493 additions and 1378 deletions

View File

@ -194,7 +194,7 @@ following command builds a Docker image.
``` ```
cd OpenSTA cd OpenSTA
docker build --file Dockerfile.ubuntu22.04 --tag opensta . docker build --file Dockerfile.ubuntu22.04 --tag opensta_ubuntu22.04 .
``` ```
To run a docker container using the OpenSTA image, use the -v option To run a docker container using the OpenSTA image, use the -v option

View File

@ -12,6 +12,11 @@ build directory instead of `app/`.
The set_max_delay and set_min_delay commands now support the -probe option. The set_max_delay and set_min_delay commands now support the -probe option.
With -probe these commands do not break paths at internal (non-startpoint) pins. With -probe these commands do not break paths at internal (non-startpoint) pins.
The report_checks command now supports a -unique_edges_to_endpoint option
to remove paths through identical pins and rise/fall edges.
report_checks [-unique_edges_to_endpoint]
Release 2.6.1 2025/03/30 Release 2.6.1 2025/03/30
------------------------- -------------------------

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -53,6 +53,7 @@ public:
int group_path_count, int group_path_count,
int endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
const MinMax *min_max, const MinMax *min_max,
const StaState *sta); const StaState *sta);
// Path group that compares arrival time, sorted by min_max. // Path group that compares arrival time, sorted by min_max.
@ -60,6 +61,7 @@ public:
int group_path_count, int group_path_count,
int endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
float min_slack, float min_slack,
float max_slack, float max_slack,
const StaState *sta); const StaState *sta);
@ -83,6 +85,7 @@ protected:
size_t group_path_count, size_t group_path_count,
size_t endpoint_path_count, size_t endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
float min_slack, float min_slack,
float max_slack, float max_slack,
bool cmp_slack, bool cmp_slack,
@ -96,6 +99,7 @@ protected:
size_t group_path_count_; size_t group_path_count_;
size_t endpoint_path_count_; size_t endpoint_path_count_;
bool unique_pins_; bool unique_pins_;
bool unique_edges_;
float slack_min_; float slack_min_;
float slack_max_; float slack_max_;
PathEndSeq path_ends_; PathEndSeq path_ends_;
@ -112,6 +116,7 @@ public:
PathGroups(int group_path_count, PathGroups(int group_path_count,
int endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
PathGroupNameSet *group_names, PathGroupNameSet *group_names,
@ -148,6 +153,7 @@ protected:
int group_path_count, int group_path_count,
int endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
const Corner *corner, const Corner *corner,
const MinMaxAll *min_max); const MinMaxAll *min_max);
void makeGroupPathEnds(ExceptionTo *to, void makeGroupPathEnds(ExceptionTo *to,
@ -162,6 +168,7 @@ protected:
int group_path_count, int group_path_count,
int endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
bool cmp_slack); bool cmp_slack);
void pushGroupPathEnds(PathEndSeq &path_ends); void pushGroupPathEnds(PathEndSeq &path_ends);
@ -171,6 +178,7 @@ protected:
void makeGroups(int group_path_count, void makeGroups(int group_path_count,
int endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
PathGroupNameSet *group_names, PathGroupNameSet *group_names,
@ -185,6 +193,7 @@ protected:
int group_path_count_; int group_path_count_;
int endpoint_path_count_; int endpoint_path_count_;
bool unique_pins_; bool unique_pins_;
bool unique_edges_;
float slack_min_; float slack_min_;
float slack_max_; float slack_max_;

View File

@ -144,7 +144,7 @@ typedef UnorderedMap<EdgePins, ExceptionPathSet*,
PinPairHash, PinPairEqual> EdgeExceptionsMap; PinPairHash, PinPairEqual> EdgeExceptionsMap;
typedef Vector<ExceptionThru*> ExceptionThruSeq; typedef Vector<ExceptionThru*> ExceptionThruSeq;
typedef Map<const Port*,InputDrive*> InputDriveMap; typedef Map<const Port*,InputDrive*> InputDriveMap;
typedef Map<int, ExceptionPathSet*, std::less<int> > ExceptionPathPtHash; typedef Map<size_t, ExceptionPathSet*, std::less<size_t> > ExceptionPathPtHash;
typedef Set<ClockLatency*, ClockLatencyLess> ClockLatencies; typedef Set<ClockLatency*, ClockLatencyLess> ClockLatencies;
typedef Map<const Pin*, ClockUncertainties*> PinClockUncertaintyMap; typedef Map<const Pin*, ClockUncertainties*> PinClockUncertaintyMap;
typedef Set<InterClockUncertainty*, InterClockUncertaintyLess> InterClockUncertaintySet; typedef Set<InterClockUncertainty*, InterClockUncertaintyLess> InterClockUncertaintySet;

View File

@ -105,6 +105,7 @@ public:
size_t group_path_count, size_t group_path_count,
size_t endpoint_path_count, size_t endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
bool sort_by_slack, bool sort_by_slack,
@ -169,18 +170,6 @@ public:
PathGroupSeq pathGroups(const PathEnd *path_end) const; PathGroupSeq pathGroups(const PathEnd *path_end) const;
void deletePathGroups(); void deletePathGroups();
void makePathGroups(int group_path_count,
int endpoint_path_count,
bool unique_pins,
float min_slack,
float max_slack,
PathGroupNameSet *group_names,
bool setup,
bool hold,
bool recovery,
bool removal,
bool clk_gating_setup,
bool clk_gating_hold);
virtual ExceptionPath *exceptionTo(ExceptionPathType type, virtual ExceptionPath *exceptionTo(ExceptionPathType type,
const Path *path, const Path *path,
const Pin *pin, const Pin *pin,
@ -256,7 +245,8 @@ public:
Edge *edge, Edge *edge,
const RiseFall *to_rf, const RiseFall *to_rf,
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap,
TagSet *tag_cache);
Tag *thruClkTag(Path *from_path, Tag *thruClkTag(Path *from_path,
Vertex *from_vertex, Vertex *from_vertex,
Tag *from_tag, Tag *from_tag,
@ -331,7 +321,8 @@ public:
InputDelay *input_delay, InputDelay *input_delay,
bool is_segment_start, bool is_segment_start,
ExceptionStateSet *states, ExceptionStateSet *states,
bool own_states); bool own_states,
TagSet *tag_cache);
void reportTags() const; void reportTags() const;
void reportClkInfos() const; void reportClkInfos() const;
const ClkInfo *findClkInfo(const ClockEdge *clk_edge, const ClkInfo *findClkInfo(const ClockEdge *clk_edge,
@ -527,7 +518,8 @@ protected:
const ClkInfo *to_clk_info, const ClkInfo *to_clk_info,
InputDelay *to_input_delay, InputDelay *to_input_delay,
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap); const PathAnalysisPt *path_ap,
TagSet *tag_cache);
ExceptionPath *exceptionTo(const Path *path, ExceptionPath *exceptionTo(const Path *path,
const Pin *pin, const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
@ -701,9 +693,11 @@ class PathVisitor : public VertexVisitor, public StaState
{ {
public: public:
// Uses search->evalPred() for search predicate. // Uses search->evalPred() for search predicate.
explicit PathVisitor(const StaState *sta); PathVisitor(const StaState *sta);
PathVisitor(SearchPred *pred, PathVisitor(SearchPred *pred,
bool make_tag_cache,
const StaState *sta); const StaState *sta);
virtual ~PathVisitor();
virtual void visitFaninPaths(Vertex *to_vertex); virtual void visitFaninPaths(Vertex *to_vertex);
virtual void visitFanoutPaths(Vertex *from_vertex); virtual void visitFanoutPaths(Vertex *from_vertex);
@ -752,6 +746,7 @@ protected:
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap) = 0; const PathAnalysisPt *path_ap) = 0;
SearchPred *pred_; SearchPred *pred_;
TagSet *tag_cache_;
}; };
// Visitor called during forward search to record an // Visitor called during forward search to record an
@ -759,7 +754,7 @@ protected:
class ArrivalVisitor : public PathVisitor class ArrivalVisitor : public PathVisitor
{ {
public: public:
explicit ArrivalVisitor(const StaState *sta); ArrivalVisitor(const StaState *sta);
virtual ~ArrivalVisitor(); virtual ~ArrivalVisitor();
// Initialize the visitor. // Initialize the visitor.
// Defaults pred to search->eval_pred_. // Defaults pred to search->eval_pred_.
@ -833,12 +828,14 @@ protected:
class RequiredVisitor : public PathVisitor class RequiredVisitor : public PathVisitor
{ {
public: public:
explicit RequiredVisitor(const StaState *sta); RequiredVisitor(const StaState *sta);
virtual ~RequiredVisitor(); virtual ~RequiredVisitor();
virtual VertexVisitor *copy() const; virtual VertexVisitor *copy() const;
virtual void visit(Vertex *vertex); virtual void visit(Vertex *vertex);
protected: protected:
RequiredVisitor(bool make_tag_cache,
const StaState *sta);
// Return false to stop visiting. // Return false to stop visiting.
virtual bool visitFromToPath(const Pin *from_pin, virtual bool visitFromToPath(const Pin *from_pin,
Vertex *from_vertex, Vertex *from_vertex,

View File

@ -821,9 +821,12 @@ public:
// Number of paths to report for // Number of paths to report for
// each endpoint. // each endpoint.
int endpoint_path_count, int endpoint_path_count,
// endpoint_path_count paths report unique pins // endpoint_path_count paths report paths with
// without rise/fall variations. // unique pins.
bool unique_pins, bool unique_pins,
// endpoint_path_count paths report paths with
// unique pins and rise/fall edges.
bool unique_edges,
// Min/max bounds for slack of // Min/max bounds for slack of
// returned path ends. // returned path ends.
float slack_min, float slack_min,

View File

@ -630,7 +630,8 @@ FalsePath::overrides(ExceptionPath *exception) const
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
LoopPath::LoopPath(ExceptionThruSeq *thrus, bool own_pts) : LoopPath::LoopPath(ExceptionThruSeq *thrus,
bool own_pts) :
FalsePath(nullptr, thrus, nullptr, MinMaxAll::all(), own_pts, FalsePath(nullptr, thrus, nullptr, MinMaxAll::all(), own_pts,
falsePathPriority() + fromThruToPriority(nullptr, thrus, nullptr), falsePathPriority() + fromThruToPriority(nullptr, thrus, nullptr),
nullptr) nullptr)
@ -1128,32 +1129,41 @@ ExceptionFromTo::deletePin(const Pin *pin,
const Network *network) const Network *network)
{ {
if (pins_) { if (pins_) {
pins_->erase(pin); auto itr = pins_->find(pin);
if (itr != pins_->end()) {
pins_->erase(itr);
// Incrementally update hash. // Incrementally update hash.
hash_ -= network->id(pin) * hash_pin; hash_ -= network->id(pin) * hash_pin;
} }
} }
}
void void
ExceptionFromTo::deleteClock(Clock *clk) ExceptionFromTo::deleteClock(Clock *clk)
{ {
if (clks_) { if (clks_) {
clks_->erase(clk); auto itr = clks_->find(clk);
if (itr != clks_->end()) {
clks_->erase(itr);
// Incrementally update hash. // Incrementally update hash.
hash_ -= clk->index() * hash_clk; hash_ -= clk->index() * hash_clk;
} }
} }
}
void void
ExceptionFromTo::deleteInstance(const Instance *inst, ExceptionFromTo::deleteInstance(const Instance *inst,
const Network *network) const Network *network)
{ {
if (insts_) { if (insts_) {
insts_->erase(inst); auto itr = insts_->find(inst);
if (itr != insts_->end()) {
insts_->erase(itr);
// Incrementally update hash. // Incrementally update hash.
hash_ -= network->id(inst) * hash_inst; hash_ -= network->id(inst) * hash_inst;
} }
} }
}
void void
ExceptionFromTo::disconnectPinBefore(const Pin *pin, ExceptionFromTo::disconnectPinBefore(const Pin *pin,
@ -1782,33 +1792,42 @@ ExceptionThru::deletePin(const Pin *pin,
const Network *network) const Network *network)
{ {
if (pins_) { if (pins_) {
pins_->erase(pin); auto itr = pins_->find(pin);
if (itr != pins_->end()) {
pins_->erase(itr);
// Incrementally update hash. // Incrementally update hash.
hash_ -= network->id(pin) * hash_pin; hash_ -= network->id(pin) * hash_pin;
} }
} }
}
void void
ExceptionThru::deleteNet(const Net *net, ExceptionThru::deleteNet(const Net *net,
const Network *network) const Network *network)
{ {
if (nets_) { if (nets_) {
nets_->erase(net); auto itr = nets_->find(net);
if (itr != nets_->end()) {
nets_->erase(itr);
// Incrementally update hash. // Incrementally update hash.
hash_ -= network->id(net) * hash_net; hash_ -= network->id(net) * hash_net;
} }
} }
}
void void
ExceptionThru::deleteInstance(const Instance *inst, ExceptionThru::deleteInstance(const Instance *inst,
const Network *network) const Network *network)
{ {
if (insts_) { if (insts_) {
insts_->erase(inst); auto itr = insts_->find(inst);
if (itr != insts_->end()) {
insts_->erase(itr);
// Incrementally update hash. // Incrementally update hash.
hash_ -= network->id(inst) * hash_inst; hash_ -= network->id(inst) * hash_inst;
} }
} }
}
void void
ExceptionThru::deleteEdge(const EdgePins &edge) ExceptionThru::deleteEdge(const EdgePins &edge)

View File

@ -4894,6 +4894,7 @@ Sdc::deleteExceptions()
path_delay_internal_from_break_.clear(); path_delay_internal_from_break_.clear();
path_delay_internal_to_.clear(); path_delay_internal_to_.clear();
path_delay_internal_to_break_.clear(); path_delay_internal_to_break_.clear();
pin_exceptions_.deleteContentsClear();
deleteExceptionPtHashMapSets(exception_merge_hash_); deleteExceptionPtHashMapSets(exception_merge_hash_);
exception_merge_hash_.clear(); exception_merge_hash_.clear();

View File

@ -421,7 +421,8 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
while (src_iter.hasNext()) { while (src_iter.hasNext()) {
Path *src_path = src_iter.next(); Path *src_path = src_iter.next();
const Clock *src_clk = src_path->clock(this); const Clock *src_clk = src_path->clock(this);
if (src_rf->matches(src_path->transition(this)) if (src_path->isClock(this)
&& src_rf->matches(src_path->transition(this))
&& src_path->minMax(this) == setup_hold_ && src_path->minMax(this) == setup_hold_
&& clk_set_.find(src_clk) != clk_set_.end()) { && clk_set_.find(src_clk) != clk_set_.end()) {
Corner *src_corner = src_path->pathAnalysisPt(this)->corner(); Corner *src_corner = src_path->pathAnalysisPt(this)->corner();

View File

@ -716,7 +716,7 @@ Genclks::makeTag(const Clock *gclk,
nullptr, insert, 0.0, nullptr, nullptr, insert, 0.0, nullptr,
path_ap, nullptr); path_ap, nullptr);
return search_->findTag(master_rf, path_ap, clk_info, false, return search_->findTag(master_rf, path_ap, clk_info, false,
nullptr, false, states, true); nullptr, false, states, true, nullptr);
} }
class GenClkArrivalSearchPred : public EvalPred class GenClkArrivalSearchPred : public EvalPred

View File

@ -395,7 +395,7 @@ Latches::latchOutArrival(const Path *data_path,
en_clk_edge->transition(), en_clk_edge->transition(),
MinMax::max(), false, states)) MinMax::max(), false, states))
q_tag = search_->findTag(q_rf, path_ap, q_clk_info, false, q_tag = search_->findTag(q_rf, path_ap, q_clk_info, false,
nullptr, false, states, true); nullptr, false, states, true, nullptr);
} }
return; return;
} }

View File

@ -48,6 +48,7 @@ namespace sta {
// after_div<--------+ // after_div<--------+
// | // |
// <--...--before_div<--...--path<---path_end // <--...--before_div<--...--path<---path_end
//
class Diversion class Diversion
{ {
public: public:
@ -105,6 +106,7 @@ deleteDiversionPathEnd(Diversion *div)
PathEnum::PathEnum(size_t group_path_count, PathEnum::PathEnum(size_t group_path_count,
size_t endpoint_path_count, size_t endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
bool cmp_slack, bool cmp_slack,
const StaState *sta) : const StaState *sta) :
StaState(sta), StaState(sta),
@ -112,6 +114,7 @@ PathEnum::PathEnum(size_t group_path_count,
group_path_count_(group_path_count), group_path_count_(group_path_count),
endpoint_path_count_(endpoint_path_count), endpoint_path_count_(endpoint_path_count),
unique_pins_(unique_pins), unique_pins_(unique_pins),
unique_edges_(unique_edges),
div_queue_(DiversionGreater(sta)), div_queue_(DiversionGreater(sta)),
div_count_(0), div_count_(0),
inserts_pruned_(false), inserts_pruned_(false),
@ -230,6 +233,7 @@ PathEnum::reportDiversionPath(Diversion *div)
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
typedef std::set<std::pair<const Vertex*, const TimingArc*>> VisitedFanins; typedef std::set<std::pair<const Vertex*, const TimingArc*>> VisitedFanins;
typedef std::pair<const Vertex*, const RiseFall*> VertexEdge;
class PathEnumFaninVisitor : public PathVisitor class PathEnumFaninVisitor : public PathVisitor
{ {
@ -237,6 +241,7 @@ public:
PathEnumFaninVisitor(PathEnd *path_end, PathEnumFaninVisitor(PathEnd *path_end,
Path *before_div, Path *before_div,
bool unique_pins, bool unique_pins,
bool unique_edges,
PathEnum *path_enum); PathEnum *path_enum);
virtual VertexVisitor *copy() const override; virtual VertexVisitor *copy() const override;
void visitFaninPathsThru(Path *before_div, void visitFaninPathsThru(Path *before_div,
@ -271,6 +276,7 @@ private:
const Pin *to_pin, const Pin *to_pin,
Vertex *to_vertex) override; Vertex *to_vertex) override;
virtual void visit(Vertex *) override {} // Not used. virtual void visit(Vertex *) override {} // Not used.
void insertUniqueEdgeDiv(Diversion *div);
void reportDiversion(const Edge *edge, void reportDiversion(const Edge *edge,
const TimingArc *div_arc, const TimingArc *div_arc,
Path *after_div); Path *after_div);
@ -278,6 +284,7 @@ private:
PathEnd *path_end_; PathEnd *path_end_;
Path *before_div_; Path *before_div_;
bool unique_pins_; bool unique_pins_;
bool unique_edges_;
PathEnum *path_enum_; PathEnum *path_enum_;
Slack path_end_slack_; Slack path_end_slack_;
@ -289,16 +296,19 @@ private:
Vertex *prev_vertex_; Vertex *prev_vertex_;
bool crpr_active_; bool crpr_active_;
VisitedFanins visited_fanins_; VisitedFanins visited_fanins_;
std::map<VertexEdge, Diversion*> unique_edge_divs_;
}; };
PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end, PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end,
Path *before_div, Path *before_div,
bool unique_pins, bool unique_pins,
bool unique_edges,
PathEnum *path_enum) : PathEnum *path_enum) :
PathVisitor(path_enum), PathVisitor(path_enum),
path_end_(path_end), path_end_(path_end),
before_div_(before_div), before_div_(before_div),
unique_pins_(unique_pins), unique_pins_(unique_pins),
unique_edges_(unique_edges),
path_enum_(path_enum), path_enum_(path_enum),
path_end_slack_(path_end->slack(this)), path_end_slack_(path_end->slack(this)),
@ -310,6 +320,13 @@ PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end,
{ {
} }
VertexVisitor *
PathEnumFaninVisitor::copy() const
{
return new PathEnumFaninVisitor(path_end_, before_div_, unique_pins_,
unique_edges_, path_enum_);
}
void void
PathEnumFaninVisitor::visitFaninPathsThru(Path *before_div, PathEnumFaninVisitor::visitFaninPathsThru(Path *before_div,
Vertex *prev_vertex, Vertex *prev_vertex,
@ -324,7 +341,13 @@ PathEnumFaninVisitor::visitFaninPathsThru(Path *before_div,
prev_arc_ = prev_arc; prev_arc_ = prev_arc;
prev_vertex_ = prev_vertex; prev_vertex_ = prev_vertex;
visited_fanins_.clear(); visited_fanins_.clear();
unique_edge_divs_.clear();
visitFaninPaths(before_div_->vertex(this)); visitFaninPaths(before_div_->vertex(this));
if (unique_edges_) {
for (auto [vertex_edge, div] : unique_edge_divs_)
path_enum_->insert(div);
}
} }
// Specialize PathVisitor::visitEdge to filter paths/arcs to // Specialize PathVisitor::visitEdge to filter paths/arcs to
@ -342,12 +365,14 @@ PathEnumFaninVisitor::visitEdge(const Pin *from_pin,
VertexPathIterator from_iter(from_vertex, search_); VertexPathIterator from_iter(from_vertex, search_);
while (from_iter.hasNext()) { while (from_iter.hasNext()) {
Path *from_path = from_iter.next(); Path *from_path = from_iter.next();
// Filter paths by path ap.
PathAnalysisPt *path_ap = from_path->pathAnalysisPt(this); PathAnalysisPt *path_ap = from_path->pathAnalysisPt(this);
if (path_ap->index() == before_div_ap_index_) { if (path_ap->index() == before_div_ap_index_) {
const MinMax *min_max = path_ap->pathMinMax(); const MinMax *min_max = path_ap->pathMinMax();
const RiseFall *from_rf = from_path->transition(this); const RiseFall *from_rf = from_path->transition(this);
TimingArc *arc1, *arc2; TimingArc *arc1, *arc2;
arc_set->arcsFrom(from_rf, arc1, arc2); arc_set->arcsFrom(from_rf, arc1, arc2);
// Filter arcs by to edge.
if (arc1 && arc1->toEdge()->asRiseFall()->index() == before_div_rf_index_) { if (arc1 && arc1->toEdge()->asRiseFall()->index() == before_div_rf_index_) {
if (!visitArc(from_pin, from_vertex, from_rf, from_path, if (!visitArc(from_pin, from_vertex, from_rf, from_path,
edge, arc1, to_pin, to_vertex, edge, arc1, to_pin, to_vertex,
@ -366,13 +391,6 @@ PathEnumFaninVisitor::visitEdge(const Pin *from_pin,
return true; return true;
} }
VertexVisitor *
PathEnumFaninVisitor::copy() const
{
return new PathEnumFaninVisitor(path_end_, before_div_, unique_pins_,
path_enum_);
}
bool bool
PathEnumFaninVisitor::visitFromToPath(const Pin *, PathEnumFaninVisitor::visitFromToPath(const Pin *,
Vertex *from_vertex, Vertex *from_vertex,
@ -393,42 +411,49 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
// 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 ((!unique_pins_ || from_vertex != prev_vertex_) if ((!unique_pins_ || from_vertex != prev_vertex_)
&& arc != prev_arc_ && arc != prev_arc_
&& Tag::matchNoCrpr(to_tag, before_div_tag_)) { && Tag::matchNoCrpr(to_tag, before_div_tag_)
// Ignore paths that only differ by crpr from same vertex/edge.
&& (!crpr_active_
|| visited_fanins_.find({from_vertex, arc}) == visited_fanins_.end())) {
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));
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) {
reportDiversion(edge, arc, from_path); reportDiversion(edge, arc, from_path);
path_enum_->makeDiversion(div_end, after_div_copy); Diversion *div = new Diversion(div_end, after_div_copy);
if (unique_edges_)
insertUniqueEdgeDiv(div);
else
path_enum_->insert(div);
if (crpr_active_)
visited_fanins_.emplace(from_vertex, arc); visited_fanins_.emplace(from_vertex, arc);
} }
}
else else
debugPrint(debug_, "path_enum", 3, " pruned %s %s", debugPrint(debug_, "path_enum", 3, " pruned %s %s",
edge->to_string(this).c_str(), edge->to_string(this).c_str(),
arc->to_string().c_str()); arc->to_string().c_str());
}
else {
PathEnd *div_end;
Path *after_div_copy;
makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy);
reportDiversion(edge, arc, from_path);
path_enum_->makeDiversion(div_end, after_div_copy);
}
}
return true; return true;
} }
void
PathEnumFaninVisitor::insertUniqueEdgeDiv(Diversion *div)
{
Slack div_slack = div->pathEnd()->slack(this);
const Path *div_path = div->divPath();
const Vertex *div_vertex = div_path->vertex(this);
const RiseFall *div_rf = div_path->transition(this);
auto itr = unique_edge_divs_.find({div_vertex, div_rf});
if (itr == unique_edge_divs_.end()
|| div_slack > itr->second->pathEnd()->slack(this))
itr->second = div;
}
void void
PathEnumFaninVisitor::makeDivertedPathEnd(Path *after_div, PathEnumFaninVisitor::makeDivertedPathEnd(Path *after_div,
Edge *div_edge, Edge *div_edge,
@ -440,13 +465,9 @@ PathEnumFaninVisitor::makeDivertedPathEnd(Path *after_div,
Path *div_path; Path *div_path;
path_enum_->makeDivertedPath(path_end_->path(), before_div_, after_div, path_enum_->makeDivertedPath(path_end_->path(), before_div_, after_div,
div_edge, div_arc, div_path, after_div_copy); div_edge, div_arc, div_path, after_div_copy);
if (after_div_copy) {
div_end = path_end_->copy(); div_end = path_end_->copy();
div_end->setPath(div_path); div_end->setPath(div_path);
} }
else
div_end = nullptr;
}
void void
PathEnumFaninVisitor::reportDiversion(const Edge *div_edge, PathEnumFaninVisitor::reportDiversion(const Edge *div_edge,
@ -476,21 +497,11 @@ PathEnumFaninVisitor::reportDiversion(const Edge *div_edge,
} }
} }
// A diversion is an alternate path formed by changing the previous
// path/arc of before_div to after_div/div_arc in path.
//
// div_arc
// after_div<--------+
// |
// <--...--before_div<--...--path<---path_end
void void
PathEnum::makeDiversion(PathEnd *div_end, PathEnum::insert(Diversion *div)
Path *after_div_copy)
{ {
Diversion *div = new Diversion(div_end, after_div_copy);
div_queue_.push(div); div_queue_.push(div);
div_count_++; div_count_++;
if (div_queue_.size() > group_path_count_ * 2) if (div_queue_.size() > group_path_count_ * 2)
// We have more potenial paths than we will need. // We have more potenial paths than we will need.
pruneDiversionQueue(); pruneDiversionQueue();
@ -550,7 +561,7 @@ PathEnum::divSlack(Path *before_div,
} }
} }
else { else {
report()->error(1370, "path diversion missing edge."); report_->error(1370, "path diversion missing edge.");
return 0.0; return 0.0;
} }
} }
@ -564,7 +575,8 @@ PathEnum::makeDiversions(PathEnd *path_end,
Path *path = before; Path *path = before;
Path *prev_path = path->prevPath(); Path *prev_path = path->prevPath();
TimingArc *prev_arc = path->prevArc(this); TimingArc *prev_arc = path->prevArc(this);
PathEnumFaninVisitor fanin_visitor(path_end, path, unique_pins_, this); PathEnumFaninVisitor fanin_visitor(path_end, path, unique_pins_,
unique_edges_, this);
while (prev_path) { while (prev_path) {
// Fanin visitor does all the work. // Fanin visitor does all the work.
// While visiting the fanins the fanin_visitor finds the // While visiting the fanins the fanin_visitor finds the
@ -686,7 +698,7 @@ PathEnum::updatePathHeadDelays(PathSeq &paths,
tag->isClock(), tag->isClock(),
tag->inputDelay(), tag->inputDelay(),
tag->isSegmentStart(), tag->isSegmentStart(),
tag->states(), false); tag->states(), false, nullptr);
path->setTag(updated_tag); path->setTag(updated_tag);
} }
debugPrint(debug_, "path_enum", 5, "update arrival %s %s %s -> %s", debugPrint(debug_, "path_enum", 5, "update arrival %s %s %s -> %s",

View File

@ -61,6 +61,7 @@ public:
PathEnum(size_t group_path_count, PathEnum(size_t group_path_count,
size_t endpoint_path_count, size_t endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
bool cmp_slack, bool cmp_slack,
const StaState *sta); const StaState *sta);
// Insert path ends that are enumerated in slack/arrival order. // Insert path ends that are enumerated in slack/arrival order.
@ -72,8 +73,7 @@ public:
private: private:
void makeDiversions(PathEnd *path_end, void makeDiversions(PathEnd *path_end,
Path *before); Path *before);
void makeDiversion(PathEnd *div_end, void insert(Diversion *div);
Path *after_div_copy);
void makeDivertedPath(Path *path, void makeDivertedPath(Path *path,
Path *before_div, Path *before_div,
Path *after_div, Path *after_div,
@ -97,6 +97,7 @@ private:
size_t group_path_count_; size_t group_path_count_;
size_t endpoint_path_count_; size_t endpoint_path_count_;
bool unique_pins_; bool unique_pins_;
bool unique_edges_;
DiversionQueue div_queue_; DiversionQueue div_queue_;
int div_count_; int div_count_;
// Number of paths returned for each endpoint (limit to endpoint_path_count). // Number of paths returned for each endpoint (limit to endpoint_path_count).

View File

@ -53,12 +53,14 @@ PathGroup::makePathGroupSlack(const char *name,
int group_path_count, int group_path_count,
int endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
const StaState *sta) const StaState *sta)
{ {
return new PathGroup(name, group_path_count, endpoint_path_count, unique_pins, return new PathGroup(name, group_path_count, endpoint_path_count,
slack_min, slack_max, true, MinMax::min(), sta); unique_pins, unique_edges, slack_min, slack_max,
true, MinMax::min(), sta);
} }
PathGroup * PathGroup *
@ -66,17 +68,20 @@ PathGroup::makePathGroupArrival(const char *name,
int group_path_count, int group_path_count,
int endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
const MinMax *min_max, const MinMax *min_max,
const StaState *sta) const StaState *sta)
{ {
return new PathGroup(name, group_path_count, endpoint_path_count, unique_pins, return new PathGroup(name, group_path_count, endpoint_path_count,
0.0, 0.0, false, min_max, sta); unique_pins, unique_edges, 0.0, 0.0,
false, min_max, sta);
} }
PathGroup::PathGroup(const char *name, PathGroup::PathGroup(const char *name,
size_t group_path_count, size_t group_path_count,
size_t endpoint_path_count, size_t endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
bool cmp_slack, bool cmp_slack,
@ -86,6 +91,7 @@ PathGroup::PathGroup(const char *name,
group_path_count_(group_path_count), group_path_count_(group_path_count),
endpoint_path_count_(endpoint_path_count), endpoint_path_count_(endpoint_path_count),
unique_pins_(unique_pins), unique_pins_(unique_pins),
unique_edges_(unique_edges),
slack_min_(slack_min), slack_min_(slack_min),
slack_max_(slack_max), slack_max_(slack_max),
min_max_(min_max), min_max_(min_max),
@ -252,6 +258,7 @@ const char *PathGroups::unconstrained_group_name_ = "unconstrained";
PathGroups::PathGroups(int group_path_count, PathGroups::PathGroups(int group_path_count,
int endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
PathGroupNameSet *group_names, PathGroupNameSet *group_names,
@ -267,14 +274,15 @@ PathGroups::PathGroups(int group_path_count,
group_path_count_(group_path_count), group_path_count_(group_path_count),
endpoint_path_count_(endpoint_path_count), endpoint_path_count_(endpoint_path_count),
unique_pins_(unique_pins), unique_pins_(unique_pins),
unique_edges_(unique_edges),
slack_min_(slack_min), slack_min_(slack_min),
slack_max_(slack_max) slack_max_(slack_max)
{ {
makeGroups(group_path_count, endpoint_path_count, unique_pins, makeGroups(group_path_count, endpoint_path_count, unique_pins, unique_edges,
slack_min, slack_max, group_names, slack_min, slack_max, group_names,
setup, recovery, clk_gating_setup, unconstrained, setup, recovery, clk_gating_setup, unconstrained,
MinMax::max()); MinMax::max());
makeGroups(group_path_count, endpoint_path_count, unique_pins, makeGroups(group_path_count, endpoint_path_count, unique_pins, unique_edges,
slack_min, slack_max, group_names, slack_min, slack_max, group_names,
hold, removal, clk_gating_hold, unconstrained, hold, removal, clk_gating_hold, unconstrained,
MinMax::min()); MinMax::min());
@ -284,6 +292,7 @@ void
PathGroups::makeGroups(int group_path_count, PathGroups::makeGroups(int group_path_count,
int endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
PathGroupNameSet *group_names, PathGroupNameSet *group_names,
@ -301,6 +310,7 @@ PathGroups::makeGroups(int group_path_count,
group_path_count, group_path_count,
endpoint_path_count, endpoint_path_count,
unique_pins, unique_pins,
unique_edges,
slack_min, slack_max, slack_min, slack_max,
this); this);
named_map_[mm_index][name] = group; named_map_[mm_index][name] = group;
@ -314,6 +324,7 @@ PathGroups::makeGroups(int group_path_count,
group_path_count, group_path_count,
endpoint_path_count, endpoint_path_count,
unique_pins, unique_pins,
unique_edges,
slack_min, slack_max, slack_min, slack_max,
this); this);
clk_map_[mm_index][clk] = group; clk_map_[mm_index][clk] = group;
@ -327,6 +338,7 @@ PathGroups::makeGroups(int group_path_count,
group_path_count, group_path_count,
endpoint_path_count, endpoint_path_count,
unique_pins, unique_pins,
unique_edges,
slack_min, slack_max, slack_min, slack_max,
this); this);
else else
@ -338,6 +350,7 @@ PathGroups::makeGroups(int group_path_count,
group_path_count, group_path_count,
endpoint_path_count, endpoint_path_count,
unique_pins, unique_pins,
unique_edges,
slack_min, slack_max, slack_min, slack_max,
this); this);
else else
@ -349,6 +362,7 @@ PathGroups::makeGroups(int group_path_count,
group_path_count, group_path_count,
endpoint_path_count, endpoint_path_count,
unique_pins, unique_pins,
unique_edges,
slack_min, slack_max, slack_min, slack_max,
this); this);
else else
@ -359,7 +373,7 @@ PathGroups::makeGroups(int group_path_count,
unconstrained_[mm_index] = unconstrained_[mm_index] =
PathGroup::makePathGroupArrival(unconstrained_group_name_, PathGroup::makePathGroupArrival(unconstrained_group_name_,
group_path_count, endpoint_path_count, group_path_count, endpoint_path_count,
unique_pins, min_max, this); unique_pins, unique_edges, min_max, this);
else else
unconstrained_[mm_index] = nullptr; unconstrained_[mm_index] = nullptr;
} }
@ -576,8 +590,8 @@ PathGroups::makePathEnds(ExceptionTo *to,
bool sort_by_slack) bool sort_by_slack)
{ {
Stats stats(debug_, report_); Stats stats(debug_, report_);
makeGroupPathEnds(to, group_path_count_, endpoint_path_count_, unique_pins_, makeGroupPathEnds(to, group_path_count_, endpoint_path_count_,
corner, min_max); unique_pins_, unique_edges_, corner, min_max);
PathEndSeq path_ends; PathEndSeq path_ends;
pushGroupPathEnds(path_ends); pushGroupPathEnds(path_ends);
@ -805,6 +819,7 @@ PathGroups::makeGroupPathEnds(ExceptionTo *to,
int group_path_count, int group_path_count,
int endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
const Corner *corner, const Corner *corner,
const MinMaxAll *min_max) const MinMaxAll *min_max)
{ {
@ -822,27 +837,33 @@ PathGroups::makeGroupPathEnds(ExceptionTo *to,
const char *name = name_group.first; const char *name = name_group.first;
PathGroup *group = findPathGroup(name, path_min_max); PathGroup *group = findPathGroup(name, path_min_max);
if (group) if (group)
enumPathEnds(group, group_path_count, endpoint_path_count, unique_pins, true); enumPathEnds(group, group_path_count, endpoint_path_count,
unique_pins, unique_edges, true);
} }
for (auto clk : sdc_->clks()) { for (auto clk : sdc_->clks()) {
PathGroup *group = findPathGroup(clk, path_min_max); PathGroup *group = findPathGroup(clk, path_min_max);
if (group) if (group)
enumPathEnds(group, group_path_count, endpoint_path_count, unique_pins, true); enumPathEnds(group, group_path_count, endpoint_path_count,
unique_pins, unique_edges, true);
} }
PathGroup *group = unconstrained_[mm_index]; PathGroup *group = unconstrained_[mm_index];
if (group) if (group)
enumPathEnds(group, group_path_count, endpoint_path_count, unique_pins, false); enumPathEnds(group, group_path_count, endpoint_path_count,
unique_pins, unique_edges, false);
group = path_delay_[mm_index]; group = path_delay_[mm_index];
if (group) if (group)
enumPathEnds(group, group_path_count, endpoint_path_count, unique_pins, true); enumPathEnds(group, group_path_count, endpoint_path_count,
unique_pins, unique_edges, true);
group = gated_clk_[mm_index]; group = gated_clk_[mm_index];
if (group) if (group)
enumPathEnds(group, group_path_count, endpoint_path_count, unique_pins, true); enumPathEnds(group, group_path_count, endpoint_path_count,
unique_pins, unique_edges, true);
group = async_[mm_index]; group = async_[mm_index];
if (group) if (group)
enumPathEnds(group, group_path_count, endpoint_path_count, unique_pins, true); enumPathEnds(group, group_path_count, endpoint_path_count,
unique_pins, unique_edges, true);
} }
} }
} }
@ -852,12 +873,13 @@ PathGroups::enumPathEnds(PathGroup *group,
int group_path_count, int group_path_count,
int endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
bool cmp_slack) bool cmp_slack)
{ {
// Insert the worst max_path path ends in the group into a path // Insert the worst max_path path ends in the group into a path
// enumerator. // enumerator.
PathEnum path_enum(group_path_count, endpoint_path_count, PathEnum path_enum(group_path_count, endpoint_path_count,
unique_pins, cmp_slack, this); unique_pins, unique_edges, cmp_slack, this);
PathGroupIterator *end_iter = group->iterator(); PathGroupIterator *end_iter = group->iterator();
while (end_iter->hasNext()) { while (end_iter->hasNext()) {
PathEnd *end = end_iter->next(); PathEnd *end = end_iter->next();

View File

@ -147,7 +147,7 @@ DynLoopSrchPred::hasPendingLoopPaths(Edge *edge,
PathAPIndex path_ap_index = from_tag->pathAPIndex(); PathAPIndex path_ap_index = from_tag->pathAPIndex();
PathAnalysisPt *path_ap = corners->findPathAnalysisPt(path_ap_index); PathAnalysisPt *path_ap = corners->findPathAnalysisPt(path_ap_index);
Tag *to_tag = search->thruTag(from_tag, edge, RiseFall::rise(), Tag *to_tag = search->thruTag(from_tag, edge, RiseFall::rise(),
path_ap->pathMinMax(), path_ap); path_ap->pathMinMax(), path_ap, nullptr);
if (to_tag if (to_tag
&& (prev_tag_group == nullptr && (prev_tag_group == nullptr
|| !prev_tag_group->hasTag(from_tag))) || !prev_tag_group->hasTag(from_tag)))
@ -450,6 +450,7 @@ Search::findPathEnds(ExceptionFrom *from,
size_t group_path_count, size_t group_path_count,
size_t endpoint_path_count, size_t endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
bool sort_by_slack, bool sort_by_slack,
@ -466,11 +467,15 @@ Search::findPathEnds(ExceptionFrom *from,
recovery = removal = false; recovery = removal = false;
if (!variables_->gatedClkChecksEnabled()) if (!variables_->gatedClkChecksEnabled())
clk_gating_setup = clk_gating_hold = false; clk_gating_setup = clk_gating_hold = false;
makePathGroups(group_path_count, endpoint_path_count, unique_pins, path_groups_ = new PathGroups(group_path_count, endpoint_path_count,
unique_pins, unique_edges,
slack_min, slack_max, slack_min, slack_max,
group_names, setup, hold, group_names,
setup, hold,
recovery, removal, recovery, removal,
clk_gating_setup, clk_gating_hold); clk_gating_setup, clk_gating_hold,
unconstrained_paths_,
this);
ensureDownstreamClkPins(); ensureDownstreamClkPins();
PathEndSeq path_ends = path_groups_->makePathEnds(to, unconstrained_paths_, PathEndSeq path_ends = path_groups_->makePathEnds(to, unconstrained_paths_,
corner, min_max, corner, min_max,
@ -1106,7 +1111,7 @@ Search::findArrivalsSeed()
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
ArrivalVisitor::ArrivalVisitor(const StaState *sta) : ArrivalVisitor::ArrivalVisitor(const StaState *sta) :
PathVisitor(nullptr, sta) PathVisitor(nullptr, false, sta)
{ {
init0(); init0();
init(true); init(true);
@ -1116,7 +1121,7 @@ ArrivalVisitor::ArrivalVisitor(const StaState *sta) :
ArrivalVisitor::ArrivalVisitor(bool always_to_endpoints, ArrivalVisitor::ArrivalVisitor(bool always_to_endpoints,
SearchPred *pred, SearchPred *pred,
const StaState *sta) : const StaState *sta) :
PathVisitor(pred, sta) PathVisitor(pred, true, sta)
{ {
init0(); init0();
init(always_to_endpoints, pred); init(always_to_endpoints, pred);
@ -1619,7 +1624,8 @@ Search::seedClkArrival(const Pin *pin,
// Only false_paths -from apply to clock tree pins. // Only false_paths -from apply to clock tree pins.
ExceptionStateSet *states = nullptr; ExceptionStateSet *states = nullptr;
sdc_->exceptionFromClkStates(pin,rf,clk,rf,min_max,states); sdc_->exceptionFromClkStates(pin,rf,clk,rf,min_max,states);
Tag *tag = findTag(rf, path_ap, clk_info, true, nullptr, false, states, true); Tag *tag = findTag(rf, path_ap, clk_info, true, nullptr, false, states,
true, nullptr);
Arrival arrival(clk_edge->time() + insertion); Arrival arrival(clk_edge->time() + insertion);
tag_bldr->setArrival(tag, arrival); tag_bldr->setArrival(tag, arrival);
} }
@ -1657,7 +1663,8 @@ Search::clkDataTag(const Pin *pin,
|| sdc_->isPropagatedClock(pin)); || sdc_->isPropagatedClock(pin));
const ClkInfo *clk_info = findClkInfo(clk_edge, pin, is_propagated, const ClkInfo *clk_info = findClkInfo(clk_edge, pin, is_propagated,
insertion, path_ap); insertion, path_ap);
return findTag(rf, path_ap, clk_info, false, nullptr, false, states, true); return findTag(rf, path_ap, clk_info, false, nullptr, false, states,
true, nullptr);
} }
else else
return nullptr; return nullptr;
@ -2018,7 +2025,7 @@ Search::inputDelayTag(const Pin *pin,
false, nullptr, clk_insertion, clk_latency, false, nullptr, clk_insertion, clk_latency,
clk_uncertainties, path_ap, nullptr); clk_uncertainties, path_ap, nullptr);
tag = findTag(rf, path_ap, clk_info, false, input_delay, is_segment_start, tag = findTag(rf, path_ap, clk_info, false, input_delay, is_segment_start,
states, true); states, true, nullptr);
} }
if (tag) { if (tag) {
@ -2026,7 +2033,7 @@ Search::inputDelayTag(const Pin *pin,
// Check for state changes on existing tag exceptions (pending -thru pins). // Check for state changes on existing tag exceptions (pending -thru pins).
tag = mutateTag(tag, pin, rf, false, clk_info, tag = mutateTag(tag, pin, rf, false, clk_info,
pin, rf, false, false, is_segment_start, clk_info, pin, rf, false, false, is_segment_start, clk_info,
input_delay, min_max, path_ap); input_delay, min_max, path_ap, nullptr);
} }
return tag; return tag;
} }
@ -2034,18 +2041,30 @@ Search::inputDelayTag(const Pin *pin,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
PathVisitor::PathVisitor(const StaState *sta) : PathVisitor::PathVisitor(const StaState *sta) :
StaState(sta), StaState(sta),
pred_(sta->search()->evalPred()) pred_(sta->search()->evalPred()),
tag_cache_( nullptr)
{ {
} }
PathVisitor::PathVisitor(SearchPred *pred, PathVisitor::PathVisitor(SearchPred *pred,
bool make_tag_cache,
const StaState *sta) : const StaState *sta) :
StaState(sta), StaState(sta),
pred_(pred) pred_(pred),
tag_cache_(make_tag_cache
? new TagSet(128, TagSet::hasher(sta), TagSet::key_equal(sta))
: nullptr)
{ {
} }
PathVisitor::~PathVisitor()
{
delete tag_cache_;
}
void void
PathVisitor::visitFaninPaths(Vertex *to_vertex) PathVisitor::visitFaninPaths(Vertex *to_vertex)
{ {
@ -2233,7 +2252,7 @@ PathVisitor::visitFromPath(const Pin *from_pin,
to_clk_info, to_pin, to_rf, min_max, to_clk_info, to_pin, to_rf, min_max,
path_ap); path_ap);
if (to_tag) if (to_tag)
to_tag = search_->thruTag(to_tag, edge, to_rf, min_max, path_ap); to_tag = search_->thruTag(to_tag, edge, to_rf, min_max, path_ap, tag_cache_);
from_arrival = search_->clkPathArrival(from_path, from_clk_info, from_arrival = search_->clkPathArrival(from_path, from_clk_info,
clk_edge, min_max, path_ap); clk_edge, min_max, path_ap);
to_arrival = from_arrival + arc_delay; to_arrival = from_arrival + arc_delay;
@ -2249,7 +2268,7 @@ PathVisitor::visitFromPath(const Pin *from_pin,
latches_->latchOutArrival(from_path, arc, edge, path_ap, latches_->latchOutArrival(from_path, arc, edge, path_ap,
to_tag, arc_delay, to_arrival); to_tag, arc_delay, to_arrival);
if (to_tag) if (to_tag)
to_tag = search_->thruTag(to_tag, edge, to_rf, min_max, path_ap); to_tag = search_->thruTag(to_tag, edge, to_rf, min_max, path_ap, tag_cache_);
} }
} }
else if (from_tag->isClock()) { else if (from_tag->isClock()) {
@ -2288,7 +2307,7 @@ PathVisitor::visitFromPath(const Pin *from_pin,
else { else {
if (!(sdc_->isPathDelayInternalFromBreak(to_pin) if (!(sdc_->isPathDelayInternalFromBreak(to_pin)
|| sdc_->isPathDelayInternalToBreak(from_pin))) { || sdc_->isPathDelayInternalToBreak(from_pin))) {
to_tag = search_->thruTag(from_tag, edge, to_rf, min_max, path_ap); to_tag = search_->thruTag(from_tag, edge, to_rf, min_max, path_ap, tag_cache_);
arc_delay = search_->deratedDelay(from_vertex, arc, edge, false, path_ap); arc_delay = search_->deratedDelay(from_vertex, arc, edge, false, path_ap);
if (!delayInf(arc_delay)) if (!delayInf(arc_delay))
to_arrival = from_arrival + arc_delay; to_arrival = from_arrival + arc_delay;
@ -2398,7 +2417,7 @@ Search::fromUnclkedInputTag(const Pin *pin,
&& (!require_exception || states)) { && (!require_exception || states)) {
const ClkInfo *clk_info = findClkInfo(nullptr, nullptr, false, 0.0, path_ap); const ClkInfo *clk_info = findClkInfo(nullptr, nullptr, false, 0.0, path_ap);
return findTag(rf, path_ap, clk_info, false, nullptr, return findTag(rf, path_ap, clk_info, false, nullptr,
is_segment_start, states, true); is_segment_start, states, true, nullptr);
} }
return nullptr; return nullptr;
} }
@ -2419,7 +2438,8 @@ Search::fromRegClkTag(const Pin *from_pin,
min_max, states)) { min_max, states)) {
// Hack for filter -from reg/Q. // Hack for filter -from reg/Q.
sdc_->filterRegQStates(to_pin, to_rf, min_max, states); sdc_->filterRegQStates(to_pin, to_rf, min_max, states);
return findTag(to_rf, path_ap, clk_info, false, nullptr, false, states, true); return findTag(to_rf, path_ap, clk_info, false, nullptr, false, states,
true, nullptr);
} }
else else
return nullptr; return nullptr;
@ -2453,7 +2473,8 @@ Search::thruTag(Tag *from_tag,
Edge *edge, Edge *edge,
const RiseFall *to_rf, const RiseFall *to_rf,
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap) const PathAnalysisPt *path_ap,
TagSet *tag_cache)
{ {
const Pin *from_pin = edge->from(graph_)->pin(); const Pin *from_pin = edge->from(graph_)->pin();
Vertex *to_vertex = edge->to(graph_); Vertex *to_vertex = edge->to(graph_);
@ -2464,7 +2485,8 @@ Search::thruTag(Tag *from_tag,
Tag *to_tag = mutateTag(from_tag, from_pin, from_rf, false, from_clk_info, Tag *to_tag = mutateTag(from_tag, from_pin, from_rf, false, from_clk_info,
to_pin, to_rf, false, to_is_reg_clk, false, to_pin, to_rf, false, to_is_reg_clk, false,
// input delay is not propagated. // input delay is not propagated.
from_clk_info, nullptr, min_max, path_ap); from_clk_info, nullptr, min_max, path_ap,
tag_cache);
return to_tag; return to_tag;
} }
@ -2498,7 +2520,7 @@ Search::thruClkTag(Path *from_path,
arc_delay_min_max_eq, min_max, path_ap); arc_delay_min_max_eq, min_max, path_ap);
Tag *to_tag = mutateTag(from_tag,from_pin,from_rf,from_is_clk,from_clk_info, Tag *to_tag = mutateTag(from_tag,from_pin,from_rf,from_is_clk,from_clk_info,
to_pin, to_rf, to_is_clk, to_is_reg_clk, false, to_pin, to_rf, to_is_clk, to_is_reg_clk, false,
to_clk_info, nullptr, min_max, path_ap); to_clk_info, nullptr, min_max, path_ap, nullptr);
return to_tag; return to_tag;
} }
@ -2629,7 +2651,8 @@ Search::mutateTag(Tag *from_tag,
const ClkInfo *to_clk_info, const ClkInfo *to_clk_info,
InputDelay *to_input_delay, InputDelay *to_input_delay,
const MinMax *min_max, const MinMax *min_max,
const PathAnalysisPt *path_ap) const PathAnalysisPt *path_ap,
TagSet *tag_cache)
{ {
ExceptionStateSet *new_states = nullptr; ExceptionStateSet *new_states = nullptr;
ExceptionStateSet *from_states = from_tag->states(); ExceptionStateSet *from_states = from_tag->states();
@ -2713,8 +2736,8 @@ Search::mutateTag(Tag *from_tag,
if (new_states) if (new_states)
return findTag(to_rf, path_ap, to_clk_info, to_is_clk, return findTag(to_rf, path_ap, to_clk_info, to_is_clk,
from_tag->inputDelay(), to_is_segment_start, from_tag->inputDelay(), to_is_segment_start, new_states,
new_states, true); true, tag_cache);
else { else {
// No state change. // No state change.
if (to_clk_info == from_clk_info if (to_clk_info == from_clk_info
@ -2724,9 +2747,8 @@ Search::mutateTag(Tag *from_tag,
&& from_tag->inputDelay() == to_input_delay) && from_tag->inputDelay() == to_input_delay)
return from_tag; return from_tag;
else else
return findTag(to_rf, path_ap, to_clk_info, to_is_clk, return findTag(to_rf, path_ap, to_clk_info, to_is_clk, to_input_delay,
to_input_delay, to_is_segment_start, to_is_segment_start, from_states, false, tag_cache);
from_states, false);
} }
} }
@ -2978,10 +3000,16 @@ Search::findTag(const RiseFall *rf,
InputDelay *input_delay, InputDelay *input_delay,
bool is_segment_start, bool is_segment_start,
ExceptionStateSet *states, ExceptionStateSet *states,
bool own_states) bool own_states,
TagSet *tag_cache)
{ {
Tag probe(0, rf->index(), path_ap->index(), clk_info, is_clk, input_delay, Tag probe(0, rf->index(), path_ap->index(), clk_info, is_clk, input_delay,
is_segment_start, states, false, this); is_segment_start, states, false, this);
if (tag_cache) {
Tag *tag = tag_cache->findKey(&probe);
if (tag)
return tag;
}
LockGuard lock(tag_lock_); LockGuard lock(tag_lock_);
Tag *tag = tag_set_->findKey(&probe); Tag *tag = tag_set_->findKey(&probe);
if (tag == nullptr) { if (tag == nullptr) {
@ -3019,6 +3047,10 @@ Search::findTag(const RiseFall *rf,
} }
if (own_states) if (own_states)
delete states; delete states;
if (tag_cache)
tag_cache->insert(tag);
return tag; return tag;
} }
@ -3531,6 +3563,14 @@ RequiredVisitor::RequiredVisitor(const StaState *sta) :
{ {
} }
RequiredVisitor::RequiredVisitor(bool make_tag_cache,
const StaState *sta) :
PathVisitor(sta->search()->evalPred(), make_tag_cache, sta),
required_cmp_(new RequiredCmp),
visit_path_ends_(new VisitPathEnds(sta))
{
}
RequiredVisitor::~RequiredVisitor() RequiredVisitor::~RequiredVisitor()
{ {
delete required_cmp_; delete required_cmp_;
@ -3540,7 +3580,7 @@ RequiredVisitor::~RequiredVisitor()
VertexVisitor * VertexVisitor *
RequiredVisitor::copy() const RequiredVisitor::copy() const
{ {
return new RequiredVisitor(this); return new RequiredVisitor(true, this);
} }
void void
@ -4091,31 +4131,6 @@ Search::wnsSlack(Vertex *vertex,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
void
Search::makePathGroups(int group_path_count,
int endpoint_path_count,
bool unique_pins,
float slack_min,
float slack_max,
PathGroupNameSet *group_names,
bool setup,
bool hold,
bool recovery,
bool removal,
bool clk_gating_setup,
bool clk_gating_hold)
{
path_groups_ = new PathGroups(group_path_count, endpoint_path_count,
unique_pins,
slack_min, slack_max,
group_names,
setup, hold,
recovery, removal,
clk_gating_setup, clk_gating_hold,
unconstrained_paths_,
this);
}
void void
Search::deletePathGroups() Search::deletePathGroups()
{ {

View File

@ -372,6 +372,7 @@ find_path_ends(ExceptionFrom *from,
int group_path_count, int group_path_count,
int endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
bool sort_by_slack, bool sort_by_slack,
@ -387,7 +388,7 @@ find_path_ends(ExceptionFrom *from,
PathEndSeq ends = sta->findPathEnds(from, thrus, to, unconstrained, PathEndSeq ends = sta->findPathEnds(from, thrus, to, unconstrained,
corner, delay_min_max, corner, delay_min_max,
group_path_count, endpoint_path_count, group_path_count, endpoint_path_count,
unique_pins, unique_pins, unique_edges,
slack_min, slack_max, slack_min, slack_max,
sort_by_slack, sort_by_slack,
groups->size() ? groups : nullptr, groups->size() ? groups : nullptr,

View File

@ -102,6 +102,7 @@ define_cmd_args "find_timing_paths" \
[-group_path_count path_count] \ [-group_path_count path_count] \
[-endpoint_path_count path_count]\ [-endpoint_path_count path_count]\
[-unique_paths_to_endpoint]\ [-unique_paths_to_endpoint]\
[-unique_edges_to_endpoint]\
[-slack_max slack_max]\ [-slack_max slack_max]\
[-slack_min slack_min]\ [-slack_min slack_min]\
[-sort_by_slack]\ [-sort_by_slack]\
@ -121,7 +122,9 @@ proc find_timing_paths_cmd { cmd args_var } {
-path_delay -corner -group_count -endpoint_count \ -path_delay -corner -group_count -endpoint_count \
-group_path_count -endpoint_path_count \ -group_path_count -endpoint_path_count \
-slack_max -slack_min -path_group} \ -slack_max -slack_min -path_group} \
flags {-unconstrained -sort_by_slack -unique_paths_to_endpoint} 0 flags {-unconstrained -sort_by_slack \
-unique_paths_to_endpoint \
-unique_edges_to_endpoint} 0
set min_max "max" set min_max "max"
set end_rf "rise_fall" set end_rf "rise_fall"
@ -195,6 +198,7 @@ proc find_timing_paths_cmd { cmd args_var } {
} }
set unique_pins [info exists flags(-unique_paths_to_endpoint)] set unique_pins [info exists flags(-unique_paths_to_endpoint)]
set unique_edges [info exists flags(-unique_edges_to_endpoint)]
set slack_min "-1e+30" set slack_min "-1e+30"
if [info exist keys(-slack_min)] { if [info exist keys(-slack_min)] {
@ -229,7 +233,8 @@ proc find_timing_paths_cmd { cmd args_var } {
set path_ends [find_path_ends $from $thrus $to $unconstrained \ set path_ends [find_path_ends $from $thrus $to $unconstrained \
$corner $min_max \ $corner $min_max \
$group_path_count $endpoint_path_count $unique_pins \ $group_path_count $endpoint_path_count \
$unique_pins $unique_edges \
$slack_min $slack_max \ $slack_min $slack_max \
$sort_by_slack $groups \ $sort_by_slack $groups \
1 1 1 1 1 1] 1 1 1 1 1 1]
@ -574,7 +579,7 @@ proc_redirect report_check_types {
set slack_max $sta::float_inf set slack_max $sta::float_inf
} }
set path_ends [find_path_ends "NULL" {} "NULL" 0 \ set path_ends [find_path_ends "NULL" {} "NULL" 0 \
$corner $path_min_max $group_path_count 1 0 \ $corner $path_min_max $group_path_count 1 1 0 \
$slack_min $slack_max \ $slack_min $slack_max \
0 {} \ 0 {} \
$setup $hold \ $setup $hold \

View File

@ -2464,6 +2464,7 @@ Sta::findPathEnds(ExceptionFrom *from,
int group_path_count, int group_path_count,
int endpoint_path_count, int endpoint_path_count,
bool unique_pins, bool unique_pins,
bool unique_edges,
float slack_min, float slack_min,
float slack_max, float slack_max,
bool sort_by_slack, bool sort_by_slack,
@ -2477,8 +2478,10 @@ Sta::findPathEnds(ExceptionFrom *from,
{ {
searchPreamble(); searchPreamble();
return search_->findPathEnds(from, thrus, to, unconstrained, return search_->findPathEnds(from, thrus, to, unconstrained,
corner, min_max, group_path_count, endpoint_path_count, corner, min_max, group_path_count,
unique_pins, slack_min, slack_max, endpoint_path_count,
unique_pins, unique_edges,
slack_min, slack_max,
sort_by_slack, group_names, sort_by_slack, group_names,
setup, hold, setup, hold,
recovery, removal, recovery, removal,
@ -2727,8 +2730,10 @@ Sta::findGroupPathPins(const char *group_path_name)
nullptr, nullptr, nullptr, false, nullptr, nullptr, nullptr, false,
// corner, min_max, // corner, min_max,
nullptr, MinMaxAll::max(), nullptr, MinMaxAll::max(),
// group_path_count, endpoint_path_count, unique_pins // group_path_count, endpoint_path_count
1, 1, false, 1, 1,
// unique_pins, unique_edges
true, true,
-INF, INF, // slack_min, slack_max, -INF, INF, // slack_min, slack_max,
false, // sort_by_slack false, // sort_by_slack
nullptr, // group_names nullptr, // group_names

View File

@ -1,6 +1,4 @@
# Test get_* -filter # get_* -filter
# Read in design and libraries
read_liberty asap7_small.lib.gz read_liberty asap7_small.lib.gz
read_verilog reg1_asap7.v read_verilog reg1_asap7.v
link_design top link_design top