diff --git a/search/PathEnum.cc b/search/PathEnum.cc index 1f39e029..a63f76e9 100644 --- a/search/PathEnum.cc +++ b/search/PathEnum.cc @@ -35,6 +35,7 @@ #include "PathAnalysisPt.hh" #include "Tag.hh" #include "Search.hh" +#include "Latches.hh" #include "PathEnd.hh" #include "Path.hh" @@ -219,7 +220,8 @@ PathEnum::reportDiversionPath(Diversion *div) p->to_string(this).c_str(), delayAsString(p->arrival(), this), Path::equal(p, after_div, this) ? " <-after diversion" : ""); - if (p != path && network_->isLatchData(p->pin(this))) + if (p != path + && network_->isLatchData(p->pin(this))) break; p = p->prevPath(); } @@ -529,13 +531,23 @@ PathEnum::divSlack(Path *before_div, const TimingArc *div_arc, const PathAnalysisPt *path_ap) { - Arrival arc_arrival = before_div->arrival(); + Arrival before_div_arrival = before_div->arrival(); if (div_edge) { - ArcDelay div_delay = search_->deratedDelay(div_edge->from(graph_), - div_arc, div_edge, - false, path_ap); - Arrival div_arrival = search_->clkPathArrival(after_div) + div_delay; - return div_arrival - arc_arrival; + if (div_edge->role()->isLatchDtoQ()) { + Arrival div_arrival; + ArcDelay div_delay; + Tag *q_tag; + latches_->latchOutArrival(after_div, div_arc, div_edge, path_ap, + q_tag, div_delay, div_arrival); + return div_arrival - before_div_arrival; + } + else { + ArcDelay div_delay = search_->deratedDelay(div_edge->from(graph_), + div_arc, div_edge, + false, path_ap); + Arrival div_arrival = search_->clkPathArrival(after_div) + div_delay; + return div_arrival - before_div_arrival; + } } else { report()->error(1370, "path diversion missing edge."); @@ -634,39 +646,56 @@ PathEnum::updatePathHeadDelays(PathSeq &paths, Tag *prev_tag = after_div->tag(this); ClkInfo *prev_clk_info = prev_tag->clkInfo(); Arrival prev_arrival = search_->clkPathArrival(after_div); - for (int i = paths.size() - 1; i >= 0; i--) { + int path_idx_max = paths.size() - 1; + // paths[0] is the path endpoint + for (int i = path_idx_max; i >= 0; i--) { Path *path = paths[i]; TimingArc *arc = path->prevArc(this); Edge *edge = path->prevEdge(this); if (edge) { + Arrival arrival; PathAnalysisPt *path_ap = path->pathAnalysisPt(this); - ArcDelay arc_delay = search_->deratedDelay(edge->from(graph_), - arc, edge, false, path_ap); - Arrival arrival = prev_arrival + arc_delay; - debugPrint(debug_, "path_enum", 5, "update arrival %s %s %s -> %s", - path->vertex(this)->to_string(this).c_str(), - path->tag(this)->to_string(this).c_str(), - delayAsString(path->arrival(), this), - delayAsString(arrival, this)); - path->setArrival(arrival); - prev_arrival = arrival; - const Tag *tag = path->tag(this); - const ClkInfo *clk_info = tag->clkInfo(); - if (crprActive() - && clk_info != prev_clk_info - // D->Q paths use the EN->Q clk info so no need to update. - && arc->role() != TimingRole::latchDtoQ()) { - // When crpr is enabled the diverion may be from another crpr clk pin, - // so update the tags to use the corresponding ClkInfo. - Tag *updated_tag = search_->findTag(path->transition(this), - path_ap, - prev_clk_info, - tag->isClock(), - tag->inputDelay(), - tag->isSegmentStart(), - tag->states(), false); - path->setTag(updated_tag); + const MinMax *min_max = path->minMax(this); + if (i == path_idx_max + && edge->role()->isLatchDtoQ() + && min_max == MinMax::max()) { + ArcDelay arc_delay; + Tag *q_tag; + latches_->latchOutArrival(after_div, arc, edge, path_ap, + q_tag, arc_delay, arrival); + path->setArrival(arrival); + path->setTag(q_tag); + prev_clk_info = q_tag->clkInfo(); } + else { + ArcDelay arc_delay = search_->deratedDelay(edge->from(graph_), + arc, edge, false, path_ap); + arrival = prev_arrival + arc_delay; + path->setArrival(arrival); + const Tag *tag = path->tag(this); + const ClkInfo *clk_info = tag->clkInfo(); + if (crprActive() + && clk_info != prev_clk_info + // D->Q paths use the EN->Q clk info so no need to update. + && arc->role() != TimingRole::latchDtoQ()) { + // When crpr is enabled the diverion may be from another crpr clk pin, + // so update the tags to use the corresponding ClkInfo. + Tag *updated_tag = search_->findTag(path->transition(this), + path_ap, + prev_clk_info, + tag->isClock(), + tag->inputDelay(), + tag->isSegmentStart(), + tag->states(), false); + path->setTag(updated_tag); + } + debugPrint(debug_, "path_enum", 5, "update arrival %s %s %s -> %s", + path->vertex(this)->to_string(this).c_str(), + path->tag(this)->to_string(this).c_str(), + delayAsString(path->arrival(), this), + delayAsString(arrival, this)); + } + prev_arrival = arrival; } } } diff --git a/search/ReportPath.cc b/search/ReportPath.cc index 01e7cac6..889f5d53 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -549,8 +549,7 @@ ReportPath::reportFull(const PathEndLatchCheck *end) const if (ignore_clk_latency) { // Based on reportSrcPath. reportPathHeader(); - reportPath3(end->path(), expanded, false, false, 0.0, - end->sourceClkOffset(this)); + reportPath3(end->path(), expanded, false, end->sourceClkOffset(this)); } else reportSrcPath(end, expanded); @@ -716,8 +715,7 @@ ReportPath::reportFull(const PathEndPathDelay *end) const if (end->ignoreClkLatency(this)) { // Based on reportSrcPath. reportPathHeader(); - reportPath3(end->path(), expanded, false, false, 0.0, - end->sourceClkOffset(this)); + reportPath3(end->path(), expanded, false, end->sourceClkOffset(this)); } else reportSrcPath(end, expanded); @@ -935,11 +933,9 @@ ReportPath::reportFull(const PathEndDataCheck *end) const const ClockEdge *tgt_clk_edge = end->targetClkEdge(this); float prev = delayAsFloat(clk_arrival) + src_offset; float offset = prev - delayAsFloat(clk_delay) - tgt_clk_edge->time(); - reportPath5(data_clk_path, clk_expanded, clk_expanded.startIndex(), - clk_expanded.size() - 1, - data_clk_path->clkInfo(search_)->isPropagated(), false, - // Delay to startpoint is already included. - prev, offset); + // Delay to startpoint is already included. + reportPath6(data_clk_path, clk_expanded, clk_expanded.startIndex(), + true, false, prev, offset); } reportRequired(end, checkRoleReason(end)); reportSlack(end); @@ -1660,7 +1656,7 @@ ReportPath::reportSkewClkPath(const char *arrival_msg, insertion, latency); reportClkSrcLatency(insertion, clk_time, early_late); PathExpanded clk_expanded(clk_path, this); - reportPath2(clk_path, clk_expanded, false, 0.0); + reportPath1(clk_path, clk_expanded, false, 0.0); } } else { @@ -2229,8 +2225,8 @@ ReportPath::reportTgtClk(const PathEnd *end, PathExpanded clk_expanded(clk_path, this); float insertion_offset = tgtClkInsertionOffet(clk_path, early_late, path_ap); - reportPath5(clk_path, clk_expanded, 0, clk_expanded.size() - 1, is_prop, - reportClkPath(), delay_zero, time_offset + insertion_offset); + reportPath6(clk_path, clk_expanded, 0, is_prop, reportClkPath(), + delay_zero, time_offset + insertion_offset); } else { // Output departure. @@ -2377,7 +2373,7 @@ ReportPath::reportGenClkSrcAndPath(const Path *path, time_offset, clk_used_as_data); if (path) { PathExpanded expanded(path, this); - reportPath4(path, expanded, skip_first_path, false, clk_used_as_data, + reportPath2(path, expanded, skip_first_path, clk_used_as_data, path_time_offset); } } @@ -2419,7 +2415,7 @@ ReportPath::reportGenClkSrcPath1(const Clock *clk, reportClkSrcLatency(insertion, gclk_time, early_late); } PathExpanded src_expanded(src_path, this); - reportPath4(src_path, src_expanded, skip_first_path, false, + reportPath2(src_path, src_expanded, skip_first_path, clk_used_as_data, gclk_time); if (!clk->isPropagated()) reportLine("clock network delay (ideal)", 0.0, @@ -2603,11 +2599,51 @@ ReportPath::reportPathFull(const Path *path) const //////////////////////////////////////////////////////////////// +// Main entry point for reporting a path. void ReportPath::reportPath1(const Path *path, const PathExpanded &expanded, bool clk_used_as_data, float time_offset) const +{ + reportPath2(path, expanded, false, clk_used_as_data, time_offset); +} + +// Alternate entry point with skip_first_path arg. +void +ReportPath::reportPath2(const Path *path, + const PathExpanded &expanded, + bool skip_first_path, + bool clk_used_as_data, + float time_offset) const +{ + bool clk_is_propagated = path->clkInfo(search_)->isPropagated(); + bool report_clk_path = (reportClkPath() && clk_is_propagated) + || clk_used_as_data; + bool propagated_clk = clk_is_propagated || clk_used_as_data; + reportPath4(path, expanded, skip_first_path, propagated_clk, + report_clk_path, time_offset); +} + +// Alternate entry point with report_clk_path arg. +void +ReportPath::reportPath3(const Path *path, + const PathExpanded &expanded, + bool report_clk_path, + float time_offset) const +{ + bool propagated_clk = path->clkInfo(search_)->isPropagated(); + reportPath4(path, expanded, false, propagated_clk, + report_clk_path, time_offset); +} + +void +ReportPath::reportPath4(const Path *path, + const PathExpanded &expanded, + bool skip_first_path, + bool propagated_clk, + bool report_clk_path, + float time_offset) const { const Path *d_path, *q_path; Edge *d_q_edge; @@ -2620,11 +2656,11 @@ ReportPath::reportPath1(const Path *path, if (latch_enable_path) { const EarlyLate *early_late = latch_enable_path->minMax(this); latch_enable_time = search_->clkPathArrival(latch_enable_path); - if (reportClkPath()) { + if (report_clk_path) { PathExpanded enable_expanded(latch_enable_path, this); // Report the path to the latch enable. - reportPath2(latch_enable_path, enable_expanded, false, - time_offset); + reportPath5(latch_enable_path, enable_expanded, skip_first_path, + propagated_clk, report_clk_path, time_offset); } Arrival time = latch_enable_time + latch_time_given; Arrival incr = latch_time_given; @@ -2634,86 +2670,45 @@ ReportPath::reportPath1(const Path *path, reportLine("time borrowed from startpoint", incr, time, early_late); // Override latch D arrival with enable + given. reportPathLine(expanded.path(0), delay_zero, time, "latch_D"); - bool propagated_clk = path->clkInfo(search_)->isPropagated(); - bool report_clk_path = path->isClock(search_) || reportClkPath(); - reportPath5(path, expanded, 1, expanded.size() - 1, - propagated_clk, report_clk_path, + reportPath6(path, expanded, 1, propagated_clk, report_clk_path, latch_enable_time + latch_time_given, time_offset); } } else - reportPath2(path, expanded, clk_used_as_data, time_offset); -} - -void -ReportPath::reportPath2(const Path *path, - const PathExpanded &expanded, - bool clk_used_as_data, - float time_offset) const -{ - // Report the clock path if the end is a clock or we wouldn't have - // anything to report. - bool report_clk_path = clk_used_as_data - || (reportClkPath() - && path->clkInfo(search_)->isPropagated()); - reportPath3(path, expanded, clk_used_as_data, report_clk_path, - delay_zero, time_offset); -} - -void -ReportPath::reportPath3(const Path *path, - const PathExpanded &expanded, - bool clk_used_as_data, - bool report_clk_path, - Arrival prev_time, - float time_offset) const -{ - bool propagated_clk = clk_used_as_data - || path->clkInfo(search_)->isPropagated(); - size_t path_last_index = expanded.size() - 1; - reportPath5(path, expanded, 0, path_last_index, propagated_clk, - report_clk_path, prev_time, time_offset); -} - -void -ReportPath::reportPath4(const Path *path, - const PathExpanded &expanded, - bool skip_first_path, - bool skip_last_path, - bool clk_used_as_data, - float time_offset) const -{ - size_t path_first_index = 0; - Arrival prev_time(0.0); - if (skip_first_path) { - path_first_index = 1; - const Path *start = expanded.path(0); - prev_time = start->arrival() + time_offset; - } - size_t path_last_index = expanded.size() - 1; - if (skip_last_path - && path_last_index > 1) - path_last_index--; - bool propagated_clk = clk_used_as_data - || path->clkInfo(search_)->isPropagated(); - // Report the clock path if the end is a clock or we wouldn't have - // anything to report. - bool report_clk_path = path->isClock(search_) - || (reportClkPath() && propagated_clk); - reportPath5(path, expanded, path_first_index, path_last_index, - propagated_clk, report_clk_path, prev_time, time_offset); + reportPath5(path, expanded, skip_first_path, propagated_clk, + report_clk_path, time_offset); } void ReportPath::reportPath5(const Path *path, + const PathExpanded &expanded, + bool skip_first_path, + bool propagated_clk, + bool report_clk_path, + float time_offset) const +{ + size_t path_first_index = 0; + Arrival prev_time = 0.0; + if (skip_first_path) { + path_first_index = 1; + const Path *start = expanded.path(0); + prev_time = start->arrival() + time_offset; + } + reportPath6(path, expanded, path_first_index, propagated_clk, + report_clk_path, prev_time, time_offset); +} + +// This does the real workk of reporting an expanded path. +void +ReportPath::reportPath6(const Path *path, const PathExpanded &expanded, size_t path_first_index, - size_t path_last_index, bool propagated_clk, bool report_clk_path, Arrival prev_time, float time_offset) const { + size_t path_last_index = expanded.size() - 1; const MinMax *min_max = path->minMax(this); DcalcAnalysisPt *dcalc_ap = path->pathAnalysisPt(this)->dcalcAnalysisPt(); DcalcAPIndex ap_index = dcalc_ap->index(); @@ -2989,8 +2984,7 @@ ReportPath::reportInputExternalDelay(const Path *first_path, pathInputDelayRefPath(first_path, input_delay, ref_path); if (!ref_path.isNull() && reportClkPath()) { PathExpanded ref_expanded(&ref_path, this); - reportPath3(&ref_path, ref_expanded, false, true, - delay_zero, 0.0); + reportPath3(&ref_path, ref_expanded, true, 0.0); } } float input_arrival = diff --git a/search/ReportPath.hh b/search/ReportPath.hh index be229016..b9f4364b 100644 --- a/search/ReportPath.hh +++ b/search/ReportPath.hh @@ -302,24 +302,28 @@ protected: 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 clk_used_as_data, bool report_clk_path, - Arrival prev_time, float time_offset) const; void reportPath4(const Path *path, const PathExpanded &expanded, - bool clk_used_as_data, bool skip_first_path, - bool skip_last_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, - size_t path_last_index, bool propagated_clk, bool report_clk_path, Arrival prev_time,