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"
|
2021-12-10 02:19:26 +01:00
|
|
|
#include "UnorderedSet.hh"
|
2020-04-05 23:53:44 +02:00
|
|
|
#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;
|
2021-12-10 02:19:26 +01:00
|
|
|
typedef UnorderedSet<Tag*, TagHash, TagEqual> TagSet;
|
|
|
|
|
typedef UnorderedSet<TagGroup*, TagGroupHash, TagGroupEqual> TagGroupSet;
|
2018-09-28 17:54:21 +02:00
|
|
|
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);
|
2021-01-22 00:58:16 +01:00
|
|
|
bool arrivalsValid();
|
2018-09-28 17:54:21 +02:00
|
|
|
// 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_; }
|
2019-06-24 04:52:29 +02:00
|
|
|
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;
|
2020-09-26 23:21:45 +02:00
|
|
|
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.
|
2021-12-10 02:19:26 +01:00
|
|
|
TagSet *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_;
|
|
|
|
|
};
|
|
|
|
|
|
2019-06-24 04:52:29 +02:00
|
|
|
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
|