mirror of
https://github.com/The-OpenROAD-Project/OpenSTA.git
synced 2026-08-31 10:04:55 +02:00
commit 4075953c9798444b9d5275f8fa0320f74b9bf1ef Author: James Cherry <[email protected]> Date: Sat Jul 4 09:00:48 2026 -0700 bfs resort hasNext Signed-off-by: James Cherry <[email protected]> commit 4fb0dd19e479f507935129fe940bcd1cf93b29d0 Author: James Cherry <[email protected]> Date: Thu Jul 2 12:23:54 2026 -0700 ApiChanges Signed-off-by: James Cherry <[email protected]> commit 510afbc1403c9fd2b764b4f3a71dddabd696f052 Author: James Cherry <[email protected]> Date: Thu Jul 2 11:07:44 2026 -0700 bfs enqueueFanin/out Signed-off-by: James Cherry <[email protected]> commit 9a5aa570e910c289b276a519bdf532dfa2e28c5f Author: James Cherry <[email protected]> Date: Thu Jul 2 10:41:27 2026 -0700 Revert "bfs continueFrom/enqueueFanin/out" This reverts commit d18498c947a7df2b615fafda38fbdbe8033eca9d. commit 02a253ab252f6637cfea29bdd788cb25da16813d Author: James Cherry <[email protected]> Date: Thu Jul 2 08:21:49 2026 -0700 Revert "Bfs rm search_pred" This reverts commit d858b3380b5e1d81ff6162b6378672a6099a246f. commit 0adf03613d91c5774545d12cba1dc52052ca732a Author: James Cherry <[email protected]> Date: Thu Jul 2 08:08:04 2026 -0700 Genclks::ensureMaster Signed-off-by: James Cherry <[email protected]> commit 089b373c548b77f9189a2617c3168867de620dfe Author: James Cherry <[email protected]> Date: Wed Jul 1 17:50:43 2026 -0700 Search::ensureDownstreamClkPins() use dfs Signed-off-by: James Cherry <[email protected]> commit 000ca16adb9bdcb92266e5f242629bc3e8612658 Author: James Cherry <[email protected]> Date: Wed Jul 1 10:03:57 2026 -0700 ApiChangeLog Signed-off-by: James Cherry <[email protected]> commit d858b3380b5e1d81ff6162b6378672a6099a246f Author: James Cherry <[email protected]> Date: Wed Jul 1 09:56:53 2026 -0700 Bfs rm search_pred Signed-off-by: James Cherry <[email protected]> commit d18498c947a7df2b615fafda38fbdbe8033eca9d Author: James Cherry <[email protected]> Date: Wed Jul 1 08:07:15 2026 -0700 bfs continueFrom/enqueueFanin/out Signed-off-by: James Cherry <[email protected]> commit a8c55b12b3ad7a1041766775727ad758ae8c6d18 Author: James Cherry <[email protected]> Date: Tue Jun 30 10:07:46 2026 -0700 bfs continue Signed-off-by: James Cherry <[email protected]> commit 8530dcd86b7ee736f1858143c3b2cee57cdbc991 Author: James Cherry <[email protected]> Date: Tue Jun 30 07:15:28 2026 -0700 Graph::visitFanin/out uninline edge iter Signed-off-by: James Cherry <[email protected]> commit 1ba1f4576f4b72c64db742369a63dcf8726ba002 Author: James Cherry <[email protected]> Date: Mon Jun 29 21:09:17 2026 -0700 BfsIterator rm Iterator<Vector> subclass Signed-off-by: James Cherry <[email protected]> commit b3ddd2580298958ad6da8225ecac0d255315504c Author: James Cherry <[email protected]> Date: Mon Jun 29 20:15:23 2026 -0700 ClkNetwork::findClkPins use VertexQueue instead of bfs Signed-off-by: James Cherry <[email protected]> commit 9e73154db48a7301be4039a25aec1fef589ef18a Author: James Cherry <[email protected]> Date: Mon Jun 29 18:39:39 2026 -0700 Search::ensureDownstreamClkPins use VertexQueue Signed-off-by: James Cherry <[email protected]> commit 9cd1b160e126ccacc47375ef508fdbb580bfa162 Author: James Cherry <[email protected]> Date: Mon Jun 29 11:18:03 2026 -0700 comment Signed-off-by: James Cherry <[email protected]> commit 0baf3838e2b8faa5fea560b0c95431b277631fea Author: James Cherry <[email protected]> Date: Mon Jun 29 10:57:39 2026 -0700 findClkArrivals use invalid for clk fringe Signed-off-by: James Cherry <[email protected]> commit e82ccd10a5e4bd69e41ce889685d7a130ae79ed6 Author: James Cherry <[email protected]> Date: Sun Jun 28 20:36:48 2026 -0700 Search::findClkArrivals Signed-off-by: James Cherry <[email protected]> commit cb66a72686c8728141c72ceb593b8a4b895ff696 Author: James Cherry <[email protected]> Date: Sun Jun 28 10:11:55 2026 -0700 rm Search::postponeClkFanouts Signed-off-by: James Cherry <[email protected]> Signed-off-by: James Cherry <[email protected]>
863 lines
33 KiB
C++
863 lines
33 KiB
C++
// opensta, Static Timing Analyzer
|
|
// Copyright (c) 2026, Parallax Software, Inc.
|
|
//
|
|
// 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/>.
|
|
//
|
|
// 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.
|
|
|
|
#pragma once
|
|
|
|
#include <atomic>
|
|
#include <mutex>
|
|
#include <unordered_set>
|
|
|
|
#include "Delay.hh"
|
|
#include "GraphClass.hh"
|
|
#include "LibertyClass.hh"
|
|
#include "MinMax.hh"
|
|
#include "NetworkClass.hh"
|
|
#include "Path.hh"
|
|
#include "SdcClass.hh"
|
|
#include "SearchClass.hh"
|
|
#include "SearchPred.hh"
|
|
#include "StaState.hh"
|
|
#include "StringUtil.hh"
|
|
#include "Transition.hh"
|
|
#include "VertexVisitor.hh"
|
|
|
|
namespace sta {
|
|
|
|
class BfsFwdIterator;
|
|
class BfsBkwdIterator;
|
|
class SearchPred;
|
|
class SearchThru;
|
|
class SearchAdj;
|
|
class ClkInfoLess;
|
|
class PathEndVisitor;
|
|
class ArrivalVisitor;
|
|
class RequiredVisitor;
|
|
class ClkPathIterator;
|
|
class EvalPred;
|
|
class TagGroup;
|
|
class TagGroupBldr;
|
|
class WorstSlacks;
|
|
class VisitPathEnds;
|
|
class GatedClk;
|
|
class CheckCrpr;
|
|
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*>;
|
|
|
|
class Search : public StaState
|
|
{
|
|
public:
|
|
Search(StaState *sta);
|
|
~Search() override;
|
|
void copyState(const StaState *sta) override;
|
|
// Reset to virgin state.
|
|
void clear();
|
|
// When enabled, non-critical path arrivals are pruned to improve
|
|
// run time and reduce memory.
|
|
[[nodiscard]] bool crprPathPruningEnabled() const;
|
|
void setCrprpathPruningEnabled(bool enabled);
|
|
// 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.
|
|
[[nodiscard]] bool crprApproxMissingRequireds() const;
|
|
void setCrprApproxMissingRequireds(bool enabled);
|
|
|
|
[[nodiscard]] bool unconstrainedPaths() const { return unconstrained_paths_; }
|
|
// from/thrus/to are owned and deleted by Search.
|
|
// Use scene nullptr to report timing for all scenes.
|
|
// PathEnds are owned by Mode PathGroups and deleted on next call.
|
|
PathEndSeq findPathEnds(ExceptionFrom *from,
|
|
ExceptionThruSeq *thrus,
|
|
ExceptionTo *to,
|
|
bool unconstrained,
|
|
const SceneSeq &scenes,
|
|
const MinMaxAll *min_max,
|
|
int group_path_count,
|
|
int endpoint_path_count,
|
|
bool unique_pins,
|
|
bool unique_edges,
|
|
float slack_min,
|
|
float slack_max,
|
|
bool sort_by_slack,
|
|
StringSeq &group_names,
|
|
bool setup,
|
|
bool hold,
|
|
bool recovery,
|
|
bool removal,
|
|
bool clk_gating_setup,
|
|
bool clk_gating_hold);
|
|
[[nodiscard]] bool arrivalsValid();
|
|
// 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);
|
|
void requiredInvalid(const Instance *inst);
|
|
void requiredInvalid(const Pin *pin);
|
|
// Vertex will be deleted.
|
|
void deleteVertexBefore(Vertex *vertex);
|
|
void deleteEdgeBefore(Edge *edge);
|
|
// 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);
|
|
[[nodiscard]] bool requiredsSeeded() const { return requireds_seeded_; }
|
|
[[nodiscard]] bool requiredsExist() const { return requireds_exist_; }
|
|
// The sum of all negative endpoints slacks.
|
|
// Incrementally updated.
|
|
Slack totalNegativeSlack(const MinMax *min_max);
|
|
Slack totalNegativeSlack(const Scene *scene,
|
|
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 Scene *scene,
|
|
const MinMax *min_max,
|
|
// Return values.
|
|
Slack &worst_slack,
|
|
Vertex *&worst_vertex);
|
|
// Clock arrival respecting ideal clock insertion delay and latency.
|
|
Arrival clkPathArrival(const Path *clk_path) const;
|
|
Arrival clkPathArrival(const Path *clk_path,
|
|
const ClkInfo *clk_info,
|
|
const ClockEdge *clk_edge,
|
|
const MinMax *min_max) const;
|
|
// Clock arrival at the path source/launch point.
|
|
Arrival pathClkPathArrival(const Path *path) const;
|
|
|
|
void deletePathGroups();
|
|
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;
|
|
void deleteFilter();
|
|
void deleteFilteredArrivals();
|
|
|
|
VertexSet &endpoints();
|
|
void endpointsInvalid();
|
|
|
|
// The set of clocks that arrive at vertex in the clock network.
|
|
ClockSet clocks(const Pin *pin,
|
|
const Mode *mode) const;
|
|
ClockSet clocks(const Vertex *vertex,
|
|
const Mode *mode) const;
|
|
// Clock domains for a vertex.
|
|
ClockSet clockDomains(const Vertex *vertex,
|
|
const Mode *mode) const;
|
|
ClockSet clockDomains(const Pin *pin,
|
|
const Mode *mode) const;
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
//
|
|
// Somewhat protected functions.
|
|
//
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
// Find arrivals for the clock tree.
|
|
void findClkArrivals();
|
|
EvalPred *evalPred() const { return eval_pred_; }
|
|
SearchPred *searchAdj() const { return search_thru_; }
|
|
Tag *tag(TagIndex index) const;
|
|
TagIndex tagCount() const;
|
|
TagGroupIndex tagGroupCount() const;
|
|
void reportTagGroups() const;
|
|
void reportPathCountHistogram() const;
|
|
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;
|
|
void endpointInvalid(Vertex *vertex);
|
|
Tag *fromUnclkedInputTag(const Pin *pin,
|
|
const RiseFall *rf,
|
|
const MinMax *min_max,
|
|
bool is_segment_start,
|
|
bool require_exception,
|
|
Scene *scene);
|
|
Tag *fromRegClkTag(const Pin *from_pin,
|
|
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);
|
|
Tag *thruTag(Tag *from_tag,
|
|
Edge *edge,
|
|
const RiseFall *to_rf,
|
|
TagSet *tag_cache);
|
|
Tag *thruClkTag(Path *from_path,
|
|
Vertex *from_vertex,
|
|
Tag *from_tag,
|
|
bool to_propagates_clk,
|
|
Edge *edge,
|
|
const RiseFall *to_rf,
|
|
bool arc_delay_min_max_eq,
|
|
const MinMax *min_max,
|
|
Scene *scene);
|
|
const ClkInfo *thruClkInfo(Path *from_path,
|
|
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);
|
|
const ClkInfo *clkInfoWithCrprClkPath(const ClkInfo *from_clk_info,
|
|
Path *from_path);
|
|
void seedClkArrivals(const Pin *pin,
|
|
const Mode *mode,
|
|
TagGroupBldr *tag_bldr);
|
|
void setVertexArrivals(Vertex *vertex,
|
|
TagGroupBldr *tag_bldr);
|
|
void tnsInvalid(Vertex *vertex);
|
|
[[nodiscard]] bool arrivalsChanged(Vertex *vertex,
|
|
TagGroupBldr *tag_bldr);
|
|
BfsFwdIterator *arrivalIterator() const { return arrival_iter_; }
|
|
BfsBkwdIterator *requiredIterator() const { return required_iter_; }
|
|
// Used by OpenROAD.
|
|
bool makeUnclkedPaths(Vertex *vertex,
|
|
bool is_segment_start,
|
|
bool require_exception,
|
|
TagGroupBldr *tag_bldr,
|
|
const Mode *mode);
|
|
bool makeUnclkedPaths2(Vertex *vertex,
|
|
TagGroupBldr *tag_bldr);
|
|
[[nodiscard]] bool isInputArrivalSrchStart(Vertex *vertex);
|
|
void seedInputSegmentArrival(const Pin *pin,
|
|
Vertex *vertex,
|
|
const Mode *mode,
|
|
TagGroupBldr *tag_bldr);
|
|
void postponeLatchDataOutputs(Vertex *vertex);
|
|
void postponeArrivals(Vertex *vertex);
|
|
void seedRequired(Vertex *vertex);
|
|
void seedRequiredEnqueueFanin(Vertex *vertex);
|
|
void seedInputDelayArrival(const Pin *pin,
|
|
Vertex *vertex,
|
|
InputDelay *input_delay,
|
|
const Mode *mode);
|
|
void seedInputDelayArrival(const Pin *pin,
|
|
Vertex *vertex,
|
|
InputDelay *input_delay,
|
|
bool is_segment_start,
|
|
const Mode *mode,
|
|
TagGroupBldr *tag_bldr);
|
|
// Insertion delay for regular or generated clock.
|
|
Arrival clockInsertion(const Clock *clk,
|
|
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,
|
|
const ClkInfo *clk_info,
|
|
bool is_clk,
|
|
InputDelay *input_delay,
|
|
bool is_segment_start,
|
|
ExceptionStateSet *states,
|
|
bool own_states,
|
|
TagSet *tag_cache);
|
|
void reportTags() const;
|
|
void reportClkInfos() const;
|
|
const ClkInfo *findClkInfo(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);
|
|
// Timing derated arc delay for a path analysis point.
|
|
ArcDelay deratedDelay(const Vertex *from_vertex,
|
|
const TimingArc *arc,
|
|
const Edge *edge,
|
|
bool is_clk,
|
|
const MinMax *min_max,
|
|
DcalcAPIndex dcalc_ap,
|
|
const Sdc *sdc);
|
|
|
|
TagGroup *tagGroup(const Vertex *vertex) const;
|
|
TagGroup *tagGroup(TagGroupIndex index) const;
|
|
void reportArrivals(Vertex *vertex,
|
|
bool report_tag_index,
|
|
int digits) const;
|
|
Slack wnsSlack(Vertex *vertex,
|
|
PathAPIndex path_ap_index);
|
|
void levelsChangedBefore();
|
|
void levelChangedBefore(Vertex *vertex);
|
|
void seedInputArrival(const Pin *pin,
|
|
Vertex *vertex,
|
|
const Mode *mode,
|
|
TagGroupBldr *tag_bldr);
|
|
void ensureDownstreamClkPins();
|
|
[[nodiscard]] bool matchesFilter(Path *path,
|
|
const ClockEdge *to_clk_edge);
|
|
CheckCrpr *checkCrpr() { return check_crpr_; }
|
|
VisitPathEnds *visitPathEnds() { return visit_path_ends_; }
|
|
GatedClk *gatedClk() { return gated_clk_; }
|
|
void findClkVertexPins(PinSet &clk_pins);
|
|
void findFilteredArrivals(ExceptionFrom *from,
|
|
ExceptionThruSeq *thrus,
|
|
ExceptionTo *to,
|
|
bool unconstrained,
|
|
bool thru_latches);
|
|
VertexSeq filteredEndpoints();
|
|
|
|
Arrival *arrivals(const Vertex *vertex) const;
|
|
Arrival *makeArrivals(const Vertex *vertex,
|
|
uint32_t count);
|
|
void deleteArrivals(const Vertex *vertex);
|
|
Required *requireds(const Vertex *vertex) const;
|
|
[[nodiscard]] bool hasRequireds(const Vertex *vertex) const;
|
|
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);
|
|
[[nodiscard]] bool crprPathPruningDisabled(const Vertex *vertex) const;
|
|
void setCrprPathPruningDisabled(const Vertex *vertex,
|
|
bool disabled);
|
|
[[nodiscard]] bool bfsInQueue(const Vertex *vertex,
|
|
BfsIndex index) const;
|
|
void setBfsInQueue(const Vertex *vertex,
|
|
BfsIndex index,
|
|
bool value);
|
|
TagGroupIndex tagGroupIndex(const Vertex *vertex) const;
|
|
void setTagGroupIndex(const Vertex *vertex,
|
|
TagGroupIndex tag_index);
|
|
void checkPrevPaths() const;
|
|
void deletePaths(Vertex *vertex);
|
|
void deleteTagGroup(TagGroup *group);
|
|
void saveEnumPath(Path *path);
|
|
bool isSrchRoot(Vertex *vertex,
|
|
const Mode *mode) const;
|
|
DelaysWrtClks arrivalsWrtClks(Vertex *vertex,
|
|
const Scene *scene);
|
|
DelaysWrtClks delaysWrtClks(Vertex *vertex,
|
|
const Scene *scene,
|
|
const PathDelayFunc &get_path_delay);
|
|
|
|
protected:
|
|
void initVars();
|
|
void deleteTags();
|
|
void deleteTagsPrev();
|
|
void deleteUnusedTagGroups();
|
|
void seedInvalidArrivals();
|
|
void seedArrivals();
|
|
void findClockVertices(VertexSet &vertices);
|
|
void seedClkDataArrival(const Pin *pin,
|
|
const RiseFall *rf,
|
|
const Clock *clk,
|
|
const ClockEdge *clk_edge,
|
|
const MinMax *min_max,
|
|
Arrival insertion,
|
|
Scene *scene,
|
|
TagGroupBldr *tag_bldr);
|
|
void seedClkArrival(const Pin *pin,
|
|
const RiseFall *rf,
|
|
const Clock *clk,
|
|
const ClockEdge *clk_edge,
|
|
const MinMax *min_max,
|
|
Arrival insertion,
|
|
Scene *scene,
|
|
TagGroupBldr *tag_bldr);
|
|
Tag *clkDataTag(const Pin *pin,
|
|
const Clock *clk,
|
|
const RiseFall *rf,
|
|
const ClockEdge *clk_edge,
|
|
Arrival insertion,
|
|
const MinMax *min_max,
|
|
Scene *scene);
|
|
void findInputArrivalVertices(VertexSet &vertices);
|
|
void findRootVertices(VertexSet &vertices);
|
|
void findInputDrvrVertices(VertexSet &vertices);
|
|
void seedInputArrival1(const Pin *pin,
|
|
Vertex *vertex,
|
|
bool is_segment_start,
|
|
const Mode *mode,
|
|
TagGroupBldr *tag_bldr);
|
|
void seedInputArrival(const Pin *pin,
|
|
Vertex *vertex,
|
|
ClockSet *wrt_clks);
|
|
void seedInputDelayArrival(const Pin *pin,
|
|
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);
|
|
void seedInputDelayArrival(const Pin *pin,
|
|
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);
|
|
void inputDelayClkArrival(InputDelay *input_delay,
|
|
const ClockEdge *clk_edge,
|
|
const MinMax *min_max,
|
|
const Mode *mode,
|
|
// Return values.
|
|
float &clk_arrival,
|
|
float &clk_insertion,
|
|
float &clk_latency);
|
|
void inputDelayRefPinArrival(Path *ref_path,
|
|
const ClockEdge *clk_edge,
|
|
const MinMax *min_max,
|
|
const Sdc *sdc,
|
|
// Return values.
|
|
float &ref_arrival,
|
|
float &ref_insertion,
|
|
float &ref_latency);
|
|
Tag *inputDelayTag(const Pin *pin,
|
|
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);
|
|
void enqueueClkRoots();
|
|
void enqueueInvalidClks();
|
|
|
|
void findAllArrivals(bool thru_latches);
|
|
void findArrivals1(Level level);
|
|
void findArrivals2(Level level);
|
|
Tag *mutateTag(Tag *from_tag,
|
|
const Pin *from_pin,
|
|
const RiseFall *from_rf,
|
|
bool from_is_clk,
|
|
const ClkInfo *from_clk_info,
|
|
const Pin *to_pin,
|
|
const RiseFall *to_rf,
|
|
bool to_is_clk,
|
|
bool to_is_reg_clk,
|
|
bool to_is_segment_start,
|
|
const ClkInfo *to_clk_info,
|
|
InputDelay *to_input_delay,
|
|
TagSet *tag_cache);
|
|
ExceptionPath *exceptionTo(const Path *path,
|
|
const Pin *pin,
|
|
const RiseFall *rf,
|
|
const ClockEdge *clk_edge,
|
|
const MinMax *min_max) const;
|
|
void seedRequireds();
|
|
void seedInvalidRequireds();
|
|
void findFilteredArrivals(bool thru_latches);
|
|
void findArrivalsSeed();
|
|
void seedFilterStarts();
|
|
[[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);
|
|
void deletePaths();
|
|
// Delete with incremental tns/wns update.
|
|
void deletePathsIncr(Vertex *vertex);
|
|
TagGroup *findTagGroup(TagGroupBldr *tag_bldr);
|
|
void deleteFilterTags();
|
|
void deleteFilterTagGroups();
|
|
void deleteFilterClkInfos();
|
|
|
|
void tnsPreamble();
|
|
void findTotalNegativeSlacks();
|
|
void updateInvalidTns();
|
|
void clearWorstSlack();
|
|
void wnsSlacks(Vertex *vertex,
|
|
// Return values.
|
|
SlackSeq &slacks);
|
|
void wnsTnsPreamble();
|
|
void worstSlackPreamble();
|
|
void deleteWorstSlacks();
|
|
void updateWorstSlacks(Vertex *vertex,
|
|
Slack slacks);
|
|
void updateTns(Vertex *vertex,
|
|
SlackSeq &slacks);
|
|
void tnsIncr(Vertex *vertex,
|
|
Slack slack,
|
|
PathAPIndex path_ap_index);
|
|
void tnsDecr(Vertex *vertex,
|
|
PathAPIndex path_ap_index);
|
|
void tnsNotifyBefore(Vertex *vertex);
|
|
[[nodiscard]] bool matchesFilterTo(Path *path,
|
|
const ClockEdge *to_clk_edge) const;
|
|
const Path *pathClkPathArrival1(const Path *path) const;
|
|
void deletePathsState(const Vertex *vertex) const;
|
|
void clocks(const Vertex *vertex,
|
|
const Mode *mode,
|
|
// Return value.
|
|
ClockSet &clks) const;
|
|
void clockDomains(const Vertex *vertex,
|
|
const Mode *mode,
|
|
// Return value.
|
|
ClockSet &clks) const;
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
// findPathEnds arg.
|
|
bool unconstrained_paths_{false};
|
|
bool crpr_path_pruning_enabled_{true};
|
|
bool crpr_approx_missing_requireds_{true};
|
|
|
|
// Search predicates.
|
|
SearchPred *search_thru_;
|
|
SearchPred *search_adj_;
|
|
EvalPred *eval_pred_;
|
|
|
|
// Some arrivals exist.
|
|
bool arrivals_exist_{false};
|
|
// Arrivals at start points have been initialized.
|
|
bool arrivals_seeded_{false};
|
|
// Vertices with invalid arrival times to update and search from.
|
|
VertexSet invalid_arrivals_;
|
|
std::mutex invalid_arrivals_lock_;
|
|
BfsFwdIterator *arrival_iter_;
|
|
ArrivalVisitor *arrival_visitor_;
|
|
|
|
// Some requireds exist.
|
|
bool requireds_exist_{false};
|
|
// Requireds have been seeded by searching arrivals to all endpoints.
|
|
bool requireds_seeded_{false};
|
|
// Vertices with invalid required times to update and search from.
|
|
VertexSet invalid_requireds_;
|
|
BfsBkwdIterator *required_iter_;
|
|
|
|
bool tns_exists_{false};
|
|
// Endpoint vertices with slacks that have changed since tns was found.
|
|
VertexSet invalid_tns_;
|
|
// Indexed by path_ap->index().
|
|
DelayDblSeq tns_;
|
|
// Indexed by path_ap->index().
|
|
VertexSlackMapSeq tns_slacks_;
|
|
std::mutex tns_lock_;
|
|
|
|
// Indexed by path_ap->index().
|
|
WorstSlacks *worst_slacks_{nullptr};
|
|
|
|
// Use pointer to clk_info set so Tag.hh does not need to be included.
|
|
ClkInfoSet *clk_info_set_;
|
|
std::mutex clk_info_lock_;
|
|
|
|
// Entries in tags_ may be missing where previous filter tags were deleted.
|
|
TagIndex tag_capacity_{128};
|
|
std::atomic<Tag **> tags_;
|
|
// Use pointer to tag set so Tag.hh does not need to be included.
|
|
TagSet *tag_set_;
|
|
std::vector<Tag **> tags_prev_;
|
|
TagIndex tag_next_{0};
|
|
std::mutex tag_lock_;
|
|
|
|
// Capacity of tag_groups_.
|
|
TagGroupIndex tag_group_capacity_;
|
|
std::atomic<TagGroup **> tag_groups_;
|
|
TagGroupSet *tag_group_set_;
|
|
std::vector<TagGroup **> tag_groups_prev_;
|
|
TagGroupIndex tag_group_next_{0};
|
|
// Holes in tag_groups_ left by deleting filter tag groups.
|
|
std::vector<TagIndex> tag_group_free_indices_;
|
|
std::mutex tag_group_lock_;
|
|
|
|
// Arrivals to queue on the next search pass.
|
|
VertexSet pending_arrivals_;
|
|
std::mutex pending_arrivals_lock_;
|
|
|
|
VertexSet endpoints_;
|
|
bool endpoints_initialized_{false};
|
|
VertexSet invalid_endpoints_;
|
|
|
|
bool have_filter_{false};
|
|
ExceptionFrom *filter_from_{nullptr};
|
|
ExceptionThruSeq *filter_thrus_{nullptr};
|
|
ExceptionTo *filter_to_{nullptr};
|
|
VertexSet filtered_arrivals_;
|
|
std::mutex filtered_arrivals_lock_;
|
|
|
|
bool found_downstream_clk_pins_{false};
|
|
std::vector<Path*> enum_paths_;
|
|
|
|
VisitPathEnds *visit_path_ends_;
|
|
GatedClk *gated_clk_;
|
|
CheckCrpr *check_crpr_;
|
|
};
|
|
|
|
// Eval across latch D->Q edges.
|
|
// SearchPred0 unless
|
|
// disabled loop
|
|
// disabled converging clock edge (Xilinx)
|
|
// clk source pin
|
|
class EvalPred : public SearchPred0
|
|
{
|
|
public:
|
|
EvalPred(const StaState *sta);
|
|
bool searchThru(Edge *edge,
|
|
const Mode *mode) const override;
|
|
void setSearchThruLatches(bool thru_latches);
|
|
bool searchTo(const Vertex *to_vertex,
|
|
const Mode *mode) const override;
|
|
|
|
using SearchPred::searchFrom;
|
|
using SearchPred::searchThru;
|
|
using SearchPred::searchTo;
|
|
|
|
protected:
|
|
bool search_thru_latches_{true};
|
|
};
|
|
|
|
// 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 StaState
|
|
{
|
|
public:
|
|
// Uses search->evalPred() for search predicate.
|
|
PathVisitor(const StaState *sta);
|
|
PathVisitor(SearchPred *pred,
|
|
bool make_tag_cache,
|
|
const StaState *sta);
|
|
~PathVisitor() override;
|
|
virtual void visitFaninPaths(Vertex *to_vertex,
|
|
bool with_latch_edges);
|
|
virtual void visitFanoutPaths(Vertex *from_vertex);
|
|
// 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;
|
|
|
|
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.
|
|
[[nodiscard]] bool visitArc(const Pin *from_pin,
|
|
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);
|
|
// 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,
|
|
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);
|
|
|
|
SearchPred *pred_;
|
|
TagSet *tag_cache_;
|
|
};
|
|
|
|
// Visitor called during forward search to record an
|
|
// arrival at an path.
|
|
class ArrivalVisitor : public PathVisitor
|
|
{
|
|
public:
|
|
ArrivalVisitor(const StaState *sta);
|
|
ArrivalVisitor(const ArrivalVisitor &arrival_visitor);
|
|
~ArrivalVisitor() override;
|
|
// Initialize the visitor.
|
|
void init(bool always_to_endpoints,
|
|
bool clks_only,
|
|
SearchPred *pred);
|
|
void copyState(const StaState *sta) override;
|
|
void visit(Vertex *vertex) override;
|
|
void visit(Vertex *vertex,
|
|
bool with_latch_edges);
|
|
VertexVisitor *copy() const 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;
|
|
void setAlwaysToEndpoints(bool to_endpoints);
|
|
TagGroupBldr *tagBldr() const { return tag_bldr_; }
|
|
|
|
protected:
|
|
void init0();
|
|
void seedArrivals(Vertex *vertex);
|
|
void pruneCrprArrivals();
|
|
void constrainedRequiredsInvalid(Vertex *vertex,
|
|
bool is_clk);
|
|
bool hasPendingLoopPaths(Edge *edge) const;
|
|
|
|
bool always_to_endpoints_;
|
|
bool always_save_prev_paths_;
|
|
bool clks_only_;
|
|
TagGroupBldr *tag_bldr_;
|
|
TagGroupBldr *tag_bldr_no_crpr_;
|
|
SearchPred *search_adj_;
|
|
bool crpr_active_;
|
|
bool has_fanin_one_;
|
|
};
|
|
|
|
class RequiredCmp
|
|
{
|
|
public:
|
|
void requiredsInit(Vertex *vertex,
|
|
const StaState *sta);
|
|
void requiredSet(size_t path_index,
|
|
Required &required,
|
|
const MinMax *min_max,
|
|
const StaState *sta);
|
|
// Return true if the requireds changed.
|
|
bool requiredsSave(Vertex *vertex,
|
|
const StaState *sta);
|
|
Required required(size_t path_index);
|
|
|
|
protected:
|
|
ArrivalSeq requireds_{10};
|
|
bool have_requireds_{false};
|
|
};
|
|
|
|
// Visitor called during backward search to record a
|
|
// required time at an path.
|
|
class RequiredVisitor : public PathVisitor
|
|
{
|
|
public:
|
|
RequiredVisitor(const StaState *sta);
|
|
RequiredVisitor(const RequiredVisitor &required_visitor);
|
|
~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;
|
|
|
|
protected:
|
|
RequiredCmp required_cmp_;
|
|
VisitPathEnds *visit_path_ends_;
|
|
};
|
|
|
|
} // namespace sta
|