532 lines
18 KiB
C++
532 lines
18 KiB
C++
// OpenSTA, Static Timing Analyzer
|
|
// Copyright (c) 2025, 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 <string>
|
|
|
|
#include "StringSeq.hh"
|
|
#include "SearchClass.hh"
|
|
#include "PathEnd.hh"
|
|
|
|
namespace sta {
|
|
|
|
class Corner;
|
|
class DcalcAnalysisPt;
|
|
class PathExpanded;
|
|
class ReportField;
|
|
|
|
typedef Vector<ReportField*> ReportFieldSeq;
|
|
|
|
class ReportPath : public StaState
|
|
{
|
|
public:
|
|
ReportPath(StaState *sta);
|
|
virtual ~ReportPath();
|
|
ReportPathFormat pathFormat() const { return format_; }
|
|
void setPathFormat(ReportPathFormat format);
|
|
void setReportFieldOrder(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_src_attr);
|
|
int digits() const { return digits_; }
|
|
void setDigits(int digits);
|
|
void setNoSplit(bool no_split);
|
|
bool reportSigmas() const { return report_sigmas_; }
|
|
void setReportSigmas(bool report);
|
|
ReportField *findField(const char *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,
|
|
const char *path_name,
|
|
int indent,
|
|
bool trailing_comma,
|
|
std::string &result) const;
|
|
void reportJson(const PathExpanded &expanded,
|
|
const char *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 reportCheck(const MaxSkewCheck *check,
|
|
bool verbose) 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,
|
|
Pin *pin,
|
|
float value,
|
|
float limit,
|
|
float slack) const;
|
|
void reportLimitVerbose(const ReportField *field,
|
|
Pin *pin,
|
|
const RiseFall *rf,
|
|
float value,
|
|
float limit,
|
|
float slack,
|
|
const Corner *corner,
|
|
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(const char *name,
|
|
const char *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;
|
|
const char *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,
|
|
const char *default_reason) const;
|
|
void reportEndpoint(const PathEndCheck *end) const;
|
|
void reportEndpoint(const PathEndLatchCheck *end) const;
|
|
const char *latchDesc(const PathEndLatchCheck *end) const;
|
|
void reportStartpoint(const char *start,
|
|
const std::string reason) const;
|
|
void reportEndpoint(const char *end,
|
|
const std::string reason) const;
|
|
void reportStartEndPoint(const char *pt,
|
|
const std::string reason,
|
|
const char *key) const;
|
|
std::string tgtClkName(const PathEnd *end) const;
|
|
const char *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;
|
|
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;
|
|
void reportGenClkSrcAndPath(const Path *path,
|
|
const Clock *clk,
|
|
const RiseFall *clk_rf,
|
|
const EarlyLate *early_late,
|
|
const PathAnalysisPt *path_ap,
|
|
float time_offset,
|
|
float path_time_offset,
|
|
bool clk_used_as_data) const;
|
|
bool reportGenClkSrcPath1(const Clock *clk,
|
|
const Pin *clk_pin,
|
|
const RiseFall *clk_rf,
|
|
const EarlyLate *early_late,
|
|
const PathAnalysisPt *path_ap,
|
|
float gclk_time,
|
|
float time_offset,
|
|
bool clk_used_as_data) const;
|
|
void reportClkSrcLatency(Arrival insertion,
|
|
float clk_time,
|
|
const EarlyLate *early_late) const;
|
|
void reportPathLine(const Path *path,
|
|
Delay incr,
|
|
Arrival time,
|
|
const char *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,
|
|
const char *clk_name,
|
|
const RiseFall *clk_rf,
|
|
Arrival clk_time,
|
|
const MinMax *min_max) const ;
|
|
void reportClkLine(const Clock *clk,
|
|
const char *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 reportHierPinsThru(const Path *path) const;
|
|
void reportInputExternalDelay(const Path *path,
|
|
float time_offset) const;
|
|
void reportLine(const char *what,
|
|
Delay total,
|
|
const EarlyLate *early_late) const;
|
|
void reportLineNegative(const char *what,
|
|
Delay total,
|
|
const EarlyLate *early_late) const;
|
|
void reportLine(const char *what,
|
|
Delay total,
|
|
const EarlyLate *early_late,
|
|
const RiseFall *rf) const;
|
|
void reportLine(const char *what,
|
|
Delay incr,
|
|
Delay total,
|
|
const EarlyLate *early_late) const;
|
|
void reportLine(const char *what,
|
|
Delay incr,
|
|
Delay total,
|
|
const EarlyLate *early_late,
|
|
const RiseFall *rf) const;
|
|
void reportLine(const char *what,
|
|
Slew slew,
|
|
Delay incr,
|
|
Delay total,
|
|
const EarlyLate *early_late) const;
|
|
void reportLine(const char *what,
|
|
float cap,
|
|
Slew slew,
|
|
float fanout,
|
|
Delay incr,
|
|
Delay total,
|
|
bool total_with_minus,
|
|
const EarlyLate *early_late,
|
|
const RiseFall *rf,
|
|
std::string src_attr,
|
|
const char *line_case) const;
|
|
void reportLineTotal(const char *what,
|
|
Delay incr,
|
|
const EarlyLate *early_late) const;
|
|
void reportLineTotalMinus(const char *what,
|
|
Delay decr,
|
|
const EarlyLate *early_late) const;
|
|
void reportLineTotal1(const char *what,
|
|
Delay incr,
|
|
bool incr_with_minus,
|
|
const EarlyLate *early_late) const;
|
|
void reportDashLineTotal() const;
|
|
void reportDescription(const char *what,
|
|
std::string &result) const;
|
|
void reportDescription(const char *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(Delay value,
|
|
const EarlyLate *early_late,
|
|
std::string &result) const;
|
|
void reportFieldDelayMinus(Delay value,
|
|
const EarlyLate *early_late,
|
|
const ReportField *field,
|
|
std::string &result) const;
|
|
void reportTotalDelay(Delay value,
|
|
const EarlyLate *early_late,
|
|
std::string &result) const;
|
|
void reportFieldDelay(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(const char *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;
|
|
float drvrFanout(Vertex *drvr,
|
|
const Corner *corner,
|
|
const MinMax *min_max) const;
|
|
const char *mpwCheckHiLow(const MinPulseWidthCheck *check) const;
|
|
void reportSkewClkPath(const char *arrival_msg,
|
|
const Path *clk_path) const;
|
|
const char *edgeRegLatchDesc(const Edge *edge,
|
|
const TimingArc *arc) const;
|
|
const char *checkRegLatchDesc(const TimingRole *role,
|
|
const RiseFall *clk_rf) const;
|
|
const char *regDesc(const RiseFall *clk_rf) const;
|
|
const char *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 PathAnalysisPt *path_ap) 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;
|
|
const char *asRisingFalling(const RiseFall *rf) const;
|
|
const char *asRiseFall(const RiseFall *rf) const;
|
|
Delay delayIncr(Delay time,
|
|
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_;
|
|
bool report_sigmas_;
|
|
|
|
int start_end_pt_width_;
|
|
|
|
ReportField *field_description_;
|
|
ReportField *field_total_;
|
|
ReportField *field_incr_;
|
|
ReportField *field_capacitance_;
|
|
ReportField *field_slew_;
|
|
ReportField *field_fanout_;
|
|
ReportField *field_src_attr_;
|
|
ReportField *field_edge_;
|
|
ReportField *field_case_;
|
|
|
|
const char *plus_zero_;
|
|
const char *minus_zero_;
|
|
|
|
static const float field_blank_;
|
|
static const float field_skip_;
|
|
};
|
|
|
|
class ReportField
|
|
{
|
|
public:
|
|
ReportField(const char *name,
|
|
const char *title,
|
|
int width,
|
|
bool left_justify,
|
|
Unit *unit,
|
|
bool enabled);
|
|
~ReportField();
|
|
void setProperties(const char *title,
|
|
int width,
|
|
bool left_justify);
|
|
const char *name() const { return name_; }
|
|
const char *title() const { return title_; }
|
|
int width() const { return width_; }
|
|
void setWidth(int width);
|
|
bool leftJustify() const { return left_justify_; }
|
|
Unit *unit() const { return unit_; }
|
|
const char *blank() const { return blank_; }
|
|
void setEnabled(bool enabled);
|
|
bool enabled() const { return enabled_; }
|
|
|
|
protected:
|
|
const char *name_;
|
|
const char *title_;
|
|
int width_;
|
|
bool left_justify_;
|
|
Unit *unit_;
|
|
bool enabled_;
|
|
char *blank_;
|
|
};
|
|
|
|
} // namespace
|