diff --git a/include/sta/PathEnd.hh b/include/sta/PathEnd.hh index c60d8fdc..e5f983d4 100644 --- a/include/sta/PathEnd.hh +++ b/include/sta/PathEnd.hh @@ -425,6 +425,7 @@ private: // Path constrained by an output delay. // If there is a reference pin, clk_path_ is the reference pin clock. +// If there is a path delay PathEndPathDelay is used instead of this. class PathEndOutputDelay : public PathEndClkConstrainedMcp { public: @@ -555,6 +556,7 @@ private: // Path constrained by set_min/max_delay. // "Clocked" when path delay ends at timing check pin. +// May end at output with set_output_delay. class PathEndPathDelay : public PathEndClkConstrained { public: @@ -587,6 +589,7 @@ public: virtual PathDelay *pathDelay() const { return path_delay_; } virtual ArcDelay margin(const StaState *sta) const; virtual float sourceClkOffset(const StaState *sta) const; + virtual ClockEdge *targetClkEdge(const StaState *sta) const; virtual float targetClkTime(const StaState *sta) const; virtual Arrival targetClkArrivalNoCrpr(const StaState *sta) const; virtual float targetClkOffset(const StaState *sta) const; @@ -594,6 +597,7 @@ public: virtual Required requiredTime(const StaState *sta) const; virtual int exceptPathCmp(const PathEnd *path_end, const StaState *sta) const; + bool hasOutputDelay() const { return output_delay_ != nullptr; } protected: PathEndPathDelay(PathDelay *path_delay, @@ -610,8 +614,7 @@ protected: PathDelay *path_delay_; TimingArc *check_arc_; Edge *check_edge_; - // Output delay is nullptr when there is no timing check or output - // delay at the endpoint. + // Output delay is nullptr when there is no output delay at the endpoint. OutputDelay *output_delay_; // Source clk arrival for set_min/max_delay -ignore_clk_latency. Arrival src_clk_arrival_; diff --git a/search/PathEnd.cc b/search/PathEnd.cc index 57a014c1..786a8af0 100644 --- a/search/PathEnd.cc +++ b/search/PathEnd.cc @@ -1845,6 +1845,17 @@ PathEnd::pathDelaySrcClkOffset(const PathRef &path, return offset; } +ClockEdge * +PathEndPathDelay::targetClkEdge(const StaState *sta) const +{ + if (!clk_path_.isNull()) + return clk_path_.clkEdge(sta); + else if (output_delay_) + return output_delay_->clkEdge(); + else + return nullptr; +} + float PathEndPathDelay::targetClkTime(const StaState *sta) const { @@ -1858,14 +1869,12 @@ PathEndPathDelay::targetClkTime(const StaState *sta) const Arrival PathEndPathDelay::targetClkArrivalNoCrpr(const StaState *sta) const { - if (!clk_path_.isNull()) { - ClockEdge *tgt_clk_edge = targetClkEdge(sta); - if (tgt_clk_edge) - return targetClkDelay(sta) - + targetClkUncertainty(sta); - else - return clk_path_.arrival(sta); - } + ClockEdge *tgt_clk_edge = targetClkEdge(sta); + if (tgt_clk_edge) + return targetClkDelay(sta) + + targetClkUncertainty(sta); + else if (!clk_path_.isNull()) + return clk_path_.arrival(sta); else return 0.0; } @@ -1887,9 +1896,7 @@ PathEndPathDelay::requiredTime(const StaState *sta) const return src_clk_arrival_ + delay + margin(sta); } else { - Arrival tgt_clk_arrival = 0.0; - if (!clk_path_.isNull()) - tgt_clk_arrival = targetClkArrival(sta); + Arrival tgt_clk_arrival = targetClkArrival(sta); float src_clk_offset = sourceClkOffset(sta); // Path delay includes target clk latency and timing check setup/hold // margin or external departure at target. diff --git a/search/ReportPath.cc b/search/ReportPath.cc index 07b6e3d8..456cb2fd 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -705,12 +705,16 @@ void ReportPath::reportEndpoint(const PathEndPathDelay *end, string &result) { - Instance *inst = network_->instance(end->vertex(this)->pin()); - const char *inst_name = cmd_network_->pathName(inst); - string clk_name = tgtClkName(end); - const char *reg_desc = clkRegLatchDesc(end); - auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str()); - reportEndpoint(inst_name, reason, result); + if (end->hasOutputDelay()) + reportEndpointOutputDelay(end, result); + else { + Instance *inst = network_->instance(end->vertex(this)->pin()); + const char *inst_name = cmd_network_->pathName(inst); + string clk_name = tgtClkName(end); + const char *reg_desc = clkRegLatchDesc(end); + auto reason = stdstrPrint("%s clocked by %s", reg_desc, clk_name.c_str()); + reportEndpoint(inst_name, reason, result); + } } void @@ -746,13 +750,11 @@ ReportPath::reportFull(const PathEndPathDelay *end, float delay = path_delay->delay(); reportLine(delay_msg.c_str(), delay, delay, early_late, result); if (!path_delay->ignoreClkLatency()) { - const Path *tgt_clk_path = end->targetClkPath(); - if (tgt_clk_path) { - float delay = 0.0; - if (path_delay) - delay = path_delay->delay(); + Clock *tgt_clk = end->targetClk(this); + if (tgt_clk) { + const Path *tgt_clk_path = end->targetClkPath(); if (reportClkPath() - && isPropagated(tgt_clk_path)) + && isPropagated(tgt_clk_path, tgt_clk)) reportTgtClk(end, delay, result); else { Arrival tgt_clk_delay = end->targetClkDelay(this); @@ -832,6 +834,13 @@ ReportPath::reportFull(const PathEndOutputDelay *end, void ReportPath::reportEndpoint(const PathEndOutputDelay *end, string &result) +{ + reportEndpointOutputDelay(end, result); +} + +void +ReportPath::reportEndpointOutputDelay(const PathEndClkConstrained *end, + string &result) { Vertex *vertex = end->vertex(this); Pin *pin = vertex->pin(); @@ -851,6 +860,7 @@ ReportPath::reportEndpoint(const PathEndOutputDelay *end, if (tgt_clk) { string clk_name = tgtClkName(end); auto reason = stdstrPrint("internal path endpoint clocked by %s", clk_name.c_str()); + reportEndpoint(pin_name, reason, result); } else diff --git a/search/ReportPath.hh b/search/ReportPath.hh index 8f24cc9d..c7ae2e75 100644 --- a/search/ReportPath.hh +++ b/search/ReportPath.hh @@ -203,6 +203,8 @@ protected: string &result); void reportEndpoint(const PathEndOutputDelay *end, string &result); + void reportEndpointOutputDelay(const PathEndClkConstrained *end, + string &result); void reportEndpoint(const PathEndPathDelay *end, string &result); void reportEndpoint(const PathEndGatedClock *end,