// 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 . // // 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 #include #include #include "StringUtil.hh" #include "SearchClass.hh" #include "PathEnd.hh" #include "CheckMinPulseWidths.hh" #include "CheckMinPeriods.hh" #include "CheckMaxSkews.hh" namespace sta { class Scene; class PathExpanded; class ReportField; using ReportFieldSeq = std::vector; class ReportPath : public StaState { public: ReportPath(StaState *sta); virtual ~ReportPath(); ReportPathFormat pathFormat() const { return format_; } void setPathFormat(ReportPathFormat format); void setReportFieldOrder(const StringSeq &field_names); void setReportFields(bool report_input_pin, bool report_hier_pins, bool report_net, bool report_cap, bool report_slew, bool report_fanout, bool report_variation, bool report_src_attr); int digits() const { return digits_; } void setDigits(int digits); void setNoSplit(bool no_split); ReportField *findField(std::string_view name) const; // Header above reportPathEnd results. void reportPathEndHeader() const; // Footer below reportPathEnd results. void reportPathEndFooter() const; void reportPathEnd(const PathEnd *end) const; // Format report_path_endpoint only: // Previous path end is used to detect path group changes // so headers are reported by group. void reportPathEnd(const PathEnd *end, const PathEnd *prev_end, bool last) const; void reportPathEnds(const PathEndSeq *ends) const; void reportPath(const Path *path) const; void reportShort(const PathEndUnconstrained *end) const; void reportShort(const PathEndCheck *end) const; void reportShort(const PathEndLatchCheck *end) const; void reportShort(const PathEndPathDelay *end) const; void reportShort(const PathEndOutputDelay *end) const; void reportShort(const PathEndGatedClock *end) const; void reportShort(const PathEndDataCheck *end) const; void reportFull(const PathEndUnconstrained *end) const; void reportFull(const PathEndCheck *end) const; void reportFull(const PathEndLatchCheck *end) const; void reportFull(const PathEndPathDelay *end) const; void reportFull(const PathEndOutputDelay *end) const; void reportFull(const PathEndGatedClock *end) const; void reportFull(const PathEndDataCheck *end) const; void reportJsonHeader() const; void reportJsonFooter() const; void reportJson(const PathEnd *end, bool last) const; void reportJson(const Path *path) const; void reportJson(const Path *path, std::string_view path_name, int indent, bool trailing_comma, std::string &result) const; void reportJson(const PathExpanded &expanded, std::string_view path_name, int indent, bool trailing_comma, std::string &result) const; void reportEndHeader() const; void reportEndLine(const PathEnd *end) const; void reportSummaryHeader() const; void reportSummaryLine(const PathEnd *end) const; void reportSlackOnlyHeader() const; void reportSlackOnly(const PathEnd *end) const; void reportMpwCheck(const MinPulseWidthCheck &check, bool verbose) const; void reportMpwChecks(const MinPulseWidthCheckSeq &checks, bool verbose) const; void reportMpwHeaderShort() const; void reportShort(const MinPulseWidthCheck &check) const; void reportVerbose(const MinPulseWidthCheck &check) const; void reportCheck(const MinPeriodCheck &check, bool verbose) const; void reportChecks(const MinPeriodCheckSeq &checks, bool verbose) const; void reportPeriodHeaderShort() const; void reportShort(const MinPeriodCheck &check) const; void reportVerbose(const MinPeriodCheck &check) const; void reportChecks(const MaxSkewCheckSeq &checks, bool verbose) const; void reportMaxSkewHeaderShort() const; void reportShort(const MaxSkewCheck &check) const; void reportVerbose(const MaxSkewCheck &check) const; void reportLimitShortHeader(const ReportField *field) const; void reportLimitShort(const ReportField *field, const Pin *pin, float value, float limit, float slack) const; void reportLimitVerbose(const ReportField *field, const Pin *pin, const RiseFall *rf, float value, float limit, float slack, const Scene *scene, const MinMax *min_max) const; ReportField *fieldSlew() const { return field_slew_; } ReportField *fieldFanout() const { return field_fanout_; } ReportField *fieldCapacitance() const { return field_capacitance_; } ReportField *fieldSrcAttr() const { return field_src_attr_; } protected: void makeFields(); ReportField *makeField(std::string_view name, std::string_view title, int width, bool left_justify, Unit *unit, bool enabled); void reportEndpointHeader(const PathEnd *end, const PathEnd *prev_end) const; void reportShort(const PathEndUnconstrained *end, const PathExpanded &expanded) const; void reportShort(const PathEndCheck *end, const PathExpanded &expanded) const; void reportShort(const PathEndLatchCheck *end, const PathExpanded &expanded) const; void reportShort(const PathEndPathDelay *end, const PathExpanded &expanded) const; void reportShort(const PathEndOutputDelay *end, const PathExpanded &expanded) const; void reportShort(const PathEndGatedClock *end, const PathExpanded &expanded) const; void reportShort(const PathEndDataCheck *end, const PathExpanded &expanded) const; void reportEndpoint(const PathEndOutputDelay *end) const; void reportEndpointOutputDelay(const PathEndClkConstrained *end) const; void reportEndpoint(const PathEndPathDelay *end) const; void reportEndpoint(const PathEndGatedClock *end) const; std::string pathEndpoint(const PathEnd *end) const; std::string pathStartpoint(const PathEnd *end, const PathExpanded &expanded) const; void reportBorrowing(const PathEndLatchCheck *end, Arrival &borrow, Arrival &time_given_to_startpoint) const; void reportEndpoint(const PathEndDataCheck *end) const; std::string_view clkNetworkDelayIdealProp(bool is_ideal) const; std::string checkRoleReason(const PathEnd *end) const; std::string checkRoleString(const PathEnd *end) const; virtual void reportGroup(const PathEnd *end) const; void reportStartpoint(const PathEnd *end, const PathExpanded &expanded) const; void reportUnclockedEndpoint(const PathEnd *end, std::string_view default_reason) const; void reportEndpoint(const PathEndCheck *end) const; void reportEndpoint(const PathEndLatchCheck *end) const; std::string_view latchDesc(const PathEndLatchCheck *end) const; void reportStartpoint(std::string_view start, const std::string &reason) const; void reportEndpoint(std::string_view end, const std::string &reason) const; void reportStartEndPoint(std::string_view pt, const std::string &reason, std::string_view key) const; std::string tgtClkName(const PathEnd *end) const; std::string_view clkRegLatchDesc(const PathEnd *end) const; void reportSrcPath(const PathEnd *end, const PathExpanded &expanded) const; void reportTgtClk(const PathEnd *end) const; void reportTgtClk(const PathEnd *end, float prev_time) const; void reportTgtClk(const PathEnd *end, float prev_time, bool is_prop) const; void reportTgtClk(const PathEnd *end, float prev_time, float src_offset, bool is_prop) const; bool pathFromGenPropClk(const Path *clk_path, const EarlyLate *early_late) const; bool isGenPropClk(const Clock *clk, const RiseFall *clk_rf, const MinMax *min_max, const EarlyLate *early_late, const Sdc *sdc) const; void reportSrcClkAndPath(const Path *path, const PathExpanded &expanded, float time_offset, Arrival clk_insertion, Arrival clk_latency, bool is_path_delay) const; bool reportGenClkSrcPath(const Path *clk_path, const Clock *clk, const RiseFall *clk_rf, const MinMax *min_max, const EarlyLate *early_late, const Sdc *sdc) const; void reportGenClkSrcAndPath(const Path *path, const Clock *clk, const RiseFall *clk_rf, const EarlyLate *early_late, float time_offset, float path_time_offset, bool clk_used_as_data, const Mode *mode) const; bool reportGenClkSrcPath1(const Clock *clk, const Pin *clk_pin, const RiseFall *clk_rf, const EarlyLate *early_late, float gclk_time, float time_offset, bool clk_used_as_data, const Mode *mode) const; void reportClkSrcLatency(Arrival insertion, float clk_time, const EarlyLate *early_late) const; void reportPathLine(const Path *path, const Delay &incr, const Arrival &time, std::string_view line_case) const; void reportCommonClkPessimism(const PathEnd *end, Arrival &clk_arrival) const ; void reportClkUncertainty(const PathEnd *end, Arrival &clk_arrival) const ; void reportClkLine(const Clock *clk, std::string_view clk_name, const RiseFall *clk_rf, Arrival clk_time, const MinMax *min_max) const ; void reportClkLine(const Clock *clk, std::string_view clk_name, const RiseFall *clk_rf, Arrival prev_time, Arrival clk_time, const MinMax *min_max) const ; void reportRequired(const PathEnd *end, std::string margin_msg) const ; void reportSlack(const PathEnd *end) const ; void reportSlack(Slack slack) const ; void reportSpaceSlack(const PathEnd *end, std::string &line) const ; void reportSpaceSlack(Slack slack, std::string &line) const ; void reportSrcPathArrival(const PathEnd *end, const PathExpanded &expanded) const ; void reportPath(const PathEnd *end, const PathExpanded &expanded) const; void reportPathFull(const Path *path) const; void reportPathHeader() const; void reportPath1(const Path *path, const PathExpanded &expanded, bool clk_used_as_data, float time_offset) const; void reportPath2(const Path *path, const PathExpanded &expanded, bool skip_first_path, bool clk_used_as_data, float time_offset) const; void reportPath3(const Path *path, const PathExpanded &expanded, bool report_clk_path, float time_offset) const; void reportPath4(const Path *path, const PathExpanded &expanded, bool skip_first_path, bool propagated_clk, bool report_clk_path, float time_offset) const; void reportPath5(const Path *path, const PathExpanded &expanded, bool skip_first_path, bool propagated_clk, bool report_clk_path, float time_offset) const; void reportPath6(const Path *path, const PathExpanded &expanded, size_t path_first_index, bool propagated_clk, bool report_clk_path, Arrival prev_time, float time_offset) const; void reportVariation(const Path *path) const; void reportHierPinsThru(const Path *path) const; void reportInputExternalDelay(const Path *path, float time_offset) const; void reportLine(std::string_view what, Delay total, const EarlyLate *early_late) const; void reportLineNegative(std::string_view what, Delay total, const EarlyLate *early_late) const; void reportLine(std::string_view what, Delay total, const EarlyLate *early_late, const RiseFall *rf) const; void reportLine(std::string_view what, const Delay &incr, const Delay &total, const EarlyLate *early_late) const; void reportLine(std::string_view what, const Delay &incr, const Delay &total, const EarlyLate *early_late, const RiseFall *rf) const; void reportLine(std::string_view what, const Slew &slew, const Delay &incr, const Delay &total, const EarlyLate *early_late) const; void reportLine(std::string_view what, float cap, const Slew &slew, float fanout, const Delay &incr, float variation, const Delay &total, bool total_with_minus, const EarlyLate *early_late, const RiseFall *rf, std::string_view src_attr, std::string_view line_case) const; void reportLineTotal(std::string_view what, const Delay &incr, const EarlyLate *early_late) const; void reportLineTotalMinus(std::string_view what, const Delay &decr, const EarlyLate *early_late) const; void reportLineTotal1(std::string_view what, const Delay &incr, bool incr_with_minus, const EarlyLate *early_late) const; void reportDashLineTotal() const; void reportDescription(std::string_view what, std::string &result) const; void reportDescription(std::string_view what, bool first_field, bool last_field, std::string &result) const; void reportFieldTime(float value, ReportField *field, std::string &result) const; void reportSpaceFieldTime(float value, std::string &result) const; void reportSpaceFieldDelay(const Delay &value, const EarlyLate *early_late, std::string &result) const; void reportFieldDelayMinus(const Delay &value, const EarlyLate *early_late, const ReportField *field, std::string &result) const; void reportTotalDelay(const Delay &value, const EarlyLate *early_late, std::string &result) const; void reportFieldDelay(const Delay &value, const EarlyLate *early_late, const ReportField *field, std::string &result) const; void reportField(float value, const ReportField *field, std::string &result) const; void reportField(std::string_view value, const ReportField *field, std::string &result) const; void reportFieldBlank(const ReportField *field, std::string &result) const; void reportDashLine() const; void reportDashLine(int line_width) const; void reportBlankLine() const; std::string descriptionField(const Vertex *vertex) const; std::string descriptionField(const Pin *pin) const; std::string descriptionNet(const Pin *pin) const; bool reportClkPath() const; std::string clkName(const Clock *clk, bool inverted) const; bool hasExtInputDriver(const Pin *pin, const RiseFall *rf, const MinMax *min_max, const Sdc *sdc) const; float drvrFanout(Vertex *drvr, const Scene *scene, const MinMax *min_max) const; std::string_view mpwCheckHiLow(const MinPulseWidthCheck &check) const; void reportSkewClkPath(std::string_view arrival_msg, const Path *clk_path) const; std::string_view edgeRegLatchDesc(const Edge *edge, const TimingArc *arc) const; std::string_view checkRegLatchDesc(const TimingRole *role, const RiseFall *clk_rf) const; std::string_view regDesc(const RiseFall *clk_rf) const; std::string_view latchDesc(const RiseFall *clk_rf) const; void pathClkPath(const Path *path, const Path &clk_path) const; bool isPropagated(const Path *clk_path) const; bool isPropagated(const Path *clk_path, const Clock *clk) const; bool pathFromClkPin(const PathExpanded &expanded) const; bool pathFromClkPin(const Path *path, const Pin *start_pin) const; void latchPaths(const Path *path, // Return values. Path &d_path, Path &q_path, Edge *&d_q_edge) const; bool nextArcAnnotated(const Path *next_path, size_t next_index, const PathExpanded &expanded, DcalcAPIndex ap_index) const; float tgtClkInsertionOffet(const Path *clk_path, const EarlyLate *early_late) const; // InputDelay used to seed path root. InputDelay *pathInputDelay(const Path *path) const; void pathInputDelayRefPath(const Path *path, const InputDelay *input_delay, // Return value. Path &ref_path) const; std::string_view asRisingFalling(const RiseFall *rf) const; std::string_view asRiseFall(const RiseFall *rf) const; Delay delayIncr(const Delay &time, const Delay &prev, const MinMax *min_max) const; // Path options. ReportPathFormat format_; ReportFieldSeq fields_; bool report_input_pin_; bool report_hier_pins_; bool report_net_; bool no_split_; int digits_; size_t start_end_pt_width_; ReportField *field_description_; ReportField *field_total_; ReportField *field_incr_; ReportField *field_capacitance_; ReportField *field_slew_; ReportField *field_fanout_; ReportField *field_variation_; ReportField *field_src_attr_; ReportField *field_edge_; ReportField *field_case_; std::string plus_zero_; std::string minus_zero_; int field_width_extra_; static constexpr float field_blank_ = -1; static const float field_skip_; }; class ReportField { public: ReportField(std::string_view name, std::string_view title, size_t width, bool left_justify, Unit *unit, bool enabled); ~ReportField(); void setProperties(std::string_view title, size_t width, bool left_justify); const std::string &name() const { return name_; } const std::string &title() const { return title_; } size_t width() const { return width_; } void setWidth(size_t width); bool leftJustify() const { return left_justify_; } Unit *unit() const { return unit_; } const std::string &blank() const { return blank_; } void setEnabled(bool enabled); bool enabled() const { return enabled_; } protected: std::string name_; std::string title_; size_t width_; bool left_justify_; Unit *unit_; bool enabled_; std::string blank_; }; } // namespace