Files
OpenSTA/include/sta/Search.hh
T

868 lines
33 KiB
C++
Raw Normal View History

2025-03-26 18:21:03 -07:00
// opensta, Static Timing Analyzer
2026-03-10 13:21:17 -07:00
// Copyright (c) 2026, Parallax Software, Inc.
2018-09-28 08:54:21 -07: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
2022-01-04 10:17:08 -07:00
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2018-09-28 08:54:21 -07:00
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
2022-01-04 10:17:08 -07:00
// along with this program. If not, see <https://www.gnu.org/licenses/>.
2025-01-21 18:54:33 -07:00
//
// The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software.
//
// Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// This notice may not be removed or altered from any source distribution.
2018-09-28 08:54:21 -07:00
2020-02-15 17:13:16 -07:00
#pragma once
2018-09-28 08:54:21 -07:00
2025-01-30 08:44:04 -07:00
#include <atomic>
2026-04-15 09:38:10 -07:00
#include <mutex>
2026-01-03 16:59:35 -08:00
#include <unordered_set>
2020-04-05 11:35:51 -07:00
2026-04-15 09:38:10 -07:00
#include "Delay.hh"
#include "GraphClass.hh"
2020-04-05 14:53:44 -07:00
#include "LibertyClass.hh"
2026-04-15 09:38:10 -07:00
#include "MinMax.hh"
2020-04-05 14:53:44 -07:00
#include "NetworkClass.hh"
2026-04-15 09:38:10 -07:00
#include "Path.hh"
2020-04-05 14:53:44 -07:00
#include "SdcClass.hh"
#include "SearchClass.hh"
#include "SearchPred.hh"
2026-04-15 09:38:10 -07:00
#include "StaState.hh"
2026-02-28 15:53:23 -08:00
#include "StringUtil.hh"
2026-04-15 09:38:10 -07:00
#include "Transition.hh"
#include "VertexVisitor.hh"
2018-09-28 08:54:21 -07:00
namespace sta {
class BfsFwdIterator;
class BfsBkwdIterator;
class SearchPred;
class SearchThru;
2026-01-03 16:59:35 -08:00
class SearchAdj;
2018-09-28 08:54:21 -07:00
class ClkInfoLess;
class PathEndVisitor;
class ArrivalVisitor;
class RequiredVisitor;
class ClkPathIterator;
class EvalPred;
class TagGroup;
class TagGroupBldr;
class WorstSlacks;
class VisitPathEnds;
class GatedClk;
2018-12-11 10:47:04 -08:00
class CheckCrpr;
2026-01-03 16:59:35 -08:00
class Scene;
using ClkInfoSet = std::set<const ClkInfo*, ClkInfoLess>;
using TagSet = std::unordered_set<Tag*, TagHash, TagEqual>;
using TagGroupSet = std::unordered_set<TagGroup*, TagGroupHash, TagGroupEqual>;
using VertexSlackMap = std::map<Vertex*, Slack>;
using VertexSlackMapSeq = std::vector<VertexSlackMap>;
using WorstSlacksSeq = std::vector<WorstSlacks>;
using DelayDblSeq = std::vector<DelayDbl>;
using ExceptionPathSeq = std::vector<ExceptionPath*>;
2018-09-28 08:54:21 -07:00
class Search : public StaState
{
public:
2026-01-03 16:59:35 -08:00
Search(StaState *sta);
2026-04-13 14:58:16 -07:00
~Search() override;
void copyState(const StaState *sta) override;
2018-09-28 08:54:21 -07:00
// Reset to virgin state.
void clear();
2018-11-26 09:15:52 -08:00
// When enabled, non-critical path arrivals are pruned to improve
2019-03-17 15:45:59 -07:00
// run time and reduce memory.
2026-01-03 16:59:35 -08:00
[[nodiscard]] bool crprPathPruningEnabled() const;
2018-11-26 09:15:52 -08:00
void setCrprpathPruningEnabled(bool enabled);
2019-03-17 15:45:59 -07: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.
2026-01-03 16:59:35 -08:00
[[nodiscard]] bool crprApproxMissingRequireds() const;
2019-03-17 15:45:59 -07:00
void setCrprApproxMissingRequireds(bool enabled);
2026-01-03 16:59:35 -08:00
[[nodiscard]] bool unconstrainedPaths() const { return unconstrained_paths_; }
2018-09-28 08:54:21 -07:00
// from/thrus/to are owned and deleted by Search.
2026-01-03 16:59:35 -08:00
// Use scene nullptr to report timing for all scenes.
// PathEnds are owned by Mode PathGroups and deleted on next call.
2023-01-20 11:19:39 -07:00
PathEndSeq findPathEnds(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
bool unconstrained,
2026-01-03 16:59:35 -08:00
const SceneSeq &scenes,
2023-01-20 11:19:39 -07:00
const MinMaxAll *min_max,
2026-03-09 10:15:53 -07:00
int group_path_count,
int endpoint_path_count,
2023-01-20 11:19:39 -07:00
bool unique_pins,
2025-11-04 12:30:55 -07:00
bool unique_edges,
2023-01-20 11:19:39 -07:00
float slack_min,
float slack_max,
bool sort_by_slack,
2026-03-08 15:51:50 -07:00
StringSeq &group_names,
2023-01-20 11:19:39 -07:00
bool setup,
bool hold,
bool recovery,
bool removal,
bool clk_gating_setup,
bool clk_gating_hold);
2026-01-03 16:59:35 -08:00
[[nodiscard]] bool arrivalsValid();
2018-09-28 08:54:21 -07:00
// Invalidate all arrival and required times.
void arrivalsInvalid();
// Invalidate vertex arrival time.
void arrivalInvalid(Vertex *vertex);
void arrivalInvalid(const Pin *pin);
// Invalidate all required times.
void requiredsInvalid();
// Invalidate vertex required time.
void requiredInvalid(Vertex *vertex);
2023-01-19 11:23:45 -07:00
void requiredInvalid(const Instance *inst);
2018-09-28 08:54:21 -07:00
void requiredInvalid(const Pin *pin);
// Vertex will be deleted.
void deleteVertexBefore(Vertex *vertex);
2025-03-26 18:21:03 -07:00
void deleteEdgeBefore(Edge *edge);
2018-09-28 08:54:21 -07:00
// Find all arrival times (propatating thru latches).
void findAllArrivals();
// Find all arrivals (without latch propagation).
void findArrivals();
// Find arrival times up thru level.
void findArrivals(Level level);
void findRequireds();
// Find required times down thru level.
void findRequireds(Level level);
2026-01-03 16:59:35 -08:00
[[nodiscard]] bool requiredsSeeded() const { return requireds_seeded_; }
[[nodiscard]] bool requiredsExist() const { return requireds_exist_; }
2018-12-05 14:18:41 -08:00
// The sum of all negative endpoints slacks.
// Incrementally updated.
2018-09-28 08:54:21 -07:00
Slack totalNegativeSlack(const MinMax *min_max);
2026-01-03 16:59:35 -08:00
Slack totalNegativeSlack(const Scene *scene,
const MinMax *min_max);
2018-12-05 14:18:41 -08:00
// Worst endpoint slack and vertex.
// Incrementally updated.
void worstSlack(const MinMax *min_max,
2026-01-03 16:59:35 -08:00
// Return values.
Slack &worst_slack,
Vertex *&worst_vertex);
void worstSlack(const Scene *scene,
const MinMax *min_max,
// Return values.
Slack &worst_slack,
Vertex *&worst_vertex);
2018-09-28 08:54:21 -07:00
// Clock arrival respecting ideal clock insertion delay and latency.
Arrival clkPathArrival(const Path *clk_path) const;
Arrival clkPathArrival(const Path *clk_path,
2026-01-03 16:59:35 -08:00
const ClkInfo *clk_info,
const ClockEdge *clk_edge,
const MinMax *min_max) const;
2018-09-28 08:54:21 -07:00
// Clock arrival at the path source/launch point.
2018-11-26 09:15:52 -08:00
Arrival pathClkPathArrival(const Path *path) const;
2018-09-28 08:54:21 -07:00
void deletePathGroups();
2026-01-03 16:59:35 -08:00
ExceptionPath *exceptionTo(ExceptionPathType type,
const Path *path,
const Pin *pin,
const RiseFall *rf,
const ClockEdge *clk_edge,
const MinMax *min_max,
bool match_min_max_exactly,
bool require_to_pin,
Sdc *sdc) const;
ExceptionPathSeq groupPathsTo(const PathEnd *path_end) const;
2018-09-28 08:54:21 -07:00
void deleteFilter();
void deleteFilteredArrivals();
2026-01-03 16:59:35 -08:00
VertexSet &endpoints();
2018-09-28 08:54:21 -07:00
void endpointsInvalid();
2023-04-09 22:22:39 -07:00
// The set of clocks that arrive at vertex in the clock network.
2026-01-03 16:59:35 -08:00
ClockSet clocks(const Pin *pin,
const Mode *mode) const;
ClockSet clocks(const Vertex *vertex,
const Mode *mode) const;
2023-04-09 22:22:39 -07:00
// Clock domains for a vertex.
2026-01-03 16:59:35 -08:00
ClockSet clockDomains(const Vertex *vertex,
const Mode *mode) const;
ClockSet clockDomains(const Pin *pin,
const Mode *mode) const;
2018-09-28 08:54:21 -07:00
////////////////////////////////////////////////////////////////
//
// Somewhat protected functions.
//
////////////////////////////////////////////////////////////////
// Find arrivals for the clock tree.
void findClkArrivals();
EvalPred *evalPred() const { return eval_pred_; }
2026-01-03 16:59:35 -08:00
SearchPred *searchAdj() const { return search_thru_; }
2018-09-28 08:54:21 -07:00
Tag *tag(TagIndex index) const;
TagIndex tagCount() const;
TagGroupIndex tagGroupCount() const;
void reportTagGroups() const;
2025-03-26 18:21:03 -07:00
void reportPathCountHistogram() const;
2026-01-03 16:59:35 -08:00
int clkInfoCount() const;
// Endpoint for any mode.
[[nodiscard]] bool isEndpoint(Vertex *vertex) const;
// Endpoint for one mode.
[[nodiscard]] bool isEndpoint(Vertex *vertex,
const Mode *mode) const;
[[nodiscard]] bool isEndpoint(Vertex *vertex,
const ModeSeq &modes) const;
[[nodiscard]] bool isEndpoint(Vertex *vertex,
SearchPred *pred,
const Mode *mode) const;
2018-09-28 08:54:21 -07:00
void endpointInvalid(Vertex *vertex);
Tag *fromUnclkedInputTag(const Pin *pin,
2026-01-03 16:59:35 -08:00
const RiseFall *rf,
const MinMax *min_max,
bool is_segment_start,
bool require_exception,
Scene *scene);
2018-09-28 08:54:21 -07:00
Tag *fromRegClkTag(const Pin *from_pin,
2026-01-03 16:59:35 -08:00
const RiseFall *from_rf,
const Clock *clk,
const RiseFall *clk_rf,
const ClkInfo *clk_info,
const Pin *to_pin,
const RiseFall *to_rf,
const MinMax *min_max,
Scene *scene);
2024-12-11 11:09:35 -08:00
Tag *thruTag(Tag *from_tag,
Edge *edge,
const RiseFall *to_rf,
2025-11-04 09:45:20 -07:00
TagSet *tag_cache);
2025-03-26 18:21:03 -07:00
Tag *thruClkTag(Path *from_path,
2025-03-17 14:58:15 -07:00
Vertex *from_vertex,
2024-12-11 11:09:35 -08:00
Tag *from_tag,
bool to_propagates_clk,
Edge *edge,
const RiseFall *to_rf,
bool arc_delay_min_max_eq,
2024-12-11 11:09:35 -08:00
const MinMax *min_max,
2026-01-03 16:59:35 -08:00
Scene *scene);
2025-09-16 15:30:16 -07:00
const ClkInfo *thruClkInfo(Path *from_path,
2026-01-03 16:59:35 -08:00
Vertex *from_vertex,
const ClkInfo *from_clk_info,
bool from_is_clk,
Edge *edge,
Vertex *to_vertex,
const Pin *to_pin,
bool to_is_clk,
bool arc_delay_min_max_eq,
const MinMax *min_max,
Scene *scene);
2025-09-16 15:30:16 -07:00
const ClkInfo *clkInfoWithCrprClkPath(const ClkInfo *from_clk_info,
2026-01-03 16:59:35 -08:00
Path *from_path);
2018-09-28 08:54:21 -07:00
void seedClkArrivals(const Pin *pin,
2026-01-03 16:59:35 -08:00
const Mode *mode,
TagGroupBldr *tag_bldr);
2018-09-28 08:54:21 -07:00
void setVertexArrivals(Vertex *vertex,
2026-04-13 14:58:16 -07:00
TagGroupBldr *tag_bldr);
2018-09-28 08:54:21 -07:00
void tnsInvalid(Vertex *vertex);
2026-01-03 16:59:35 -08:00
[[nodiscard]] bool arrivalsChanged(Vertex *vertex,
TagGroupBldr *tag_bldr);
2018-09-28 08:54:21 -07:00
BfsFwdIterator *arrivalIterator() const { return arrival_iter_; }
BfsBkwdIterator *requiredIterator() const { return required_iter_; }
2025-11-06 16:46:05 -07:00
// Used by OpenROAD.
2018-09-28 08:54:21 -07:00
bool makeUnclkedPaths(Vertex *vertex,
2026-01-03 16:59:35 -08:00
bool is_segment_start,
2022-08-10 15:43:11 -07:00
bool require_exception,
2026-01-03 16:59:35 -08:00
TagGroupBldr *tag_bldr,
const Mode *mode);
2022-08-10 15:43:11 -07:00
bool makeUnclkedPaths2(Vertex *vertex,
TagGroupBldr *tag_bldr);
2026-01-03 16:59:35 -08:00
[[nodiscard]] bool isInputArrivalSrchStart(Vertex *vertex);
2018-09-28 08:54:21 -07:00
void seedInputSegmentArrival(const Pin *pin,
2026-01-03 16:59:35 -08:00
Vertex *vertex,
const Mode *mode,
TagGroupBldr *tag_bldr);
2026-06-24 16:55:51 -07:00
void postponeLatchDataOutputs(Vertex *vertex);
void postponeArrivals(Vertex *vertex);
2026-01-03 16:59:35 -08:00
void enqueuePendingClkFanouts();
void postponeClkFanouts(Vertex *vertex);
void seedRequired(Vertex *vertex);
void seedRequiredEnqueueFanin(Vertex *vertex);
2018-09-28 08:54:21 -07:00
void seedInputDelayArrival(const Pin *pin,
2026-01-03 16:59:35 -08:00
Vertex *vertex,
InputDelay *input_delay,
const Mode *mode);
2018-09-28 08:54:21 -07:00
void seedInputDelayArrival(const Pin *pin,
2026-01-03 16:59:35 -08:00
Vertex *vertex,
InputDelay *input_delay,
bool is_segment_start,
const Mode *mode,
TagGroupBldr *tag_bldr);
2018-09-28 08:54:21 -07:00
// Insertion delay for regular or generated clock.
Arrival clockInsertion(const Clock *clk,
2026-01-03 16:59:35 -08:00
const Pin *pin,
const RiseFall *rf,
const MinMax *min_max,
const EarlyLate *early_late,
const Mode *mode) const;
[[nodiscard]] bool propagateClkSense(const Pin *from_pin,
Path *from_path,
const RiseFall *to_rf);
Tag *findTag(Scene *scene,
const RiseFall *rf,
const MinMax *min_max,
2026-04-13 14:58:16 -07:00
const ClkInfo *clk_info,
2025-11-03 18:53:17 -05:00
bool is_clk,
InputDelay *input_delay,
bool is_segment_start,
ExceptionStateSet *states,
bool own_states,
2025-11-04 09:45:20 -07:00
TagSet *tag_cache);
2018-09-28 08:54:21 -07:00
void reportTags() const;
void reportClkInfos() const;
2026-01-03 16:59:35 -08:00
const ClkInfo *findClkInfo(Scene *scene,
const ClockEdge *clk_edge,
const Pin *clk_src,
bool is_propagated,
const Pin *gen_clk_src,
bool gen_clk_src_path,
const RiseFall *pulse_clk_sense,
Arrival insertion,
float latency,
const ClockUncertainties *uncertainties,
const MinMax *min_max,
Path *crpr_clk_path);
const ClkInfo *findClkInfo(Scene *scene,
const ClockEdge *clk_edge,
const Pin *clk_src,
bool is_propagated,
Arrival insertion,
const MinMax *min_max);
2018-09-28 08:54:21 -07:00
// Timing derated arc delay for a path analysis point.
2025-02-01 14:53:28 -08:00
ArcDelay deratedDelay(const Vertex *from_vertex,
2026-01-03 16:59:35 -08:00
const TimingArc *arc,
const Edge *edge,
bool is_clk,
const MinMax *min_max,
DcalcAPIndex dcalc_ap,
const Sdc *sdc);
2018-09-28 08:54:21 -07:00
TagGroup *tagGroup(const Vertex *vertex) const;
TagGroup *tagGroup(TagGroupIndex index) const;
2025-09-03 15:05:14 -07:00
void reportArrivals(Vertex *vertex,
2026-05-28 12:43:10 -07:00
bool report_tag_index,
int digits) const;
2018-09-28 08:54:21 -07:00
Slack wnsSlack(Vertex *vertex,
2026-01-03 16:59:35 -08:00
PathAPIndex path_ap_index);
void levelsChangedBefore();
2018-09-28 08:54:21 -07:00
void levelChangedBefore(Vertex *vertex);
void seedInputArrival(const Pin *pin,
2026-01-03 16:59:35 -08:00
Vertex *vertex,
const Mode *mode,
TagGroupBldr *tag_bldr);
2018-09-28 08:54:21 -07:00
void ensureDownstreamClkPins();
2026-01-03 16:59:35 -08:00
[[nodiscard]] bool matchesFilter(Path *path,
const ClockEdge *to_clk_edge);
2018-12-11 10:47:04 -08:00
CheckCrpr *checkCrpr() { return check_crpr_; }
2018-09-28 08:54:21 -07:00
VisitPathEnds *visitPathEnds() { return visit_path_ends_; }
GatedClk *gatedClk() { return gated_clk_; }
void findClkVertexPins(PinSet &clk_pins);
2022-06-10 09:39:49 -07:00
void findFilteredArrivals(ExceptionFrom *from,
ExceptionThruSeq *thrus,
ExceptionTo *to,
2023-04-07 18:33:24 -07:00
bool unconstrained,
bool thru_latches);
2023-04-07 18:47:01 -07:00
VertexSeq filteredEndpoints();
2025-03-26 18:21:03 -07:00
Arrival *arrivals(const Vertex *vertex) const;
Arrival *makeArrivals(const Vertex *vertex,
2026-01-03 16:59:35 -08:00
uint32_t count);
2025-03-26 18:21:03 -07:00
void deleteArrivals(const Vertex *vertex);
Required *requireds(const Vertex *vertex) const;
2026-01-03 16:59:35 -08:00
[[nodiscard]] bool hasRequireds(const Vertex *vertex) const;
2025-03-26 18:21:03 -07:00
Required *makeRequireds(const Vertex *vertex,
uint32_t count);
void deleteRequireds(const Vertex *vertex);
size_t arrivalCount() const;
size_t requiredCount() const;
Path *prevPaths(const Vertex *vertex) const;
Path *makePrevPaths(const Vertex *vertex,
uint32_t count);
void deletePrevPaths(Vertex *vertex);
2026-01-03 16:59:35 -08:00
[[nodiscard]] bool crprPathPruningDisabled(const Vertex *vertex) const;
2025-03-26 18:21:03 -07:00
void setCrprPathPruningDisabled(const Vertex *vertex,
bool disabled);
2026-01-03 16:59:35 -08:00
[[nodiscard]] bool bfsInQueue(const Vertex *vertex,
BfsIndex index) const;
2025-03-26 18:21:03 -07:00
void setBfsInQueue(const Vertex *vertex,
BfsIndex index,
bool value);
TagGroupIndex tagGroupIndex(const Vertex *vertex) const;
void setTagGroupIndex(const Vertex *vertex,
TagGroupIndex tag_index);
2025-07-02 08:32:04 -07:00
void checkPrevPaths() const;
void deletePaths(Vertex *vertex);
2025-09-03 15:05:14 -07:00
void deleteTagGroup(TagGroup *group);
2025-12-02 14:50:41 -08:00
void saveEnumPath(Path *path);
2026-01-03 16:59:35 -08:00
bool isSrchRoot(Vertex *vertex,
const Mode *mode) const;
2026-04-24 11:54:28 -07:00
DelaysWrtClks arrivalsWrtClks(Vertex *vertex,
const Scene *scene);
DelaysWrtClks delaysWrtClks(Vertex *vertex,
const Scene *scene,
const PathDelayFunc &get_path_delay);
2018-09-28 08:54:21 -07:00
protected:
2019-03-17 15:45:59 -07:00
void initVars();
2025-02-10 17:31:45 -07:00
void deleteTags();
void deleteTagsPrev();
2025-09-12 08:50:58 -07:00
void deleteUnusedTagGroups();
2018-09-28 08:54:21 -07:00
void seedInvalidArrivals();
void seedArrivals();
void findClockVertices(VertexSet &vertices);
void seedClkDataArrival(const Pin *pin,
2026-01-03 16:59:35 -08:00
const RiseFall *rf,
const Clock *clk,
const ClockEdge *clk_edge,
const MinMax *min_max,
Arrival insertion,
Scene *scene,
TagGroupBldr *tag_bldr);
2018-09-28 08:54:21 -07:00
void seedClkArrival(const Pin *pin,
2026-01-03 16:59:35 -08:00
const RiseFall *rf,
const Clock *clk,
const ClockEdge *clk_edge,
const MinMax *min_max,
Arrival insertion,
Scene *scene,
TagGroupBldr *tag_bldr);
2018-09-28 08:54:21 -07:00
Tag *clkDataTag(const Pin *pin,
2026-01-03 16:59:35 -08:00
const Clock *clk,
const RiseFall *rf,
const ClockEdge *clk_edge,
Arrival insertion,
const MinMax *min_max,
Scene *scene);
2018-09-28 08:54:21 -07:00
void findInputArrivalVertices(VertexSet &vertices);
void findRootVertices(VertexSet &vertices);
void findInputDrvrVertices(VertexSet &vertices);
void seedInputArrival1(const Pin *pin,
2026-01-03 16:59:35 -08:00
Vertex *vertex,
bool is_segment_start,
const Mode *mode,
TagGroupBldr *tag_bldr);
2018-09-28 08:54:21 -07:00
void seedInputArrival(const Pin *pin,
2026-01-03 16:59:35 -08:00
Vertex *vertex,
ClockSet *wrt_clks);
2018-09-28 08:54:21 -07:00
void seedInputDelayArrival(const Pin *pin,
2026-01-03 16:59:35 -08:00
InputDelay *input_delay,
const ClockEdge *clk_edge,
float clk_arrival,
float clk_insertion,
float clk_latency,
bool is_segment_start,
const MinMax *min_max,
Scene *scene,
TagGroupBldr *tag_bldr);
2018-09-28 08:54:21 -07:00
void seedInputDelayArrival(const Pin *pin,
2026-01-03 16:59:35 -08:00
const RiseFall *rf,
float arrival,
InputDelay *input_delay,
const ClockEdge *clk_edge,
float clk_insertion,
float clk_latency,
bool is_segment_start,
const MinMax *min_max,
Scene *scene,
TagGroupBldr *tag_bldr);
2018-09-28 08:54:21 -07:00
void inputDelayClkArrival(InputDelay *input_delay,
2026-01-03 16:59:35 -08:00
const ClockEdge *clk_edge,
const MinMax *min_max,
const Mode *mode,
// Return values.
float &clk_arrival,
float &clk_insertion,
float &clk_latency);
2018-09-28 08:54:21 -07:00
void inputDelayRefPinArrival(Path *ref_path,
2026-01-03 16:59:35 -08:00
const ClockEdge *clk_edge,
const MinMax *min_max,
const Sdc *sdc,
// Return values.
float &ref_arrival,
float &ref_insertion,
float &ref_latency);
2018-09-28 08:54:21 -07:00
Tag *inputDelayTag(const Pin *pin,
2026-01-03 16:59:35 -08:00
const RiseFall *rf,
const ClockEdge *clk_edge,
float clk_insertion,
float clk_latency,
InputDelay *input_delay,
bool is_segment_start,
const MinMax *min_max,
Scene *scene);
2018-09-28 08:54:21 -07:00
void seedClkVertexArrivals();
void findClkArrivals1();
2026-01-03 16:59:35 -08:00
void findAllArrivals(bool thru_latches,
bool clks_only);
2023-04-07 18:33:24 -07:00
void findArrivals1(Level level);
2018-09-28 08:54:21 -07:00
Tag *mutateTag(Tag *from_tag,
2025-11-03 18:53:17 -05:00
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,
2025-11-04 09:45:20 -07:00
TagSet *tag_cache);
2018-09-28 08:54:21 -07:00
ExceptionPath *exceptionTo(const Path *path,
2026-01-03 16:59:35 -08:00
const Pin *pin,
const RiseFall *rf,
const ClockEdge *clk_edge,
const MinMax *min_max) const;
2018-09-28 08:54:21 -07:00
void seedRequireds();
void seedInvalidRequireds();
2023-04-07 18:33:24 -07:00
void findFilteredArrivals(bool thru_latches);
void findArrivalsSeed();
2018-09-28 08:54:21 -07:00
void seedFilterStarts();
2026-01-03 16:59:35 -08:00
[[nodiscard]] bool hasEnabledChecks(Vertex *vertex,
const Mode *mode) const;
float timingDerate(const Vertex *from_vertex,
const TimingArc *arc,
const Edge *edge,
bool is_clk,
const Sdc *sdc,
const MinMax *min_max);
2018-09-28 08:54:21 -07:00
void deletePaths();
2024-10-04 17:12:45 -07:00
// Delete with incremental tns/wns update.
void deletePathsIncr(Vertex *vertex);
2026-04-13 14:58:16 -07:00
TagGroup *findTagGroup(TagGroupBldr *tag_bldr);
2018-09-28 08:54:21 -07:00
void deleteFilterTags();
void deleteFilterTagGroups();
void deleteFilterClkInfos();
2018-12-05 14:18:41 -08:00
void tnsPreamble();
2018-09-28 08:54:21 -07:00
void findTotalNegativeSlacks();
void updateInvalidTns();
void clearWorstSlack();
void wnsSlacks(Vertex *vertex,
2026-01-03 16:59:35 -08:00
// Return values.
SlackSeq &slacks);
2018-09-28 08:54:21 -07:00
void wnsTnsPreamble();
void worstSlackPreamble();
void deleteWorstSlacks();
void updateWorstSlacks(Vertex *vertex,
2026-01-03 16:59:35 -08:00
Slack slacks);
2018-09-28 08:54:21 -07:00
void updateTns(Vertex *vertex,
2026-01-03 16:59:35 -08:00
SlackSeq &slacks);
2018-09-28 08:54:21 -07:00
void tnsIncr(Vertex *vertex,
2026-01-03 16:59:35 -08:00
Slack slack,
PathAPIndex path_ap_index);
2018-09-28 08:54:21 -07:00
void tnsDecr(Vertex *vertex,
2026-01-03 16:59:35 -08:00
PathAPIndex path_ap_index);
2018-09-28 08:54:21 -07:00
void tnsNotifyBefore(Vertex *vertex);
2026-01-03 16:59:35 -08:00
[[nodiscard]] bool matchesFilterTo(Path *path,
const ClockEdge *to_clk_edge) const;
2025-03-26 18:21:03 -07:00
const Path *pathClkPathArrival1(const Path *path) const;
void deletePathsState(const Vertex *vertex) const;
2023-01-19 11:23:45 -07:00
void clocks(const Vertex *vertex,
2026-01-03 16:59:35 -08:00
const Mode *mode,
2023-01-19 11:23:45 -07:00
// Return value.
ClockSet &clks) const;
2023-04-09 22:22:39 -07:00
void clockDomains(const Vertex *vertex,
2026-01-03 16:59:35 -08:00
const Mode *mode,
2023-04-09 22:22:39 -07:00
// Return value.
ClockSet &clks) const;
2018-09-28 08:54:21 -07:00
////////////////////////////////////////////////////////////////
2019-01-05 16:09:27 -08:00
// findPathEnds arg.
2026-04-13 14:58:16 -07:00
bool unconstrained_paths_{false};
bool crpr_path_pruning_enabled_{true};
bool crpr_approx_missing_requireds_{true};
2026-01-03 16:59:35 -08:00
2018-09-28 08:54:21 -07:00
// Search predicates.
2026-01-03 16:59:35 -08:00
SearchPred *search_thru_;
2026-06-24 16:55:51 -07:00
SearchPred *search_adj_;
2018-09-28 08:54:21 -07:00
EvalPred *eval_pred_;
2026-01-03 16:59:35 -08:00
2018-09-28 08:54:21 -07:00
// Some arrivals exist.
2026-04-13 14:58:16 -07:00
bool arrivals_exist_{false};
2018-09-28 08:54:21 -07:00
// Arrivals at start points have been initialized.
2026-04-13 14:58:16 -07:00
bool arrivals_seeded_{false};
2026-01-03 16:59:35 -08:00
// Vertices with invalid arrival times to update and search from.
VertexSet invalid_arrivals_;
std::mutex invalid_arrivals_lock_;
BfsFwdIterator *arrival_iter_;
ArrivalVisitor *arrival_visitor_;
2018-09-28 08:54:21 -07:00
// Some requireds exist.
2026-04-13 14:58:16 -07:00
bool requireds_exist_{false};
2018-09-28 08:54:21 -07:00
// Requireds have been seeded by searching arrivals to all endpoints.
2026-04-13 14:58:16 -07:00
bool requireds_seeded_{false};
2018-09-28 08:54:21 -07:00
// Vertices with invalid required times to update and search from.
2026-01-03 16:59:35 -08:00
VertexSet invalid_requireds_;
2018-09-28 08:54:21 -07:00
BfsBkwdIterator *required_iter_;
2026-01-03 16:59:35 -08:00
2026-04-13 14:58:16 -07:00
bool tns_exists_{false};
2018-09-28 08:54:21 -07:00
// Endpoint vertices with slacks that have changed since tns was found.
2026-01-03 16:59:35 -08:00
VertexSet invalid_tns_;
2018-12-05 14:18:41 -08:00
// Indexed by path_ap->index().
2024-12-21 16:53:48 -07:00
DelayDblSeq tns_;
2018-12-05 14:18:41 -08:00
// Indexed by path_ap->index().
VertexSlackMapSeq tns_slacks_;
2019-03-12 17:25:53 -07:00
std::mutex tns_lock_;
2026-01-03 16:59:35 -08:00
2018-12-05 14:18:41 -08:00
// Indexed by path_ap->index().
2026-04-13 14:58:16 -07:00
WorstSlacks *worst_slacks_{nullptr};
2026-01-03 16:59:35 -08:00
2018-09-28 08:54:21 -07:00
// Use pointer to clk_info set so Tag.hh does not need to be included.
ClkInfoSet *clk_info_set_;
2019-03-12 17:25:53 -07:00
std::mutex clk_info_lock_;
2026-01-03 16:59:35 -08:00
2018-09-28 08:54:21 -07:00
// Entries in tags_ may be missing where previous filter tags were deleted.
2026-04-13 14:58:16 -07:00
TagIndex tag_capacity_{128};
2025-01-30 08:44:04 -07:00
std::atomic<Tag **> tags_;
2026-01-03 16:59:35 -08:00
// Use pointer to tag set so Tag.hh does not need to be included.
TagSet *tag_set_;
2025-04-11 16:59:48 -07:00
std::vector<Tag **> tags_prev_;
2026-04-13 14:58:16 -07:00
TagIndex tag_next_{0};
2019-03-12 17:25:53 -07:00
std::mutex tag_lock_;
2026-01-03 16:59:35 -08:00
// Capacity of tag_groups_.
TagGroupIndex tag_group_capacity_;
2025-01-30 08:44:04 -07:00
std::atomic<TagGroup **> tag_groups_;
2026-01-03 16:59:35 -08:00
TagGroupSet *tag_group_set_;
2025-04-11 16:59:48 -07:00
std::vector<TagGroup **> tag_groups_prev_;
2026-04-13 14:58:16 -07:00
TagGroupIndex tag_group_next_{0};
2019-03-26 20:25:12 -07:00
// Holes in tag_groups_ left by deleting filter tag groups.
std::vector<TagIndex> tag_group_free_indices_;
2019-03-12 17:25:53 -07:00
std::mutex tag_group_lock_;
2026-01-03 16:59:35 -08:00
2018-09-28 08:54:21 -07:00
// Latches data outputs to queue on the next search pass.
2026-06-24 16:55:51 -07:00
VertexSet postponed_arrivals_;
std::mutex postponed_arrivals_lock_;
2026-01-03 16:59:35 -08:00
// Clock network endpoints where arrival search was suppended by findClkArrivals().
2026-06-24 16:55:51 -07:00
VertexSet postponed_clk_endpoints_;
std::mutex postponed_clk_endpoints_lock_;
2026-01-03 16:59:35 -08:00
VertexSet endpoints_;
2026-04-13 14:58:16 -07:00
bool endpoints_initialized_{false};
2026-01-03 16:59:35 -08:00
VertexSet invalid_endpoints_;
2026-04-13 14:58:16 -07:00
bool have_filter_{false};
ExceptionFrom *filter_from_{nullptr};
ExceptionThruSeq *filter_thrus_{nullptr};
ExceptionTo *filter_to_{nullptr};
2026-01-03 16:59:35 -08:00
VertexSet filtered_arrivals_;
std::mutex filtered_arrivals_lock_;
2026-01-03 16:59:35 -08:00
2026-04-13 14:58:16 -07:00
bool found_downstream_clk_pins_{false};
2025-12-02 14:50:41 -08:00
std::vector<Path*> enum_paths_;
2026-01-03 16:59:35 -08:00
VisitPathEnds *visit_path_ends_;
2018-09-28 08:54:21 -07:00
GatedClk *gated_clk_;
2018-12-11 10:47:04 -08:00
CheckCrpr *check_crpr_;
2018-09-28 08:54:21 -07:00
};
// Eval across latch D->Q edges.
// SearchPred0 unless
// disabled loop
// disabled converging clock edge (Xilinx)
// clk source pin
class EvalPred : public SearchPred0
{
public:
2026-01-03 16:59:35 -08:00
EvalPred(const StaState *sta);
bool searchThru(Edge *edge,
const Mode *mode) const override;
2018-09-28 08:54:21 -07:00
void setSearchThruLatches(bool thru_latches);
2026-01-03 16:59:35 -08:00
bool searchTo(const Vertex *to_vertex,
const Mode *mode) const override;
using SearchPred::searchFrom;
using SearchPred::searchThru;
using SearchPred::searchTo;
2018-09-28 08:54:21 -07:00
protected:
2026-04-13 14:58:16 -07:00
bool search_thru_latches_{true};
2018-09-28 08:54:21 -07:00
};
// Class for visiting fanin/fanout paths of a vertex.
// This used by forward/backward search to find arrival/required path times.
2026-04-13 14:58:16 -07:00
class PathVisitor : public VertexVisitor,
public StaState
2018-09-28 08:54:21 -07:00
{
public:
// Uses search->evalPred() for search predicate.
2025-11-04 09:45:20 -07:00
PathVisitor(const StaState *sta);
2018-09-28 08:54:21 -07:00
PathVisitor(SearchPred *pred,
2026-01-03 16:59:35 -08:00
bool make_tag_cache,
const StaState *sta);
2026-04-13 14:58:16 -07:00
~PathVisitor() override;
2026-06-17 20:23:42 -07:00
virtual void visitFaninPaths(Vertex *to_vertex,
bool with_latch_edges);
2018-09-28 08:54:21 -07:00
virtual void visitFanoutPaths(Vertex *from_vertex);
2026-04-13 14:58:16 -07:00
// Return false to stop visiting.
virtual bool visitFromToPath(const Pin *from_pin,
Vertex *from_vertex,
const RiseFall *from_rf,
Tag *from_tag,
Path *from_path,
const Arrival &from_arrival,
Edge *edge,
TimingArc *arc,
ArcDelay arc_delay,
Vertex *to_vertex,
const RiseFall *to_rf,
Tag *to_tag,
Arrival &to_arrival,
const MinMax *min_max) = 0;
2018-09-28 08:54:21 -07:00
protected:
// Return false to stop visiting.
2026-01-03 16:59:35 -08:00
virtual bool visitEdge(const Pin *from_pin,
Vertex *from_vertex,
Edge *edge,
const Pin *to_pin,
Vertex *to_vertex);
2018-09-28 08:54:21 -07:00
// Return false to stop visiting.
2026-01-03 16:59:35 -08:00
[[nodiscard]] bool visitArc(const Pin *from_pin,
2026-05-05 18:20:46 -07:00
Vertex *from_vertex,
const RiseFall *from_rf,
Path *from_path,
Edge *edge,
TimingArc *arc,
const Pin *to_pin,
Vertex *to_vertex,
const MinMax *min_max,
const Mode *mode);
2018-09-28 08:54:21 -07:00
// This calls visit below with everything required to make to_path.
// Return false to stop visiting.
virtual bool visitFromPath(const Pin *from_pin,
2026-01-03 16:59:35 -08:00
Vertex *from_vertex,
const RiseFall *from_rf,
Path *from_path,
Edge *edge,
TimingArc *arc,
const Pin *to_pin,
Vertex *to_vertex,
const RiseFall *to_rf,
const MinMax *min_max);
2018-09-28 08:54:21 -07:00
SearchPred *pred_;
2025-11-04 09:45:20 -07:00
TagSet *tag_cache_;
2018-09-28 08:54:21 -07:00
};
// Visitor called during forward search to record an
// arrival at an path.
class ArrivalVisitor : public PathVisitor
{
public:
2025-11-04 09:45:20 -07:00
ArrivalVisitor(const StaState *sta);
2026-05-05 16:35:40 -07:00
ArrivalVisitor(const ArrivalVisitor &arrival_visitor);
2026-04-13 14:58:16 -07:00
~ArrivalVisitor() override;
2018-09-28 08:54:21 -07:00
// Initialize the visitor.
void init(bool always_to_endpoints,
2026-01-03 16:59:35 -08:00
bool clks_only,
SearchPred *pred);
2026-04-13 14:58:16 -07:00
void copyState(const StaState *sta) override;
void visit(Vertex *vertex) override;
2026-06-17 20:23:42 -07:00
void visit(Vertex *vertex,
bool with_latch_edges);
2026-04-13 14:58:16 -07:00
VertexVisitor *copy() const override;
2018-09-28 08:54:21 -07:00
// Return false to stop visiting.
2026-04-13 14:58:16 -07:00
bool visitFromToPath(const Pin *from_pin,
Vertex *from_vertex,
const RiseFall *from_rf,
Tag *from_tag,
Path *from_path,
const Arrival &from_arrival,
Edge *edge,
TimingArc *arc,
ArcDelay arc_delay,
Vertex *to_vertex,
const RiseFall *to_rf,
Tag *to_tag,
Arrival &to_arrival,
const MinMax *min_max) override;
2018-09-28 08:54:21 -07:00
void setAlwaysToEndpoints(bool to_endpoints);
TagGroupBldr *tagBldr() const { return tag_bldr_; }
protected:
void init0();
2026-01-03 16:59:35 -08:00
void seedArrivals(Vertex *vertex);
2018-09-28 08:54:21 -07:00
void pruneCrprArrivals();
void constrainedRequiredsInvalid(Vertex *vertex,
2026-01-03 16:59:35 -08:00
bool is_clk);
2026-06-24 16:55:51 -07:00
bool hasPendingLoopPaths(Edge *edge) const;
2018-09-28 08:54:21 -07:00
bool always_to_endpoints_;
2025-02-26 14:44:38 -08:00
bool always_save_prev_paths_;
2026-01-03 16:59:35 -08:00
bool clks_only_;
2018-09-28 08:54:21 -07:00
TagGroupBldr *tag_bldr_;
TagGroupBldr *tag_bldr_no_crpr_;
2026-06-25 10:43:43 -07:00
SearchPred *search_adj_;
2018-09-28 08:54:21 -07:00
bool crpr_active_;
bool has_fanin_one_;
};
class RequiredCmp
{
public:
void requiredsInit(Vertex *vertex,
2026-01-03 16:59:35 -08:00
const StaState *sta);
2025-03-26 18:21:03 -07:00
void requiredSet(size_t path_index,
2026-01-03 16:59:35 -08:00
Required &required,
const MinMax *min_max,
const StaState *sta);
2018-09-28 08:54:21 -07:00
// Return true if the requireds changed.
bool requiredsSave(Vertex *vertex,
2026-01-03 16:59:35 -08:00
const StaState *sta);
2025-03-26 18:21:03 -07:00
Required required(size_t path_index);
2018-09-28 08:54:21 -07:00
protected:
2026-04-13 14:58:16 -07:00
ArrivalSeq requireds_{10};
bool have_requireds_{false};
2018-09-28 08:54:21 -07:00
};
// Visitor called during backward search to record a
// required time at an path.
class RequiredVisitor : public PathVisitor
{
public:
2025-11-04 09:45:20 -07:00
RequiredVisitor(const StaState *sta);
2026-05-05 16:35:40 -07:00
RequiredVisitor(const RequiredVisitor &required_visitor);
2026-04-13 14:58:16 -07:00
~RequiredVisitor() override;
VertexVisitor *copy() const override;
void visit(Vertex *vertex) override;
// Return false to stop visiting.
bool visitFromToPath(const Pin *from_pin,
Vertex *from_vertex,
const RiseFall *from_rf,
Tag *from_tag,
Path *from_path,
const Arrival &from_arrival,
Edge *edge,
TimingArc *arc,
ArcDelay arc_delay,
Vertex *to_vertex,
const RiseFall *to_rf,
Tag *to_tag,
Arrival &to_arrival,
const MinMax *min_max) override;
2018-09-28 08:54:21 -07:00
protected:
2026-05-05 19:37:43 -07:00
RequiredCmp required_cmp_;
2018-09-28 08:54:21 -07:00
VisitPathEnds *visit_path_ends_;
};
2026-04-13 14:58:16 -07:00
} // namespace sta