OpenSTA/include/sta/Search.hh

820 lines
26 KiB
C++
Raw Normal View History

2018-09-28 17:54:21 +02:00
// OpenSTA, Static Timing Analyzer
2020-03-07 03:50:37 +01:00
// Copyright (c) 2020, Parallax Software, Inc.
2018-09-28 17:54:21 +02:00
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
2020-02-16 01:13:16 +01:00
#pragma once
2018-09-28 17:54:21 +02:00
2019-03-13 01:25:53 +01:00
#include <mutex>
2020-04-05 20:35:51 +02:00
2020-04-05 23:53:44 +02:00
#include "MinMax.hh"
#include "HashSet.hh"
#include "Transition.hh"
#include "LibertyClass.hh"
#include "NetworkClass.hh"
#include "GraphClass.hh"
#include "Delay.hh"
#include "SdcClass.hh"
#include "StaState.hh"
#include "SearchClass.hh"
#include "SearchPred.hh"
#include "VertexVisitor.hh"
2018-09-28 17:54:21 +02:00
namespace sta {
class BfsFwdIterator;
class BfsBkwdIterator;
class SearchPred;
class SearchThru;
class ClkInfoLess;
class PathEndVisitor;
class ArrivalVisitor;
class RequiredVisitor;
class ClkPathIterator;
class EvalPred;
class TagGroup;
class TagGroupBldr;
class PathGroups;
class WorstSlacks;
class DcalcAnalysisPt;
class VisitPathEnds;
class GatedClk;
2018-12-11 19:47:04 +01:00
class CheckCrpr;
2018-09-28 17:54:21 +02:00
class Genclks;
class Corner;
typedef Set<ClkInfo*, ClkInfoLess> ClkInfoSet;
typedef HashSet<Tag*, TagHash, TagEqual> TagHashSet;
typedef HashSet<TagGroup*, TagGroupHash, TagGroupEqual> TagGroupSet;
typedef Map<Vertex*, Slack> VertexSlackMap;
2018-12-05 23:18:41 +01:00
typedef Vector<VertexSlackMap> VertexSlackMapSeq;
typedef Vector<WorstSlacks> WorstSlacksSeq;
2018-09-28 17:54:21 +02:00
class Search : public StaState
{
public:
explicit Search(StaState *sta);
virtual ~Search();
virtual void copyState(const StaState *sta);
// Reset to virgin state.
void clear();
2018-11-26 18:15:52 +01:00
// When enabled, non-critical path arrivals are pruned to improve
2019-03-17 23:45:59 +01:00
// run time and reduce memory.
2018-11-26 18:15:52 +01:00
bool crprPathPruningEnabled() const;
void setCrprpathPruningEnabled(bool enabled);
2019-03-17 23:45:59 +01:00
// When path pruning is enabled required times for non-critical paths
// that have been pruned require additional search. This option
// disables additional search to returns approximate required times.
bool crprApproxMissingRequireds() const;
void setCrprApproxMissingRequireds(bool enabled);
2019-01-06 01:09:27 +01:00
bool unconstrainedPaths() const { return unconstrained_paths_; }
2018-09-28 17:54:21 +02:00
// from/thrus/to are owned and deleted by Search.
2019-03-13 01:25:53 +01:00
// Use corner nullptr to report timing for all corners.
2018-09-28 17:54:21 +02:00
// Returned sequence is owned by the caller.
// PathEnds are owned by Search PathGroups and deleted on next call.
PathEndSeq *findPathEnds(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
2019-01-06 01:09:27 +01:00
bool unconstrained,
2018-09-28 17:54:21 +02:00
const Corner *corner,
const MinMaxAll *min_max,
2018-10-24 01:28:41 +02:00
int group_count,
int endpoint_count,
2018-09-28 17:54:21 +02:00
bool unique_pins,
float slack_min,
float slack_max,
bool sort_by_slack,
PathGroupNameSet *group_names,
bool setup,
bool hold,
bool recovery,
bool removal,
bool clk_gating_setup,
bool clk_gating_hold);
// Invalidate all arrival and required times.
void arrivalsInvalid();
// Invalidate vertex arrival time.
void arrivalInvalid(Vertex *vertex);
void arrivalInvalidDelete(Vertex *vertex);
void arrivalInvalid(const Pin *pin);
// Invalidate all required times.
void requiredsInvalid();
// Invalidate vertex required time.
void requiredInvalid(Vertex *vertex);
void requiredInvalid(Instance *inst);
void requiredInvalid(const Pin *pin);
// Vertex will be deleted.
void deleteVertexBefore(Vertex *vertex);
// Find all arrival times (propatating thru latches).
void findAllArrivals();
// Find all arrivals (without latch propagation).
void findArrivals();
virtual void findAllArrivals(VertexVisitor *visitor);
// Find arrival times up thru level.
void findArrivals(Level level);
void findRequireds();
// Find required times down thru level.
void findRequireds(Level level);
bool requiredsSeeded() const { return requireds_seeded_; }
bool requiredsExist() const { return requireds_exist_; }
2018-12-05 23:18:41 +01:00
// The sum of all negative endpoints slacks.
// Incrementally updated.
2018-09-28 17:54:21 +02:00
Slack totalNegativeSlack(const MinMax *min_max);
2018-12-05 23:18:41 +01:00
Slack totalNegativeSlack(const Corner *corner,
const MinMax *min_max);
// Worst endpoint slack and vertex.
// Incrementally updated.
void worstSlack(const MinMax *min_max,
// Return values.
Slack &worst_slack,
Vertex *&worst_vertex);
void worstSlack(const Corner *corner,
const MinMax *min_max,
// Return values.
Slack &worst_slack,
Vertex *&worst_vertex);
2018-09-28 17:54:21 +02:00
// Clock arrival respecting ideal clock insertion delay and latency.
Arrival clkPathArrival(const Path *clk_path) const;
Arrival clkPathArrival(const Path *clk_path,
ClkInfo *clk_info,
ClockEdge *clk_edge,
const MinMax *min_max,
const PathAnalysisPt *path_ap) const;
// Clock arrival at the path source/launch point.
2018-11-26 18:15:52 +01:00
Arrival pathClkPathArrival(const Path *path) const;
2018-09-28 17:54:21 +02:00
PathGroup *pathGroup(const PathEnd *path_end) const;
void deletePathGroups();
virtual ExceptionPath *exceptionTo(ExceptionPathType type,
const Path *path,
const Pin *pin,
2019-11-11 23:30:19 +01:00
const RiseFall *rf,
2018-09-28 17:54:21 +02:00
const ClockEdge *clk_edge,
const MinMax *min_max,
bool match_min_max_exactly,
bool require_to_pin) const;
FilterPath *filter() const { return filter_; }
void deleteFilter();
void deleteFilteredArrivals();
// Endpoints are discovered during arrival search, so are only
// defined after findArrivals.
VertexSet *endpoints();
void endpointsInvalid();
// Clock tree vertices between the clock source pin and register clk pins.
// This does NOT include generated clock source paths.
bool isClock(const Vertex *vertex) const;
// Vertices on propagated generated clock source paths.
bool isGenClkSrc(const Vertex *vertex) const;
// The set of clocks that arrive at vertex.
void clocks(const Vertex *vertex,
// Return value.
ClockSet &clks) const;
void clocks(const Pin *pin,
// Return value.
ClockSet &clks) const;
void visitStartpoints(VertexVisitor *visitor);
void visitEndpoints(VertexVisitor *visitor);
bool havePathGroups() const;
PathGroup *findPathGroup(const char *name,
const MinMax *min_max) const;
PathGroup *findPathGroup(const Clock *clk,
const MinMax *min_max) const;
////////////////////////////////////////////////////////////////
//
// Somewhat protected functions.
//
////////////////////////////////////////////////////////////////
// Find arrivals for the clock tree.
void findClkArrivals();
void seedArrival(Vertex *vertex);
EvalPred *evalPred() const { return eval_pred_; }
SearchPred *searchAdj() const { return search_adj_; }
Tag *tag(TagIndex index) const;
TagIndex tagCount() const;
TagGroupIndex tagGroupCount() const;
void reportTagGroups() const;
void reportArrivalCountHistogram() const;
virtual int clkInfoCount() const;
virtual bool isEndpoint(Vertex *vertex) const;
virtual bool isEndpoint(Vertex *vertex,
SearchPred *pred) const;
void endpointInvalid(Vertex *vertex);
Tag *fromUnclkedInputTag(const Pin *pin,
2019-11-11 23:30:19 +01:00
const RiseFall *rf,
2018-09-28 17:54:21 +02:00
const MinMax *min_max,
const PathAnalysisPt *path_ap,
bool is_segment_start);
Tag *fromRegClkTag(const Pin *from_pin,
2019-11-11 23:30:19 +01:00
const RiseFall *from_rf,
2018-09-28 17:54:21 +02:00
Clock *clk,
2019-11-11 23:30:19 +01:00
const RiseFall *clk_rf,
2018-09-28 17:54:21 +02:00
ClkInfo *clk_info,
const Pin *to_pin,
2019-11-11 23:30:19 +01:00
const RiseFall *to_rf,
2018-09-28 17:54:21 +02:00
const MinMax *min_max,
const PathAnalysisPt *path_ap);
virtual Tag *thruTag(Tag *from_tag,
Edge *edge,
2019-11-11 23:30:19 +01:00
const RiseFall *to_rf,
2018-09-28 17:54:21 +02:00
const MinMax *min_max,
const PathAnalysisPt *path_ap);
virtual Tag *thruClkTag(PathVertex *from_path,
Tag *from_tag,
bool to_propagates_clk,
Edge *edge,
2019-11-11 23:30:19 +01:00
const RiseFall *to_rf,
2018-09-28 17:54:21 +02:00
const MinMax *min_max,
const PathAnalysisPt *path_ap);
ClkInfo *thruClkInfo(PathVertex *from_path,
ClkInfo *from_tag_clk,
Edge *edge,
Vertex *to_vertex,
const Pin *to_pin,
const MinMax *min_max,
const PathAnalysisPt *path_ap);
ClkInfo *clkInfoWithCrprClkPath(ClkInfo *from_clk_info,
PathVertex *from_path,
const PathAnalysisPt *path_ap);
void seedClkArrivals(const Pin *pin,
Vertex *vertex,
TagGroupBldr *tag_bldr);
void setVertexArrivals(Vertex *vertex,
TagGroupBldr *group_bldr);
void tnsInvalid(Vertex *vertex);
bool arrivalsChanged(Vertex *vertex,
TagGroupBldr *tag_bldr);
BfsFwdIterator *arrivalIterator() const { return arrival_iter_; }
BfsBkwdIterator *requiredIterator() const { return required_iter_; }
bool arrivalsAtEndpointsExist()const{return arrivals_at_endpoints_exist_;}
bool makeUnclkedPaths(Vertex *vertex,
bool is_segment_start,
TagGroupBldr *tag_bldr);
bool isSegmentStart(const Pin *pin);
bool isInputArrivalSrchStart(Vertex *vertex);
void seedInputSegmentArrival(const Pin *pin,
Vertex *vertex,
TagGroupBldr *tag_bldr);
void enqueueLatchDataOutputs(Vertex *vertex);
virtual void seedRequired(Vertex *vertex);
virtual void seedRequiredEnqueueFanin(Vertex *vertex);
void seedInputDelayArrival(const Pin *pin,
Vertex *vertex,
InputDelay *input_delay);
void seedInputDelayArrival(const Pin *pin,
Vertex *vertex,
InputDelay *input_delay,
bool is_segment_start,
TagGroupBldr *tag_bldr);
// Insertion delay for regular or generated clock.
Arrival clockInsertion(const Clock *clk,
const Pin *pin,
2019-11-11 23:30:19 +01:00
const RiseFall *rf,
2018-09-28 17:54:21 +02:00
const MinMax *min_max,
const EarlyLate *early_late,
const PathAnalysisPt *path_ap) const;
bool propagateClkSense(const Pin *from_pin,
Path *from_path,
2019-11-11 23:30:19 +01:00
const RiseFall *to_rf);
2018-09-28 17:54:21 +02:00
2019-11-11 23:30:19 +01:00
Tag *findTag(const RiseFall *rf,
2018-09-28 17:54:21 +02:00
const PathAnalysisPt *path_ap,
ClkInfo *tag_clk,
bool is_clk,
InputDelay *input_delay,
bool is_segment_start,
ExceptionStateSet *states,
2019-02-16 21:07:59 +01:00
bool own_states);
2018-09-28 17:54:21 +02:00
void reportTags() const;
void reportClkInfos() const;
virtual ClkInfo *findClkInfo(ClockEdge *clk_edge,
const Pin *clk_src,
bool is_propagated,
const Pin *gen_clk_src,
bool gen_clk_src_path,
2019-11-11 23:30:19 +01:00
const RiseFall *pulse_clk_sense,
2018-09-28 17:54:21 +02:00
Arrival insertion,
float latency,
ClockUncertainties *uncertainties,
const PathAnalysisPt *path_ap,
PathVertex *crpr_clk_path);
ClkInfo *findClkInfo(ClockEdge *clk_edge,
const Pin *clk_src,
bool is_propagated,
Arrival insertion,
const PathAnalysisPt *path_ap);
// Timing derated arc delay for a path analysis point.
ArcDelay deratedDelay(Vertex *from_vertex,
TimingArc *arc,
Edge *edge,
bool is_clk,
const PathAnalysisPt *path_ap);
TagGroup *tagGroup(const Vertex *vertex) const;
TagGroup *tagGroup(TagGroupIndex index) const;
void reportArrivals(Vertex *vertex) const;
Slack wnsSlack(Vertex *vertex,
2018-12-05 23:18:41 +01:00
PathAPIndex path_ap_index);
2018-09-28 17:54:21 +02:00
void levelChangedBefore(Vertex *vertex);
void seedInputArrival(const Pin *pin,
Vertex *vertex,
TagGroupBldr *tag_bldr);
void ensureDownstreamClkPins();
bool pathPropagatedToClkSrc(const Pin *pin,
Path *path);
// Check paths from inputs from the default arrival clock
// (missing set_input_delay).
virtual bool checkDefaultArrivalPaths() { return true; }
bool matchesFilter(Path *path,
const ClockEdge *to_clk_edge);
2018-12-11 19:47:04 +01:00
CheckCrpr *checkCrpr() { return check_crpr_; }
2018-09-28 17:54:21 +02:00
VisitPathEnds *visitPathEnds() { return visit_path_ends_; }
GatedClk *gatedClk() { return gated_clk_; }
Genclks *genclks() { return genclks_; }
void findClkVertexPins(PinSet &clk_pins);
2018-09-28 17:54:21 +02:00
protected:
void init(StaState *sta);
2019-03-17 23:45:59 +01:00
void initVars();
2018-09-28 17:54:21 +02:00
void makeAnalysisPts(AnalysisType analysis_type);
void makeAnalysisPts(bool swap_clk_min_max,
bool report_min,
bool report_max,
DcalcAnalysisPt *dcalc_ap_min,
DcalcAnalysisPt *dcalc_ap_max);
virtual void deleteTags();
void seedInvalidArrivals();
void seedArrivals();
void findClockVertices(VertexSet &vertices);
void seedClkDataArrival(const Pin *pin,
2019-11-11 23:30:19 +01:00
const RiseFall *rf,
2018-09-28 17:54:21 +02:00
Clock *clk,
ClockEdge *clk_edge,
const MinMax *min_max,
const PathAnalysisPt *path_ap,
Arrival insertion,
TagGroupBldr *tag_bldr);
void seedClkArrival(const Pin *pin,
2019-11-11 23:30:19 +01:00
const RiseFall *rf,
2018-09-28 17:54:21 +02:00
Clock *clk,
ClockEdge *clk_edge,
const MinMax *min_max,
const PathAnalysisPt *path_ap,
Arrival insertion,
TagGroupBldr *tag_bldr);
Tag *clkDataTag(const Pin *pin,
Clock *clk,
2019-11-11 23:30:19 +01:00
const RiseFall *rf,
2018-09-28 17:54:21 +02:00
ClockEdge *clk_edge,
Arrival insertion,
const MinMax *min_max,
const PathAnalysisPt *path_ap);
void findInputArrivalVertices(VertexSet &vertices);
void seedInputArrivals(ClockSet *clks);
void findRootVertices(VertexSet &vertices);
void findInputDrvrVertices(VertexSet &vertices);
void seedInputArrival1(const Pin *pin,
Vertex *vertex,
bool is_segment_start,
TagGroupBldr *tag_bldr);
void seedInputArrival(const Pin *pin,
Vertex *vertex,
ClockSet *wrt_clks);
void seedInputDelayArrival(const Pin *pin,
InputDelay *input_delay,
ClockEdge *clk_edge,
float clk_arrival,
float clk_insertion,
float clk_latency,
bool is_segment_start,
const MinMax *min_max,
PathAnalysisPt *path_ap,
TagGroupBldr *tag_bldr);
void seedInputDelayArrival(const Pin *pin,
2019-11-11 23:30:19 +01:00
const RiseFall *rf,
2018-09-28 17:54:21 +02:00
float arrival,
InputDelay *input_delay,
ClockEdge *clk_edge,
float clk_insertion,
float clk_latency,
bool is_segment_start,
const MinMax *min_max,
PathAnalysisPt *path_ap,
TagGroupBldr *tag_bldr);
void inputDelayClkArrival(InputDelay *input_delay,
ClockEdge *clk_edge,
const MinMax *min_max,
const PathAnalysisPt *path_ap,
// Return values.
float &clk_arrival,
float &clk_insertion,
float &clk_latency);
void inputDelayRefPinArrival(Path *ref_path,
ClockEdge *clk_edge,
const MinMax *min_max,
// Return values.
float &ref_arrival,
float &ref_insertion,
float &ref_latency);
Tag *inputDelayTag(const Pin *pin,
2019-11-11 23:30:19 +01:00
const RiseFall *rf,
2018-09-28 17:54:21 +02:00
ClockEdge *clk_edge,
float clk_insertion,
float clk_latency,
InputDelay *input_delay,
bool is_segment_start,
const MinMax *min_max,
const PathAnalysisPt *path_ap);
void seedClkVertexArrivals();
void seedClkVertexArrivals(const Pin *pin,
Vertex *vertex);
void findClkArrivals1();
virtual void findArrivals(Level level,
VertexVisitor *arrival_visitor);
Tag *mutateTag(Tag *from_tag,
const Pin *from_pin,
2019-11-11 23:30:19 +01:00
const RiseFall *from_rf,
2018-09-28 17:54:21 +02:00
bool from_is_clk,
ClkInfo *from_clk_info,
const Pin *to_pin,
2019-11-11 23:30:19 +01:00
const RiseFall *to_rf,
2018-09-28 17:54:21 +02:00
bool to_is_clk,
bool to_is_reg_clk,
bool to_is_segment_start,
ClkInfo *to_clk_info,
InputDelay *to_input_delay,
const MinMax *min_max,
const PathAnalysisPt *path_ap);
ExceptionPath *exceptionTo(const Path *path,
const Pin *pin,
2019-11-11 23:30:19 +01:00
const RiseFall *rf,
2018-09-28 17:54:21 +02:00
const ClockEdge *clk_edge,
const MinMax *min_max) const;
void seedRequireds();
void seedInvalidRequireds();
bool havePendingLatchOutputs();
void clearPendingLatchOutputs();
void enqueuePendingLatchOutputs();
void findFilteredArrivals();
void findArrivals1();
void seedFilterStarts();
bool hasEnabledChecks(Vertex *vertex) const;
virtual float timingDerate(Vertex *from_vertex,
TimingArc *arc,
Edge *edge,
bool is_clk,
const PathAnalysisPt *path_ap);
void deletePaths();
void deletePaths(Vertex *vertex);
TagGroup *findTagGroup(TagGroupBldr *group_bldr);
void deleteFilterTags();
void deleteFilterTagGroups();
void deleteFilterClkInfos();
2018-12-05 23:18:41 +01:00
void tnsPreamble();
2018-09-28 17:54:21 +02:00
void findTotalNegativeSlacks();
void updateInvalidTns();
void clearWorstSlack();
void wnsSlacks(Vertex *vertex,
// Return values.
2018-12-05 23:18:41 +01:00
SlackSeq &slacks);
2018-09-28 17:54:21 +02:00
void wnsTnsPreamble();
void worstSlackPreamble();
void deleteWorstSlacks();
void updateWorstSlacks(Vertex *vertex,
2018-12-05 23:18:41 +01:00
Slack slacks);
2018-09-28 17:54:21 +02:00
void updateTns(Vertex *vertex,
2018-12-05 23:18:41 +01:00
SlackSeq &slacks);
2018-09-28 17:54:21 +02:00
void tnsIncr(Vertex *vertex,
2018-12-05 23:18:41 +01:00
Slack slack,
PathAPIndex path_ap_index);
2018-09-28 17:54:21 +02:00
void tnsDecr(Vertex *vertex,
2018-12-05 23:18:41 +01:00
PathAPIndex path_ap_index);
2018-09-28 17:54:21 +02:00
void tnsNotifyBefore(Vertex *vertex);
2018-10-24 01:28:41 +02:00
PathGroups *makePathGroups(int group_count,
int endpoint_count,
2018-09-28 17:54:21 +02:00
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);
bool matchesFilterTo(Path *path,
const ClockEdge *to_clk_edge) const;
PathRef pathClkPathArrival1(const Path *path) const;
2018-09-28 17:54:21 +02:00
////////////////////////////////////////////////////////////////
2019-01-06 01:09:27 +01:00
// findPathEnds arg.
bool unconstrained_paths_;
2019-03-17 23:45:59 +01:00
bool crpr_path_pruning_enabled_;
bool crpr_approx_missing_requireds_;
2018-09-28 17:54:21 +02:00
// Search predicates.
SearchPred *search_adj_;
SearchPred *search_clk_;
EvalPred *eval_pred_;
ArrivalVisitor *arrival_visitor_;
// Clock arrivals are known.
bool clk_arrivals_valid_;
// Some arrivals exist.
bool arrivals_exist_;
// Arrivals at end points exist (but may be invalid).
bool arrivals_at_endpoints_exist_;
// Arrivals at start points have been initialized.
bool arrivals_seeded_;
// Some requireds exist.
bool requireds_exist_;
// Requireds have been seeded by searching arrivals to all endpoints.
bool requireds_seeded_;
// Vertices with invalid arrival times to update and search from.
VertexSet invalid_arrivals_;
2019-03-13 01:25:53 +01:00
std::mutex invalid_arrivals_lock_;
2018-09-28 17:54:21 +02:00
BfsFwdIterator *arrival_iter_;
// Vertices with invalid required times to update and search from.
VertexSet invalid_requireds_;
BfsBkwdIterator *required_iter_;
bool tns_exists_;
// Endpoint vertices with slacks that have changed since tns was found.
VertexSet invalid_tns_;
2018-12-05 23:18:41 +01:00
// Indexed by path_ap->index().
SlackSeq tns_;
// Indexed by path_ap->index().
VertexSlackMapSeq tns_slacks_;
2019-03-13 01:25:53 +01:00
std::mutex tns_lock_;
2018-12-05 23:18:41 +01:00
// Indexed by path_ap->index().
2018-09-28 17:54:21 +02:00
WorstSlacks *worst_slacks_;
// Use pointer to clk_info set so Tag.hh does not need to be included.
ClkInfoSet *clk_info_set_;
2019-03-13 01:25:53 +01:00
std::mutex clk_info_lock_;
2018-09-28 17:54:21 +02:00
// Use pointer to tag set so Tag.hh does not need to be included.
2019-02-16 21:07:59 +01:00
TagHashSet *tag_set_;
2018-09-28 17:54:21 +02:00
// Entries in tags_ may be missing where previous filter tags were deleted.
2019-02-16 21:07:59 +01:00
TagIndex tag_capacity_;
Tag **tags_;
2019-03-27 00:07:32 +01:00
TagIndex tag_next_;
2019-03-27 04:25:12 +01:00
// Holes in tags_ left by deleting filter tags.
std::vector<TagIndex> tag_free_indices_;
2019-03-13 01:25:53 +01:00
std::mutex tag_lock_;
2019-02-16 21:07:59 +01:00
TagGroupSet *tag_group_set_;
TagGroup **tag_groups_;
2019-03-27 00:07:32 +01:00
TagGroupIndex tag_group_next_;
2019-03-27 04:25:12 +01:00
// Holes in tag_groups_ left by deleting filter tag groups.
std::vector<TagIndex> tag_group_free_indices_;
2018-09-28 17:54:21 +02:00
// Capacity of tag_groups_.
2019-02-16 21:07:59 +01:00
TagGroupIndex tag_group_capacity_;
2019-03-13 01:25:53 +01:00
std::mutex tag_group_lock_;
2018-09-28 17:54:21 +02:00
// Latches data outputs to queue on the next search pass.
VertexSet pending_latch_outputs_;
2019-03-13 01:25:53 +01:00
std::mutex pending_latch_outputs_lock_;
2018-09-28 17:54:21 +02:00
VertexSet *endpoints_;
VertexSet *invalid_endpoints_;
// Filter exception to tag arrivals for
// report_timing -from pin|inst -through.
2019-03-13 01:25:53 +01:00
// -to is always nullptr.
2018-09-28 17:54:21 +02:00
FilterPath *filter_;
// filter_from_ is owned by filter_ if it exists.
ExceptionFrom *filter_from_;
ExceptionTo *filter_to_;
bool found_downstream_clk_pins_;
PathGroups *path_groups_;
VisitPathEnds *visit_path_ends_;
GatedClk *gated_clk_;
2018-12-11 19:47:04 +01:00
CheckCrpr *check_crpr_;
2018-09-28 17:54:21 +02:00
Genclks *genclks_;
};
// Eval across latch D->Q edges.
// SearchPred0 unless
// timing check edge
// disabled loop
// disabled converging clock edge (Xilinx)
// clk source pin
class EvalPred : public SearchPred0
{
public:
explicit EvalPred(const StaState *sta);
virtual bool searchThru(Edge *edge);
void setSearchThruLatches(bool thru_latches);
virtual bool searchTo(const Vertex *to_vertex);
protected:
bool search_thru_latches_;
};
class ClkArrivalSearchPred : public EvalPred
{
public:
ClkArrivalSearchPred(const StaState *sta);
virtual bool searchThru(Edge *edge);
private:
DISALLOW_COPY_AND_ASSIGN(ClkArrivalSearchPred);
};
2018-09-28 17:54:21 +02:00
// Class for visiting fanin/fanout paths of a vertex.
// This used by forward/backward search to find arrival/required path times.
class PathVisitor : public VertexVisitor
{
public:
// Uses search->evalPred() for search predicate.
explicit PathVisitor(const StaState *sta);
PathVisitor(SearchPred *pred,
const StaState *sta);
virtual void visitFaninPaths(Vertex *to_vertex);
virtual void visitFanoutPaths(Vertex *from_vertex);
protected:
// Return false to stop visiting.
virtual bool visitEdge(const Pin *from_pin, Vertex *from_vertex,
Edge *edge, const Pin *to_pin, Vertex *to_vertex);
// Return false to stop visiting.
bool visitArc(const Pin *from_pin,
Vertex *from_vertex,
2019-11-11 23:30:19 +01:00
const RiseFall *from_rf,
2018-09-28 17:54:21 +02:00
PathVertex *from_path,
Edge *edge,
TimingArc *arc,
const Pin *to_pin,
Vertex *to_vertex,
const MinMax *min_max,
PathAnalysisPt *path_ap);
// This calls visit below with everything required to make to_path.
// Return false to stop visiting.
virtual bool visitFromPath(const Pin *from_pin,
Vertex *from_vertex,
2019-11-11 23:30:19 +01:00
const RiseFall *from_rf,
2018-09-28 17:54:21 +02:00
PathVertex *from_path,
Edge *edge,
TimingArc *arc,
const Pin *to_pin,
Vertex *to_vertex,
2019-11-11 23:30:19 +01:00
const RiseFall *to_rf,
2018-09-28 17:54:21 +02:00
const MinMax *min_max,
const PathAnalysisPt *path_ap);
// Return false to stop visiting.
virtual bool visitFromToPath(const Pin *from_pin,
Vertex *from_vertex,
2019-11-11 23:30:19 +01:00
const RiseFall *from_rf,
2018-09-28 17:54:21 +02:00
Tag *from_tag,
PathVertex *from_path,
Edge *edge,
TimingArc *arc,
ArcDelay arc_delay,
Vertex *to_vertex,
2019-11-11 23:30:19 +01:00
const RiseFall *to_rf,
2018-09-28 17:54:21 +02:00
Tag *to_tag,
Arrival &to_arrival,
const MinMax *min_max,
const PathAnalysisPt *path_ap) = 0;
SearchPred *pred_;
const StaState *sta_;
};
// Visitor called during forward search to record an
// arrival at an path.
class ArrivalVisitor : public PathVisitor
{
public:
explicit ArrivalVisitor(const StaState *sta);
virtual ~ArrivalVisitor();
// Initialize the visitor.
// Defaults pred to search->eval_pred_.
void init(bool always_to_endpoints);
void init(bool always_to_endpoints,
SearchPred *pred);
virtual void visit(Vertex *vertex);
virtual VertexVisitor *copy();
// Return false to stop visiting.
virtual bool visitFromToPath(const Pin *from_pin,
Vertex *from_vertex,
2019-11-11 23:30:19 +01:00
const RiseFall *from_rf,
2018-09-28 17:54:21 +02:00
Tag *from_tag,
PathVertex *from_path,
Edge *edge,
TimingArc *arc,
ArcDelay arc_delay,
Vertex *to_vertex,
2019-11-11 23:30:19 +01:00
const RiseFall *to_rf,
2018-09-28 17:54:21 +02:00
Tag *to_tag,
Arrival &to_arrival,
const MinMax *min_max,
const PathAnalysisPt *path_ap);
void setAlwaysToEndpoints(bool to_endpoints);
TagGroupBldr *tagBldr() const { return tag_bldr_; }
protected:
ArrivalVisitor(bool always_to_endpoints,
SearchPred *pred,
const StaState *sta);
void init0();
void enqueueRefPinInputDelays(const Pin *ref_pin);
void seedInputDelayArrival(const Pin *pin,
Vertex *vertex,
InputDelay *input_delay);
void pruneCrprArrivals();
void constrainedRequiredsInvalid(Vertex *vertex,
bool is_clk);
bool always_to_endpoints_;
TagGroupBldr *tag_bldr_;
TagGroupBldr *tag_bldr_no_crpr_;
SearchPred *adj_pred_;
bool crpr_active_;
bool has_fanin_one_;
};
class RequiredCmp
{
public:
RequiredCmp();
void requiredsInit(Vertex *vertex,
const StaState *sta);
void requiredSet(int arrival_index,
Required required,
2020-07-12 02:43:30 +02:00
const MinMax *min_max,
const StaState *sta);
2018-09-28 17:54:21 +02:00
// Return true if the requireds changed.
bool requiredsSave(Vertex *vertex,
const StaState *sta);
Required required(int arrival_index);
protected:
ArrivalSeq requireds_;
bool have_requireds_;
};
// Visitor called during backward search to record a
// required time at an path.
class RequiredVisitor : public PathVisitor
{
public:
explicit RequiredVisitor(const StaState *sta);
virtual ~RequiredVisitor();
virtual VertexVisitor *copy();
virtual void visit(Vertex *vertex);
protected:
// Return false to stop visiting.
virtual bool visitFromToPath(const Pin *from_pin,
Vertex *from_vertex,
2019-11-11 23:30:19 +01:00
const RiseFall *from_rf,
2018-09-28 17:54:21 +02:00
Tag *from_tag,
PathVertex *from_path,
Edge *edge,
TimingArc *arc,
ArcDelay arc_delay,
Vertex *to_vertex,
2019-11-11 23:30:19 +01:00
const RiseFall *to_rf,
2018-09-28 17:54:21 +02:00
Tag *to_tag,
Arrival &to_arrival,
const MinMax *min_max,
const PathAnalysisPt *path_ap);
RequiredCmp *required_cmp_;
VisitPathEnds *visit_path_ends_;
};
// This does not use SearchPred as a base class to avoid getting
// two sets of StaState variables when multiple inheritance is used
// to add the functions in this class to another.
class DynLoopSrchPred
{
public:
explicit DynLoopSrchPred(TagGroupBldr *tag_bldr);
protected:
bool loopEnabled(Edge *edge,
const Sdc *sdc,
const Graph *graph,
Search *search);
bool hasPendingLoopPaths(Edge *edge,
const Graph *graph,
Search *search);
TagGroupBldr *tag_bldr_;
private:
DISALLOW_COPY_AND_ASSIGN(DynLoopSrchPred);
};
} // namespace