Compare commits
9 Commits
19202ac933
...
96101312a2
| Author | SHA1 | Date |
|---|---|---|
|
|
96101312a2 | |
|
|
79d8a5ecb3 | |
|
|
10a3cdc4d1 | |
|
|
28812daf20 | |
|
|
97b711c7c4 | |
|
|
f6523bd9c6 | |
|
|
423c12c8f9 | |
|
|
9f3123cff1 | |
|
|
265e7f2d10 |
|
|
@ -194,7 +194,7 @@ following command builds a Docker image.
|
|||
|
||||
```
|
||||
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
|
||||
|
|
|
|||
|
|
@ -12,6 +12,11 @@ build directory instead of `app/`.
|
|||
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.
|
||||
|
||||
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
|
||||
-------------------------
|
||||
|
||||
|
|
|
|||
2329
doc/OpenSTA.fodt
2329
doc/OpenSTA.fodt
File diff suppressed because it is too large
Load Diff
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -53,6 +53,7 @@ public:
|
|||
int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta);
|
||||
// Path group that compares arrival time, sorted by min_max.
|
||||
|
|
@ -60,6 +61,7 @@ public:
|
|||
int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
float min_slack,
|
||||
float max_slack,
|
||||
const StaState *sta);
|
||||
|
|
@ -83,6 +85,7 @@ protected:
|
|||
size_t group_path_count,
|
||||
size_t endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
float min_slack,
|
||||
float max_slack,
|
||||
bool cmp_slack,
|
||||
|
|
@ -96,6 +99,7 @@ protected:
|
|||
size_t group_path_count_;
|
||||
size_t endpoint_path_count_;
|
||||
bool unique_pins_;
|
||||
bool unique_edges_;
|
||||
float slack_min_;
|
||||
float slack_max_;
|
||||
PathEndSeq path_ends_;
|
||||
|
|
@ -112,6 +116,7 @@ public:
|
|||
PathGroups(int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
PathGroupNameSet *group_names,
|
||||
|
|
@ -148,6 +153,7 @@ protected:
|
|||
int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
const Corner *corner,
|
||||
const MinMaxAll *min_max);
|
||||
void makeGroupPathEnds(ExceptionTo *to,
|
||||
|
|
@ -162,6 +168,7 @@ protected:
|
|||
int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
bool cmp_slack);
|
||||
|
||||
void pushGroupPathEnds(PathEndSeq &path_ends);
|
||||
|
|
@ -171,6 +178,7 @@ protected:
|
|||
void makeGroups(int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
PathGroupNameSet *group_names,
|
||||
|
|
@ -185,6 +193,7 @@ protected:
|
|||
int group_path_count_;
|
||||
int endpoint_path_count_;
|
||||
bool unique_pins_;
|
||||
bool unique_edges_;
|
||||
float slack_min_;
|
||||
float slack_max_;
|
||||
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ typedef UnorderedMap<EdgePins, ExceptionPathSet*,
|
|||
PinPairHash, PinPairEqual> EdgeExceptionsMap;
|
||||
typedef Vector<ExceptionThru*> ExceptionThruSeq;
|
||||
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 Map<const Pin*, ClockUncertainties*> PinClockUncertaintyMap;
|
||||
typedef Set<InterClockUncertainty*, InterClockUncertaintyLess> InterClockUncertaintySet;
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ public:
|
|||
size_t group_path_count,
|
||||
size_t endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
bool sort_by_slack,
|
||||
|
|
@ -169,18 +170,6 @@ public:
|
|||
|
||||
PathGroupSeq pathGroups(const PathEnd *path_end) const;
|
||||
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,
|
||||
const Path *path,
|
||||
const Pin *pin,
|
||||
|
|
@ -256,7 +245,8 @@ public:
|
|||
Edge *edge,
|
||||
const RiseFall *to_rf,
|
||||
const MinMax *min_max,
|
||||
const PathAnalysisPt *path_ap);
|
||||
const PathAnalysisPt *path_ap,
|
||||
TagSet *tag_cache);
|
||||
Tag *thruClkTag(Path *from_path,
|
||||
Vertex *from_vertex,
|
||||
Tag *from_tag,
|
||||
|
|
@ -325,13 +315,14 @@ public:
|
|||
const RiseFall *to_rf);
|
||||
|
||||
Tag *findTag(const RiseFall *rf,
|
||||
const PathAnalysisPt *path_ap,
|
||||
const ClkInfo *tag_clk,
|
||||
bool is_clk,
|
||||
InputDelay *input_delay,
|
||||
bool is_segment_start,
|
||||
ExceptionStateSet *states,
|
||||
bool own_states);
|
||||
const PathAnalysisPt *path_ap,
|
||||
const ClkInfo *tag_clk,
|
||||
bool is_clk,
|
||||
InputDelay *input_delay,
|
||||
bool is_segment_start,
|
||||
ExceptionStateSet *states,
|
||||
bool own_states,
|
||||
TagSet *tag_cache);
|
||||
void reportTags() const;
|
||||
void reportClkInfos() const;
|
||||
const ClkInfo *findClkInfo(const ClockEdge *clk_edge,
|
||||
|
|
@ -515,19 +506,20 @@ protected:
|
|||
void findAllArrivals(bool thru_latches);
|
||||
void findArrivals1(Level level);
|
||||
Tag *mutateTag(Tag *from_tag,
|
||||
const Pin *from_pin,
|
||||
const RiseFall *from_rf,
|
||||
bool from_is_clk,
|
||||
const ClkInfo *from_clk_info,
|
||||
const Pin *to_pin,
|
||||
const RiseFall *to_rf,
|
||||
bool to_is_clk,
|
||||
bool to_is_reg_clk,
|
||||
bool to_is_segment_start,
|
||||
const ClkInfo *to_clk_info,
|
||||
InputDelay *to_input_delay,
|
||||
const MinMax *min_max,
|
||||
const PathAnalysisPt *path_ap);
|
||||
const Pin *from_pin,
|
||||
const RiseFall *from_rf,
|
||||
bool from_is_clk,
|
||||
const ClkInfo *from_clk_info,
|
||||
const Pin *to_pin,
|
||||
const RiseFall *to_rf,
|
||||
bool to_is_clk,
|
||||
bool to_is_reg_clk,
|
||||
bool to_is_segment_start,
|
||||
const ClkInfo *to_clk_info,
|
||||
InputDelay *to_input_delay,
|
||||
const MinMax *min_max,
|
||||
const PathAnalysisPt *path_ap,
|
||||
TagSet *tag_cache);
|
||||
ExceptionPath *exceptionTo(const Path *path,
|
||||
const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
|
|
@ -701,9 +693,11 @@ class PathVisitor : public VertexVisitor, public StaState
|
|||
{
|
||||
public:
|
||||
// Uses search->evalPred() for search predicate.
|
||||
explicit PathVisitor(const StaState *sta);
|
||||
PathVisitor(const StaState *sta);
|
||||
PathVisitor(SearchPred *pred,
|
||||
bool make_tag_cache,
|
||||
const StaState *sta);
|
||||
virtual ~PathVisitor();
|
||||
virtual void visitFaninPaths(Vertex *to_vertex);
|
||||
virtual void visitFanoutPaths(Vertex *from_vertex);
|
||||
|
||||
|
|
@ -752,6 +746,7 @@ protected:
|
|||
const MinMax *min_max,
|
||||
const PathAnalysisPt *path_ap) = 0;
|
||||
SearchPred *pred_;
|
||||
TagSet *tag_cache_;
|
||||
};
|
||||
|
||||
// Visitor called during forward search to record an
|
||||
|
|
@ -759,7 +754,7 @@ protected:
|
|||
class ArrivalVisitor : public PathVisitor
|
||||
{
|
||||
public:
|
||||
explicit ArrivalVisitor(const StaState *sta);
|
||||
ArrivalVisitor(const StaState *sta);
|
||||
virtual ~ArrivalVisitor();
|
||||
// Initialize the visitor.
|
||||
// Defaults pred to search->eval_pred_.
|
||||
|
|
@ -833,12 +828,14 @@ protected:
|
|||
class RequiredVisitor : public PathVisitor
|
||||
{
|
||||
public:
|
||||
explicit RequiredVisitor(const StaState *sta);
|
||||
RequiredVisitor(const StaState *sta);
|
||||
virtual ~RequiredVisitor();
|
||||
virtual VertexVisitor *copy() const;
|
||||
virtual void visit(Vertex *vertex);
|
||||
|
||||
protected:
|
||||
RequiredVisitor(bool make_tag_cache,
|
||||
const StaState *sta);
|
||||
// Return false to stop visiting.
|
||||
virtual bool visitFromToPath(const Pin *from_pin,
|
||||
Vertex *from_vertex,
|
||||
|
|
|
|||
|
|
@ -821,9 +821,12 @@ public:
|
|||
// Number of paths to report for
|
||||
// each endpoint.
|
||||
int endpoint_path_count,
|
||||
// endpoint_path_count paths report unique pins
|
||||
// without rise/fall variations.
|
||||
// endpoint_path_count paths report paths with
|
||||
// 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
|
||||
// returned path ends.
|
||||
float slack_min,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
falsePathPriority() + fromThruToPriority(nullptr, thrus, nullptr),
|
||||
nullptr)
|
||||
|
|
@ -1128,9 +1129,12 @@ ExceptionFromTo::deletePin(const Pin *pin,
|
|||
const Network *network)
|
||||
{
|
||||
if (pins_) {
|
||||
pins_->erase(pin);
|
||||
// Incrementally update hash.
|
||||
hash_ -= network->id(pin) * hash_pin;
|
||||
auto itr = pins_->find(pin);
|
||||
if (itr != pins_->end()) {
|
||||
pins_->erase(itr);
|
||||
// Incrementally update hash.
|
||||
hash_ -= network->id(pin) * hash_pin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1138,9 +1142,12 @@ void
|
|||
ExceptionFromTo::deleteClock(Clock *clk)
|
||||
{
|
||||
if (clks_) {
|
||||
clks_->erase(clk);
|
||||
// Incrementally update hash.
|
||||
hash_ -= clk->index() * hash_clk;
|
||||
auto itr = clks_->find(clk);
|
||||
if (itr != clks_->end()) {
|
||||
clks_->erase(itr);
|
||||
// Incrementally update hash.
|
||||
hash_ -= clk->index() * hash_clk;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1149,9 +1156,12 @@ ExceptionFromTo::deleteInstance(const Instance *inst,
|
|||
const Network *network)
|
||||
{
|
||||
if (insts_) {
|
||||
insts_->erase(inst);
|
||||
// Incrementally update hash.
|
||||
hash_ -= network->id(inst) * hash_inst;
|
||||
auto itr = insts_->find(inst);
|
||||
if (itr != insts_->end()) {
|
||||
insts_->erase(itr);
|
||||
// Incrementally update hash.
|
||||
hash_ -= network->id(inst) * hash_inst;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1782,9 +1792,12 @@ ExceptionThru::deletePin(const Pin *pin,
|
|||
const Network *network)
|
||||
{
|
||||
if (pins_) {
|
||||
pins_->erase(pin);
|
||||
// Incrementally update hash.
|
||||
hash_ -= network->id(pin) * hash_pin;
|
||||
auto itr = pins_->find(pin);
|
||||
if (itr != pins_->end()) {
|
||||
pins_->erase(itr);
|
||||
// Incrementally update hash.
|
||||
hash_ -= network->id(pin) * hash_pin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1793,9 +1806,12 @@ ExceptionThru::deleteNet(const Net *net,
|
|||
const Network *network)
|
||||
{
|
||||
if (nets_) {
|
||||
nets_->erase(net);
|
||||
// Incrementally update hash.
|
||||
hash_ -= network->id(net) * hash_net;
|
||||
auto itr = nets_->find(net);
|
||||
if (itr != nets_->end()) {
|
||||
nets_->erase(itr);
|
||||
// Incrementally update hash.
|
||||
hash_ -= network->id(net) * hash_net;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1804,9 +1820,12 @@ ExceptionThru::deleteInstance(const Instance *inst,
|
|||
const Network *network)
|
||||
{
|
||||
if (insts_) {
|
||||
insts_->erase(inst);
|
||||
// Incrementally update hash.
|
||||
hash_ -= network->id(inst) * hash_inst;
|
||||
auto itr = insts_->find(inst);
|
||||
if (itr != insts_->end()) {
|
||||
insts_->erase(itr);
|
||||
// Incrementally update hash.
|
||||
hash_ -= network->id(inst) * hash_inst;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4894,6 +4894,7 @@ Sdc::deleteExceptions()
|
|||
path_delay_internal_from_break_.clear();
|
||||
path_delay_internal_to_.clear();
|
||||
path_delay_internal_to_break_.clear();
|
||||
pin_exceptions_.deleteContentsClear();
|
||||
|
||||
deleteExceptionPtHashMapSets(exception_merge_hash_);
|
||||
exception_merge_hash_.clear();
|
||||
|
|
|
|||
|
|
@ -421,7 +421,8 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
|
|||
while (src_iter.hasNext()) {
|
||||
Path *src_path = src_iter.next();
|
||||
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_
|
||||
&& clk_set_.find(src_clk) != clk_set_.end()) {
|
||||
Corner *src_corner = src_path->pathAnalysisPt(this)->corner();
|
||||
|
|
|
|||
|
|
@ -716,7 +716,7 @@ Genclks::makeTag(const Clock *gclk,
|
|||
nullptr, insert, 0.0, nullptr,
|
||||
path_ap, nullptr);
|
||||
return search_->findTag(master_rf, path_ap, clk_info, false,
|
||||
nullptr, false, states, true);
|
||||
nullptr, false, states, true, nullptr);
|
||||
}
|
||||
|
||||
class GenClkArrivalSearchPred : public EvalPred
|
||||
|
|
|
|||
|
|
@ -395,7 +395,7 @@ Latches::latchOutArrival(const Path *data_path,
|
|||
en_clk_edge->transition(),
|
||||
MinMax::max(), false, states))
|
||||
q_tag = search_->findTag(q_rf, path_ap, q_clk_info, false,
|
||||
nullptr, false, states, true);
|
||||
nullptr, false, states, true, nullptr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ namespace sta {
|
|||
// after_div<--------+
|
||||
// |
|
||||
// <--...--before_div<--...--path<---path_end
|
||||
//
|
||||
class Diversion
|
||||
{
|
||||
public:
|
||||
|
|
@ -105,6 +106,7 @@ deleteDiversionPathEnd(Diversion *div)
|
|||
PathEnum::PathEnum(size_t group_path_count,
|
||||
size_t endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
bool cmp_slack,
|
||||
const StaState *sta) :
|
||||
StaState(sta),
|
||||
|
|
@ -112,6 +114,7 @@ PathEnum::PathEnum(size_t group_path_count,
|
|||
group_path_count_(group_path_count),
|
||||
endpoint_path_count_(endpoint_path_count),
|
||||
unique_pins_(unique_pins),
|
||||
unique_edges_(unique_edges),
|
||||
div_queue_(DiversionGreater(sta)),
|
||||
div_count_(0),
|
||||
inserts_pruned_(false),
|
||||
|
|
@ -230,6 +233,7 @@ PathEnum::reportDiversionPath(Diversion *div)
|
|||
////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef std::set<std::pair<const Vertex*, const TimingArc*>> VisitedFanins;
|
||||
typedef std::pair<const Vertex*, const RiseFall*> VertexEdge;
|
||||
|
||||
class PathEnumFaninVisitor : public PathVisitor
|
||||
{
|
||||
|
|
@ -237,6 +241,7 @@ public:
|
|||
PathEnumFaninVisitor(PathEnd *path_end,
|
||||
Path *before_div,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
PathEnum *path_enum);
|
||||
virtual VertexVisitor *copy() const override;
|
||||
void visitFaninPathsThru(Path *before_div,
|
||||
|
|
@ -271,6 +276,7 @@ private:
|
|||
const Pin *to_pin,
|
||||
Vertex *to_vertex) override;
|
||||
virtual void visit(Vertex *) override {} // Not used.
|
||||
void insertUniqueEdgeDiv(Diversion *div);
|
||||
void reportDiversion(const Edge *edge,
|
||||
const TimingArc *div_arc,
|
||||
Path *after_div);
|
||||
|
|
@ -278,6 +284,7 @@ private:
|
|||
PathEnd *path_end_;
|
||||
Path *before_div_;
|
||||
bool unique_pins_;
|
||||
bool unique_edges_;
|
||||
PathEnum *path_enum_;
|
||||
|
||||
Slack path_end_slack_;
|
||||
|
|
@ -289,16 +296,19 @@ private:
|
|||
Vertex *prev_vertex_;
|
||||
bool crpr_active_;
|
||||
VisitedFanins visited_fanins_;
|
||||
std::map<VertexEdge, Diversion*> unique_edge_divs_;
|
||||
};
|
||||
|
||||
PathEnumFaninVisitor::PathEnumFaninVisitor(PathEnd *path_end,
|
||||
Path *before_div,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
PathEnum *path_enum) :
|
||||
PathVisitor(path_enum),
|
||||
path_end_(path_end),
|
||||
before_div_(before_div),
|
||||
unique_pins_(unique_pins),
|
||||
unique_edges_(unique_edges),
|
||||
path_enum_(path_enum),
|
||||
|
||||
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
|
||||
PathEnumFaninVisitor::visitFaninPathsThru(Path *before_div,
|
||||
Vertex *prev_vertex,
|
||||
|
|
@ -324,7 +341,13 @@ PathEnumFaninVisitor::visitFaninPathsThru(Path *before_div,
|
|||
prev_arc_ = prev_arc;
|
||||
prev_vertex_ = prev_vertex;
|
||||
visited_fanins_.clear();
|
||||
unique_edge_divs_.clear();
|
||||
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
|
||||
|
|
@ -342,13 +365,15 @@ PathEnumFaninVisitor::visitEdge(const Pin *from_pin,
|
|||
VertexPathIterator from_iter(from_vertex, search_);
|
||||
while (from_iter.hasNext()) {
|
||||
Path *from_path = from_iter.next();
|
||||
// Filter paths by path ap.
|
||||
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_) {
|
||||
// Filter arcs by to edge.
|
||||
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))
|
||||
|
|
@ -366,13 +391,6 @@ PathEnumFaninVisitor::visitEdge(const Pin *from_pin,
|
|||
return true;
|
||||
}
|
||||
|
||||
VertexVisitor *
|
||||
PathEnumFaninVisitor::copy() const
|
||||
{
|
||||
return new PathEnumFaninVisitor(path_end_, before_div_, unique_pins_,
|
||||
path_enum_);
|
||||
}
|
||||
|
||||
bool
|
||||
PathEnumFaninVisitor::visitFromToPath(const Pin *,
|
||||
Vertex *from_vertex,
|
||||
|
|
@ -393,42 +411,49 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *,
|
|||
// These paths fanin to before_div_ so we know to_vertex matches.
|
||||
if ((!unique_pins_ || from_vertex != prev_vertex_)
|
||||
&& 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",
|
||||
from_path->to_string(this).c_str(),
|
||||
to_vertex->to_string(this).c_str(),
|
||||
to_rf->to_string().c_str(),
|
||||
delayAsString(search_->deratedDelay(from_vertex, arc, edge,
|
||||
false,path_ap), this));
|
||||
if (crpr_active_) {
|
||||
// Ingore paths that only differ by crpr from same vertex/edge.
|
||||
if (visited_fanins_.find({from_vertex, arc}) == visited_fanins_.end()) {
|
||||
PathEnd *div_end;
|
||||
Path *after_div_copy;
|
||||
// Make the diverted path end to check slack with from_path crpr.
|
||||
makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy);
|
||||
if (div_end) {
|
||||
reportDiversion(edge, arc, from_path);
|
||||
path_enum_->makeDiversion(div_end, after_div_copy);
|
||||
visited_fanins_.emplace(from_vertex, arc);
|
||||
}
|
||||
}
|
||||
else
|
||||
debugPrint(debug_, "path_enum", 3, " pruned %s %s",
|
||||
edge->to_string(this).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);
|
||||
}
|
||||
PathEnd *div_end;
|
||||
Path *after_div_copy;
|
||||
// Make the diverted path end to check slack with from_path crpr.
|
||||
makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy);
|
||||
reportDiversion(edge, arc, from_path);
|
||||
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);
|
||||
}
|
||||
else
|
||||
debugPrint(debug_, "path_enum", 3, " pruned %s %s",
|
||||
edge->to_string(this).c_str(),
|
||||
arc->to_string().c_str());
|
||||
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
|
||||
PathEnumFaninVisitor::makeDivertedPathEnd(Path *after_div,
|
||||
Edge *div_edge,
|
||||
|
|
@ -440,12 +465,8 @@ PathEnumFaninVisitor::makeDivertedPathEnd(Path *after_div,
|
|||
Path *div_path;
|
||||
path_enum_->makeDivertedPath(path_end_->path(), before_div_, after_div,
|
||||
div_edge, div_arc, div_path, after_div_copy);
|
||||
if (after_div_copy) {
|
||||
div_end = path_end_->copy();
|
||||
div_end->setPath(div_path);
|
||||
}
|
||||
else
|
||||
div_end = nullptr;
|
||||
div_end = path_end_->copy();
|
||||
div_end->setPath(div_path);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -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
|
||||
PathEnum::makeDiversion(PathEnd *div_end,
|
||||
Path *after_div_copy)
|
||||
PathEnum::insert(Diversion *div)
|
||||
{
|
||||
Diversion *div = new Diversion(div_end, after_div_copy);
|
||||
div_queue_.push(div);
|
||||
div_count_++;
|
||||
|
||||
if (div_queue_.size() > group_path_count_ * 2)
|
||||
// We have more potenial paths than we will need.
|
||||
pruneDiversionQueue();
|
||||
|
|
@ -550,7 +561,7 @@ PathEnum::divSlack(Path *before_div,
|
|||
}
|
||||
}
|
||||
else {
|
||||
report()->error(1370, "path diversion missing edge.");
|
||||
report_->error(1370, "path diversion missing edge.");
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
|
@ -564,7 +575,8 @@ PathEnum::makeDiversions(PathEnd *path_end,
|
|||
Path *path = before;
|
||||
Path *prev_path = path->prevPath();
|
||||
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) {
|
||||
// Fanin visitor does all the work.
|
||||
// While visiting the fanins the fanin_visitor finds the
|
||||
|
|
@ -686,7 +698,7 @@ PathEnum::updatePathHeadDelays(PathSeq &paths,
|
|||
tag->isClock(),
|
||||
tag->inputDelay(),
|
||||
tag->isSegmentStart(),
|
||||
tag->states(), false);
|
||||
tag->states(), false, nullptr);
|
||||
path->setTag(updated_tag);
|
||||
}
|
||||
debugPrint(debug_, "path_enum", 5, "update arrival %s %s %s -> %s",
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ public:
|
|||
PathEnum(size_t group_path_count,
|
||||
size_t endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
bool cmp_slack,
|
||||
const StaState *sta);
|
||||
// Insert path ends that are enumerated in slack/arrival order.
|
||||
|
|
@ -72,8 +73,7 @@ public:
|
|||
private:
|
||||
void makeDiversions(PathEnd *path_end,
|
||||
Path *before);
|
||||
void makeDiversion(PathEnd *div_end,
|
||||
Path *after_div_copy);
|
||||
void insert(Diversion *div);
|
||||
void makeDivertedPath(Path *path,
|
||||
Path *before_div,
|
||||
Path *after_div,
|
||||
|
|
@ -97,6 +97,7 @@ private:
|
|||
size_t group_path_count_;
|
||||
size_t endpoint_path_count_;
|
||||
bool unique_pins_;
|
||||
bool unique_edges_;
|
||||
DiversionQueue div_queue_;
|
||||
int div_count_;
|
||||
// Number of paths returned for each endpoint (limit to endpoint_path_count).
|
||||
|
|
|
|||
|
|
@ -53,12 +53,14 @@ PathGroup::makePathGroupSlack(const char *name,
|
|||
int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
const StaState *sta)
|
||||
{
|
||||
return new PathGroup(name, group_path_count, endpoint_path_count, unique_pins,
|
||||
slack_min, slack_max, true, MinMax::min(), sta);
|
||||
return new PathGroup(name, group_path_count, endpoint_path_count,
|
||||
unique_pins, unique_edges, slack_min, slack_max,
|
||||
true, MinMax::min(), sta);
|
||||
}
|
||||
|
||||
PathGroup *
|
||||
|
|
@ -66,17 +68,20 @@ PathGroup::makePathGroupArrival(const char *name,
|
|||
int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta)
|
||||
{
|
||||
return new PathGroup(name, group_path_count, endpoint_path_count, unique_pins,
|
||||
0.0, 0.0, false, min_max, sta);
|
||||
return new PathGroup(name, group_path_count, endpoint_path_count,
|
||||
unique_pins, unique_edges, 0.0, 0.0,
|
||||
false, min_max, sta);
|
||||
}
|
||||
|
||||
PathGroup::PathGroup(const char *name,
|
||||
size_t group_path_count,
|
||||
size_t endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
bool cmp_slack,
|
||||
|
|
@ -86,6 +91,7 @@ PathGroup::PathGroup(const char *name,
|
|||
group_path_count_(group_path_count),
|
||||
endpoint_path_count_(endpoint_path_count),
|
||||
unique_pins_(unique_pins),
|
||||
unique_edges_(unique_edges),
|
||||
slack_min_(slack_min),
|
||||
slack_max_(slack_max),
|
||||
min_max_(min_max),
|
||||
|
|
@ -252,6 +258,7 @@ const char *PathGroups::unconstrained_group_name_ = "unconstrained";
|
|||
PathGroups::PathGroups(int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
PathGroupNameSet *group_names,
|
||||
|
|
@ -267,14 +274,15 @@ PathGroups::PathGroups(int group_path_count,
|
|||
group_path_count_(group_path_count),
|
||||
endpoint_path_count_(endpoint_path_count),
|
||||
unique_pins_(unique_pins),
|
||||
unique_edges_(unique_edges),
|
||||
slack_min_(slack_min),
|
||||
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,
|
||||
setup, recovery, clk_gating_setup, unconstrained,
|
||||
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,
|
||||
hold, removal, clk_gating_hold, unconstrained,
|
||||
MinMax::min());
|
||||
|
|
@ -284,6 +292,7 @@ void
|
|||
PathGroups::makeGroups(int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
PathGroupNameSet *group_names,
|
||||
|
|
@ -301,6 +310,7 @@ PathGroups::makeGroups(int group_path_count,
|
|||
group_path_count,
|
||||
endpoint_path_count,
|
||||
unique_pins,
|
||||
unique_edges,
|
||||
slack_min, slack_max,
|
||||
this);
|
||||
named_map_[mm_index][name] = group;
|
||||
|
|
@ -314,6 +324,7 @@ PathGroups::makeGroups(int group_path_count,
|
|||
group_path_count,
|
||||
endpoint_path_count,
|
||||
unique_pins,
|
||||
unique_edges,
|
||||
slack_min, slack_max,
|
||||
this);
|
||||
clk_map_[mm_index][clk] = group;
|
||||
|
|
@ -327,6 +338,7 @@ PathGroups::makeGroups(int group_path_count,
|
|||
group_path_count,
|
||||
endpoint_path_count,
|
||||
unique_pins,
|
||||
unique_edges,
|
||||
slack_min, slack_max,
|
||||
this);
|
||||
else
|
||||
|
|
@ -338,6 +350,7 @@ PathGroups::makeGroups(int group_path_count,
|
|||
group_path_count,
|
||||
endpoint_path_count,
|
||||
unique_pins,
|
||||
unique_edges,
|
||||
slack_min, slack_max,
|
||||
this);
|
||||
else
|
||||
|
|
@ -349,6 +362,7 @@ PathGroups::makeGroups(int group_path_count,
|
|||
group_path_count,
|
||||
endpoint_path_count,
|
||||
unique_pins,
|
||||
unique_edges,
|
||||
slack_min, slack_max,
|
||||
this);
|
||||
else
|
||||
|
|
@ -359,7 +373,7 @@ PathGroups::makeGroups(int group_path_count,
|
|||
unconstrained_[mm_index] =
|
||||
PathGroup::makePathGroupArrival(unconstrained_group_name_,
|
||||
group_path_count, endpoint_path_count,
|
||||
unique_pins, min_max, this);
|
||||
unique_pins, unique_edges, min_max, this);
|
||||
else
|
||||
unconstrained_[mm_index] = nullptr;
|
||||
}
|
||||
|
|
@ -576,8 +590,8 @@ PathGroups::makePathEnds(ExceptionTo *to,
|
|||
bool sort_by_slack)
|
||||
{
|
||||
Stats stats(debug_, report_);
|
||||
makeGroupPathEnds(to, group_path_count_, endpoint_path_count_, unique_pins_,
|
||||
corner, min_max);
|
||||
makeGroupPathEnds(to, group_path_count_, endpoint_path_count_,
|
||||
unique_pins_, unique_edges_, corner, min_max);
|
||||
|
||||
PathEndSeq path_ends;
|
||||
pushGroupPathEnds(path_ends);
|
||||
|
|
@ -805,6 +819,7 @@ PathGroups::makeGroupPathEnds(ExceptionTo *to,
|
|||
int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
const Corner *corner,
|
||||
const MinMaxAll *min_max)
|
||||
{
|
||||
|
|
@ -822,27 +837,33 @@ PathGroups::makeGroupPathEnds(ExceptionTo *to,
|
|||
const char *name = name_group.first;
|
||||
PathGroup *group = findPathGroup(name, path_min_max);
|
||||
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()) {
|
||||
PathGroup *group = findPathGroup(clk, path_min_max);
|
||||
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];
|
||||
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];
|
||||
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];
|
||||
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];
|
||||
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 endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
bool cmp_slack)
|
||||
{
|
||||
// Insert the worst max_path path ends in the group into a path
|
||||
// enumerator.
|
||||
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();
|
||||
while (end_iter->hasNext()) {
|
||||
PathEnd *end = end_iter->next();
|
||||
|
|
|
|||
173
search/Search.cc
173
search/Search.cc
|
|
@ -147,7 +147,7 @@ DynLoopSrchPred::hasPendingLoopPaths(Edge *edge,
|
|||
PathAPIndex path_ap_index = from_tag->pathAPIndex();
|
||||
PathAnalysisPt *path_ap = corners->findPathAnalysisPt(path_ap_index);
|
||||
Tag *to_tag = search->thruTag(from_tag, edge, RiseFall::rise(),
|
||||
path_ap->pathMinMax(), path_ap);
|
||||
path_ap->pathMinMax(), path_ap, nullptr);
|
||||
if (to_tag
|
||||
&& (prev_tag_group == nullptr
|
||||
|| !prev_tag_group->hasTag(from_tag)))
|
||||
|
|
@ -450,6 +450,7 @@ Search::findPathEnds(ExceptionFrom *from,
|
|||
size_t group_path_count,
|
||||
size_t endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
bool sort_by_slack,
|
||||
|
|
@ -466,11 +467,15 @@ Search::findPathEnds(ExceptionFrom *from,
|
|||
recovery = removal = false;
|
||||
if (!variables_->gatedClkChecksEnabled())
|
||||
clk_gating_setup = clk_gating_hold = false;
|
||||
makePathGroups(group_path_count, endpoint_path_count, unique_pins,
|
||||
slack_min, slack_max,
|
||||
group_names, setup, hold,
|
||||
recovery, removal,
|
||||
clk_gating_setup, clk_gating_hold);
|
||||
path_groups_ = new PathGroups(group_path_count, endpoint_path_count,
|
||||
unique_pins, unique_edges,
|
||||
slack_min, slack_max,
|
||||
group_names,
|
||||
setup, hold,
|
||||
recovery, removal,
|
||||
clk_gating_setup, clk_gating_hold,
|
||||
unconstrained_paths_,
|
||||
this);
|
||||
ensureDownstreamClkPins();
|
||||
PathEndSeq path_ends = path_groups_->makePathEnds(to, unconstrained_paths_,
|
||||
corner, min_max,
|
||||
|
|
@ -1106,7 +1111,7 @@ Search::findArrivalsSeed()
|
|||
////////////////////////////////////////////////////////////////
|
||||
|
||||
ArrivalVisitor::ArrivalVisitor(const StaState *sta) :
|
||||
PathVisitor(nullptr, sta)
|
||||
PathVisitor(nullptr, false, sta)
|
||||
{
|
||||
init0();
|
||||
init(true);
|
||||
|
|
@ -1116,7 +1121,7 @@ ArrivalVisitor::ArrivalVisitor(const StaState *sta) :
|
|||
ArrivalVisitor::ArrivalVisitor(bool always_to_endpoints,
|
||||
SearchPred *pred,
|
||||
const StaState *sta) :
|
||||
PathVisitor(pred, sta)
|
||||
PathVisitor(pred, true, sta)
|
||||
{
|
||||
init0();
|
||||
init(always_to_endpoints, pred);
|
||||
|
|
@ -1619,7 +1624,8 @@ Search::seedClkArrival(const Pin *pin,
|
|||
// Only false_paths -from apply to clock tree pins.
|
||||
ExceptionStateSet *states = nullptr;
|
||||
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);
|
||||
tag_bldr->setArrival(tag, arrival);
|
||||
}
|
||||
|
|
@ -1657,7 +1663,8 @@ Search::clkDataTag(const Pin *pin,
|
|||
|| sdc_->isPropagatedClock(pin));
|
||||
const ClkInfo *clk_info = findClkInfo(clk_edge, pin, is_propagated,
|
||||
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
|
||||
return nullptr;
|
||||
|
|
@ -2018,7 +2025,7 @@ Search::inputDelayTag(const Pin *pin,
|
|||
false, nullptr, clk_insertion, clk_latency,
|
||||
clk_uncertainties, path_ap, nullptr);
|
||||
tag = findTag(rf, path_ap, clk_info, false, input_delay, is_segment_start,
|
||||
states, true);
|
||||
states, true, nullptr);
|
||||
}
|
||||
|
||||
if (tag) {
|
||||
|
|
@ -2026,7 +2033,7 @@ Search::inputDelayTag(const Pin *pin,
|
|||
// Check for state changes on existing tag exceptions (pending -thru pins).
|
||||
tag = mutateTag(tag, pin, rf, false, 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;
|
||||
}
|
||||
|
|
@ -2034,18 +2041,30 @@ Search::inputDelayTag(const Pin *pin,
|
|||
////////////////////////////////////////////////////////////////
|
||||
|
||||
PathVisitor::PathVisitor(const StaState *sta) :
|
||||
|
||||
StaState(sta),
|
||||
pred_(sta->search()->evalPred())
|
||||
pred_(sta->search()->evalPred()),
|
||||
tag_cache_( nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
PathVisitor::PathVisitor(SearchPred *pred,
|
||||
bool make_tag_cache,
|
||||
const 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
|
||||
PathVisitor::visitFaninPaths(Vertex *to_vertex)
|
||||
{
|
||||
|
|
@ -2233,8 +2252,8 @@ PathVisitor::visitFromPath(const Pin *from_pin,
|
|||
to_clk_info, to_pin, to_rf, min_max,
|
||||
path_ap);
|
||||
if (to_tag)
|
||||
to_tag = search_->thruTag(to_tag, edge, to_rf, min_max, path_ap);
|
||||
from_arrival = search_->clkPathArrival(from_path, from_clk_info,
|
||||
to_tag = search_->thruTag(to_tag, edge, to_rf, min_max, path_ap, tag_cache_);
|
||||
from_arrival = search_->clkPathArrival(from_path, from_clk_info,
|
||||
clk_edge, min_max, path_ap);
|
||||
to_arrival = from_arrival + arc_delay;
|
||||
}
|
||||
|
|
@ -2249,7 +2268,7 @@ PathVisitor::visitFromPath(const Pin *from_pin,
|
|||
latches_->latchOutArrival(from_path, arc, edge, path_ap,
|
||||
to_tag, arc_delay, to_arrival);
|
||||
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()) {
|
||||
|
|
@ -2288,7 +2307,7 @@ PathVisitor::visitFromPath(const Pin *from_pin,
|
|||
else {
|
||||
if (!(sdc_->isPathDelayInternalFromBreak(to_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);
|
||||
if (!delayInf(arc_delay))
|
||||
to_arrival = from_arrival + arc_delay;
|
||||
|
|
@ -2398,7 +2417,7 @@ Search::fromUnclkedInputTag(const Pin *pin,
|
|||
&& (!require_exception || states)) {
|
||||
const ClkInfo *clk_info = findClkInfo(nullptr, nullptr, false, 0.0, path_ap);
|
||||
return findTag(rf, path_ap, clk_info, false, nullptr,
|
||||
is_segment_start, states, true);
|
||||
is_segment_start, states, true, nullptr);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -2419,7 +2438,8 @@ Search::fromRegClkTag(const Pin *from_pin,
|
|||
min_max, states)) {
|
||||
// Hack for filter -from reg/Q.
|
||||
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
|
||||
return nullptr;
|
||||
|
|
@ -2450,10 +2470,11 @@ Search::clkInfoWithCrprClkPath(const ClkInfo *from_clk_info,
|
|||
// Return nullptr if the result tag completes a false path.
|
||||
Tag *
|
||||
Search::thruTag(Tag *from_tag,
|
||||
Edge *edge,
|
||||
const RiseFall *to_rf,
|
||||
const MinMax *min_max,
|
||||
const PathAnalysisPt *path_ap)
|
||||
Edge *edge,
|
||||
const RiseFall *to_rf,
|
||||
const MinMax *min_max,
|
||||
const PathAnalysisPt *path_ap,
|
||||
TagSet *tag_cache)
|
||||
{
|
||||
const Pin *from_pin = edge->from(graph_)->pin();
|
||||
Vertex *to_vertex = edge->to(graph_);
|
||||
|
|
@ -2462,9 +2483,10 @@ Search::thruTag(Tag *from_tag,
|
|||
const ClkInfo *from_clk_info = from_tag->clkInfo();
|
||||
bool to_is_reg_clk = to_vertex->isRegClk();
|
||||
Tag *to_tag = mutateTag(from_tag, from_pin, from_rf, false, from_clk_info,
|
||||
to_pin, to_rf, false, to_is_reg_clk, false,
|
||||
// input delay is not propagated.
|
||||
from_clk_info, nullptr, min_max, path_ap);
|
||||
to_pin, to_rf, false, to_is_reg_clk, false,
|
||||
// input delay is not propagated.
|
||||
from_clk_info, nullptr, min_max, path_ap,
|
||||
tag_cache);
|
||||
return to_tag;
|
||||
}
|
||||
|
||||
|
|
@ -2498,7 +2520,7 @@ Search::thruClkTag(Path *from_path,
|
|||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -2617,19 +2639,20 @@ Search::thruClkInfo(Path *from_path,
|
|||
// Find the tag for a path going from from_tag thru edge to to_pin.
|
||||
Tag *
|
||||
Search::mutateTag(Tag *from_tag,
|
||||
const Pin *from_pin,
|
||||
const RiseFall *from_rf,
|
||||
bool from_is_clk,
|
||||
const ClkInfo *from_clk_info,
|
||||
const Pin *to_pin,
|
||||
const RiseFall *to_rf,
|
||||
bool to_is_clk,
|
||||
bool to_is_reg_clk,
|
||||
bool to_is_segment_start,
|
||||
const ClkInfo *to_clk_info,
|
||||
InputDelay *to_input_delay,
|
||||
const MinMax *min_max,
|
||||
const PathAnalysisPt *path_ap)
|
||||
const Pin *from_pin,
|
||||
const RiseFall *from_rf,
|
||||
bool from_is_clk,
|
||||
const ClkInfo *from_clk_info,
|
||||
const Pin *to_pin,
|
||||
const RiseFall *to_rf,
|
||||
bool to_is_clk,
|
||||
bool to_is_reg_clk,
|
||||
bool to_is_segment_start,
|
||||
const ClkInfo *to_clk_info,
|
||||
InputDelay *to_input_delay,
|
||||
const MinMax *min_max,
|
||||
const PathAnalysisPt *path_ap,
|
||||
TagSet *tag_cache)
|
||||
{
|
||||
ExceptionStateSet *new_states = nullptr;
|
||||
ExceptionStateSet *from_states = from_tag->states();
|
||||
|
|
@ -2713,8 +2736,8 @@ Search::mutateTag(Tag *from_tag,
|
|||
|
||||
if (new_states)
|
||||
return findTag(to_rf, path_ap, to_clk_info, to_is_clk,
|
||||
from_tag->inputDelay(), to_is_segment_start,
|
||||
new_states, true);
|
||||
from_tag->inputDelay(), to_is_segment_start, new_states,
|
||||
true, tag_cache);
|
||||
else {
|
||||
// No state change.
|
||||
if (to_clk_info == from_clk_info
|
||||
|
|
@ -2724,9 +2747,8 @@ Search::mutateTag(Tag *from_tag,
|
|||
&& from_tag->inputDelay() == to_input_delay)
|
||||
return from_tag;
|
||||
else
|
||||
return findTag(to_rf, path_ap, to_clk_info, to_is_clk,
|
||||
to_input_delay, to_is_segment_start,
|
||||
from_states, false);
|
||||
return findTag(to_rf, path_ap, to_clk_info, to_is_clk, to_input_delay,
|
||||
to_is_segment_start, from_states, false, tag_cache);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2972,16 +2994,22 @@ Search::tagCount() const
|
|||
|
||||
Tag *
|
||||
Search::findTag(const RiseFall *rf,
|
||||
const PathAnalysisPt *path_ap,
|
||||
const ClkInfo *clk_info,
|
||||
bool is_clk,
|
||||
InputDelay *input_delay,
|
||||
bool is_segment_start,
|
||||
ExceptionStateSet *states,
|
||||
bool own_states)
|
||||
const PathAnalysisPt *path_ap,
|
||||
const ClkInfo *clk_info,
|
||||
bool is_clk,
|
||||
InputDelay *input_delay,
|
||||
bool is_segment_start,
|
||||
ExceptionStateSet *states,
|
||||
bool own_states,
|
||||
TagSet *tag_cache)
|
||||
{
|
||||
Tag probe(0, rf->index(), path_ap->index(), clk_info, is_clk, input_delay,
|
||||
is_segment_start, states, false, this);
|
||||
if (tag_cache) {
|
||||
Tag *tag = tag_cache->findKey(&probe);
|
||||
if (tag)
|
||||
return tag;
|
||||
}
|
||||
LockGuard lock(tag_lock_);
|
||||
Tag *tag = tag_set_->findKey(&probe);
|
||||
if (tag == nullptr) {
|
||||
|
|
@ -3019,6 +3047,10 @@ Search::findTag(const RiseFall *rf,
|
|||
}
|
||||
if (own_states)
|
||||
delete states;
|
||||
|
||||
if (tag_cache)
|
||||
tag_cache->insert(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()
|
||||
{
|
||||
delete required_cmp_;
|
||||
|
|
@ -3540,7 +3580,7 @@ RequiredVisitor::~RequiredVisitor()
|
|||
VertexVisitor *
|
||||
RequiredVisitor::copy() const
|
||||
{
|
||||
return new RequiredVisitor(this);
|
||||
return new RequiredVisitor(true, this);
|
||||
}
|
||||
|
||||
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
|
||||
Search::deletePathGroups()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -372,6 +372,7 @@ find_path_ends(ExceptionFrom *from,
|
|||
int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
bool sort_by_slack,
|
||||
|
|
@ -387,7 +388,7 @@ find_path_ends(ExceptionFrom *from,
|
|||
PathEndSeq ends = sta->findPathEnds(from, thrus, to, unconstrained,
|
||||
corner, delay_min_max,
|
||||
group_path_count, endpoint_path_count,
|
||||
unique_pins,
|
||||
unique_pins, unique_edges,
|
||||
slack_min, slack_max,
|
||||
sort_by_slack,
|
||||
groups->size() ? groups : nullptr,
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ define_cmd_args "find_timing_paths" \
|
|||
[-group_path_count path_count] \
|
||||
[-endpoint_path_count path_count]\
|
||||
[-unique_paths_to_endpoint]\
|
||||
[-unique_edges_to_endpoint]\
|
||||
[-slack_max slack_max]\
|
||||
[-slack_min slack_min]\
|
||||
[-sort_by_slack]\
|
||||
|
|
@ -121,7 +122,9 @@ proc find_timing_paths_cmd { cmd args_var } {
|
|||
-path_delay -corner -group_count -endpoint_count \
|
||||
-group_path_count -endpoint_path_count \
|
||||
-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 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_edges [info exists flags(-unique_edges_to_endpoint)]
|
||||
|
||||
set slack_min "-1e+30"
|
||||
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 \
|
||||
$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 \
|
||||
$sort_by_slack $groups \
|
||||
1 1 1 1 1 1]
|
||||
|
|
@ -574,7 +579,7 @@ proc_redirect report_check_types {
|
|||
set slack_max $sta::float_inf
|
||||
}
|
||||
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 \
|
||||
0 {} \
|
||||
$setup $hold \
|
||||
|
|
|
|||
|
|
@ -2464,6 +2464,7 @@ Sta::findPathEnds(ExceptionFrom *from,
|
|||
int group_path_count,
|
||||
int endpoint_path_count,
|
||||
bool unique_pins,
|
||||
bool unique_edges,
|
||||
float slack_min,
|
||||
float slack_max,
|
||||
bool sort_by_slack,
|
||||
|
|
@ -2477,8 +2478,10 @@ Sta::findPathEnds(ExceptionFrom *from,
|
|||
{
|
||||
searchPreamble();
|
||||
return search_->findPathEnds(from, thrus, to, unconstrained,
|
||||
corner, min_max, group_path_count, endpoint_path_count,
|
||||
unique_pins, slack_min, slack_max,
|
||||
corner, min_max, group_path_count,
|
||||
endpoint_path_count,
|
||||
unique_pins, unique_edges,
|
||||
slack_min, slack_max,
|
||||
sort_by_slack, group_names,
|
||||
setup, hold,
|
||||
recovery, removal,
|
||||
|
|
@ -2727,8 +2730,10 @@ Sta::findGroupPathPins(const char *group_path_name)
|
|||
nullptr, nullptr, nullptr, false,
|
||||
// corner, min_max,
|
||||
nullptr, MinMaxAll::max(),
|
||||
// group_path_count, endpoint_path_count, unique_pins
|
||||
1, 1, false,
|
||||
// group_path_count, endpoint_path_count
|
||||
1, 1,
|
||||
// unique_pins, unique_edges
|
||||
true, true,
|
||||
-INF, INF, // slack_min, slack_max,
|
||||
false, // sort_by_slack
|
||||
nullptr, // group_names
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
# Test get_* -filter
|
||||
|
||||
# Read in design and libraries
|
||||
# get_* -filter
|
||||
read_liberty asap7_small.lib.gz
|
||||
read_verilog reg1_asap7.v
|
||||
link_design top
|
||||
|
|
|
|||
Loading…
Reference in New Issue