diff --git a/Dockerfile.ubuntu22.04 b/Dockerfile.ubuntu22.04 index 4bc5ea9d..bee8b31e 100644 --- a/Dockerfile.ubuntu22.04 +++ b/Dockerfile.ubuntu22.04 @@ -16,8 +16,7 @@ RUN apt-get update && \ bison \ flex \ automake \ - autotools-dev \ - valgrind + autotools-dev # Download CUDD RUN wget https://raw.githubusercontent.com/davidkebo/cudd/main/cudd_versions/cudd-3.0.0.tar.gz && \ diff --git a/README.md b/README.md index 3b2c1754..e54711c0 100644 --- a/README.md +++ b/README.md @@ -194,7 +194,7 @@ following command builds a Docker image. ``` cd OpenSTA -docker build --file Dockerfile.ubuntu22.04 --tag OpenSTA . +docker build --file Dockerfile.ubuntu22.04 --tag opensta . ``` To run a docker container using the OpenSTA image, use the -v option @@ -202,7 +202,7 @@ to docker to mount direcories with data to use and -i to run interactively. ``` -docker run -i -v $HOME:/data OpenSTA +docker run -i -v $HOME:/data opensta ``` ## Build on Macos/Darwin diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index 1f02f666..b2ce0988 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -209,14 +209,14 @@ public: virtual VertexVisitor *copy() const; protected: - GraphDelayCalc *graph_delay_calc1_; + GraphDelayCalc *graph_delay_calc_; ArcDelayCalc *arc_delay_calc_; }; -FindVertexDelays::FindVertexDelays(GraphDelayCalc *graph_delay_calc1) : +FindVertexDelays::FindVertexDelays(GraphDelayCalc *graph_delay_calc) : VertexVisitor(), - graph_delay_calc1_(graph_delay_calc1), - arc_delay_calc_(graph_delay_calc1_->arc_delay_calc_->copy()) + graph_delay_calc_(graph_delay_calc), + arc_delay_calc_(graph_delay_calc_->arc_delay_calc_->copy()) { } @@ -230,13 +230,13 @@ FindVertexDelays::copy() const { // Copy StaState::arc_delay_calc_ because it needs separate state // for each thread. - return new FindVertexDelays(graph_delay_calc1_); + return new FindVertexDelays(graph_delay_calc_); } void FindVertexDelays::visit(Vertex *vertex) { - graph_delay_calc1_->findVertexDelay(vertex, arc_delay_calc_, true); + graph_delay_calc_->findVertexDelay(vertex, arc_delay_calc_, true); } // The logical structure of incremental delay calculation closely diff --git a/doc/ChangeLog.txt b/doc/ChangeLog.txt index 29d7c8be..d2bc6b97 100644 --- a/doc/ChangeLog.txt +++ b/doc/ChangeLog.txt @@ -6,6 +6,10 @@ This file summarizes user visible changes for each release. Realase 2.6.1 2025/03/30 ------------------------- +The -list_annotated and -list_not_annotated arguments to the +report_annotated_delay and report_annotated_check commands have been renamed to +-report_annotated and -report_unannotated. + The Tcl "source" command is no longer redefined to support "-echo" and "-verbose" arguments and redirecton. Use the "include" command instead. diff --git a/doc/OpenSTA.odt b/doc/OpenSTA.odt index 05d8c054..1458edde 100644 Binary files a/doc/OpenSTA.odt and b/doc/OpenSTA.odt differ diff --git a/doc/OpenSTA.pdf b/doc/OpenSTA.pdf index df95f6bd..29f4ba6a 100644 Binary files a/doc/OpenSTA.pdf and b/doc/OpenSTA.pdf differ diff --git a/include/sta/Search.hh b/include/sta/Search.hh index cd2dd9e7..780ef60a 100644 --- a/include/sta/Search.hh +++ b/include/sta/Search.hh @@ -359,6 +359,7 @@ public: void reportArrivals(Vertex *vertex) const; Slack wnsSlack(Vertex *vertex, PathAPIndex path_ap_index); + void levelsChangedBefore(); void levelChangedBefore(Vertex *vertex); void seedInputArrival(const Pin *pin, Vertex *vertex, diff --git a/network/Network.tcl b/network/Network.tcl index d2d9108a..7a05760e 100644 --- a/network/Network.tcl +++ b/network/Network.tcl @@ -42,7 +42,11 @@ proc_redirect report_instance { sta_warn 234 "report_instance -verbose is deprecated." } set instance_path [lindex $args 0] - set instance [find_instance $instance_path] + if { [is_object $instance_path] } { + set instance $instance_path + } else { + set instance [find_instance $instance_path] + } if { $instance != "NULL" } { report_instance1 $instance } else { diff --git a/sdc/Sdc.tcl b/sdc/Sdc.tcl index de5d7c9a..6071435a 100644 --- a/sdc/Sdc.tcl +++ b/sdc/Sdc.tcl @@ -3530,7 +3530,7 @@ proc set_wire_load_selection_group { args } { ################################################################ define_cmd_args "set_voltage" \ - {[-min min_case_value] [-object_list list_of_power_nets] max_case_voltage} + {[-min min_case_value] [-object_list power_nets] max_case_voltage} proc set_voltage { args } { parse_key_args "set_voltage" args keys {-min -object_list} flags {} diff --git a/sdf/Sdf.tcl b/sdf/Sdf.tcl index d84bd17c..32ce32d3 100644 --- a/sdf/Sdf.tcl +++ b/sdf/Sdf.tcl @@ -65,12 +65,13 @@ proc_redirect read_sdf { define_cmd_args "report_annotated_delay" \ {[-cell] [-net] [-from_in_ports] [-to_out_ports] [-max_lines lines]\ - [-list_annotated] [-list_not_annotated] [-constant_arcs]} + [-report_annotated] [-report_unannotated] [-constant_arcs]} proc_redirect report_annotated_delay { parse_key_args "report_annotated_delay" args keys {-max_lines} \ - flags {-cell -net -from_in_ports -to_out_ports -list_annotated \ - -list_not_annotated -constant_arcs} + flags {-cell -net -from_in_ports -to_out_ports \ + -report_annotated -report_unannotated -constant_arcs \ + -list_not_annotated -list_annotated} if { [info exists flags(-cell)] || [info exists flags(-net)] \ || [info exists flags(-from_in_ports)] \ || [info exists flags(-to_out_ports)] } { @@ -91,22 +92,35 @@ proc_redirect report_annotated_delay { check_positive_integer "-max_lines" $max_lines } + set report_annotated [info exists flags(-report_annotated)] + if { [info exists flags(-list_annotated)] } { + # Deprecated 05/26/2025 + sta_warn 624 "-list_annotated is deprecated. Use -report_annotated." + set report_annotated 1 + } + set report_unannotated [info exists flags(-report_unannotated)] + if { [info exists flags(-list_not_annotated)] } { + # Deprecated 05/26/2025 + sta_warn 625 "-list_not_annotated is deprecated. Use -report_unannotated." + set report_unannotated 1 + } + report_annotated_delay_cmd $report_cells $report_nets \ $report_in_nets $report_out_nets \ - $max_lines [info exists flags(-list_annotated)] \ - [info exists flags(-list_not_annotated)] \ + $max_lines $report_annotated $report_unannotated \ [info exists flags(-constant_arcs)] } define_cmd_args "report_annotated_check" \ {[-setup] [-hold] [-recovery] [-removal] [-nochange] [-width] [-period]\ - [-max_skew] [-max_lines lines] [-list_annotated] [-list_not_annotated]\ + [-max_skew] [-max_lines lines] [-report_annotated] [-report_unannotated]\ [-constant_arcs]} proc_redirect report_annotated_check { parse_key_args "report_annotated_check" args keys {-max_lines} \ flags {-setup -hold -recovery -removal -nochange -width -period \ - -max_skew -list_annotated -list_not_annotated -constant_arcs} + -max_skew -report_annotated -report_unannotated -constant_arcs \ + -list_annotated -list_not_annotated} if { [info exists flags(-setup)] || [info exists flags(-hold)] \ || [info exists flags(-recovery)] || [info exists flags(-removal)] \ || [info exists flags(-nochange)] || [info exists flags(-width)] \ @@ -136,11 +150,23 @@ proc_redirect report_annotated_check { check_positive_integer "-max_lines" $max_lines } + set report_annotated [info exists flags(-report_annotated)] + if { [info exists flags(-list_annotated)] } { + # Deprecated 05/26/2025 + sta_warn 626 "-list_annotated is deprecated. Use -report_annotated." + set report_annotated 1 + } + set report_unannotated [info exists flags(-report_unannotated)] + if { [info exists flags(-list_not_annotated)] } { + # Deprecated 05/26/2025 + sta_warn 627 "-list_not_annotated is deprecated. Use -report_unannotated." + set report_unannotated 1 + } + report_annotated_check_cmd $report_setup $report_hold \ $report_recovery $report_removal $report_nochange \ $report_width $report_period $report_max_skew \ - $max_lines [info exists flags(-list_annotated)] \ - [info exists flags(-list_not_annotated)] \ + $max_lines $report_annotated $report_unannotated \ [info exists flags(-constant_arcs)] } diff --git a/search/ClkInfo.cc b/search/ClkInfo.cc index 8025a0ba..26a3c4d0 100644 --- a/search/ClkInfo.cc +++ b/search/ClkInfo.cc @@ -34,15 +34,6 @@ namespace sta { -static bool -clkInfoEqual(const ClkInfo *clk_info1, - const ClkInfo *clk_info2, - const StaState *sta); -static int -clkInfoCmp(const ClkInfo *clk_info1, - const ClkInfo *clk_info2, - const StaState *sta); - ClkInfo::ClkInfo(const ClockEdge *clk_edge, const Pin *clk_src, bool is_propagated, @@ -210,7 +201,7 @@ ClkInfoEqual::operator()(const ClkInfo *clk_info1, return clkInfoEqual(clk_info1, clk_info2, sta_); } -static bool +bool clkInfoEqual(const ClkInfo *clk_info1, const ClkInfo *clk_info2, const StaState *sta) @@ -253,7 +244,7 @@ ClkInfoLess::operator()(const ClkInfo *clk_info1, return clkInfoCmp(clk_info1, clk_info2, sta_) < 0; } -static int +int clkInfoCmp(const ClkInfo *clk_info1, const ClkInfo *clk_info2, const StaState *sta) diff --git a/search/ClkInfo.hh b/search/ClkInfo.hh index f4706ee1..825a182c 100644 --- a/search/ClkInfo.hh +++ b/search/ClkInfo.hh @@ -93,6 +93,15 @@ private: unsigned int path_ap_index_:path_ap_index_bit_count; }; +int +clkInfoCmp(const ClkInfo *clk_info1, + const ClkInfo *clk_info2, + const StaState *sta); +bool +clkInfoEqual(const ClkInfo *clk_info1, + const ClkInfo *clk_info2, + const StaState *sta); + class ClkInfoLess { public: diff --git a/search/Levelize.cc b/search/Levelize.cc index 074ec759..79f54066 100644 --- a/search/Levelize.cc +++ b/search/Levelize.cc @@ -122,6 +122,8 @@ Levelize::levelize() Stats stats(debug_, report_); debugPrint(debug_, "levelize", 1, "levelize"); clear(); + if (observer_) + observer_->levelsChangedBefore(); VertexIterator vertex_iter(graph_); while (vertex_iter.hasNext()) { @@ -135,7 +137,7 @@ Levelize::levelize() findRoots(); findBackEdges(); - VertexSeq topo_sorted = findToplologicalOrder(); + VertexSeq topo_sorted = findTopologicalOrder(); assignLevels(topo_sorted); ensureLatchLevels(); @@ -345,7 +347,7 @@ Levelize::findUnvisitedVertices() //////////////////////////////////////////////////////////////// VertexSeq -Levelize::findToplologicalOrder() +Levelize::findTopologicalOrder() { Stats stats(debug_, report_); std::map in_degree; @@ -545,6 +547,19 @@ Levelize::ensureLatchLevels() latch_d_to_q_edges_.clear(); } +void +Levelize::setLevel(Vertex *vertex, + Level level) +{ + debugPrint(debug_, "levelize", 2, "set level %s %d", + vertex->to_string(this).c_str(), + level); + vertex->setLevel(level); + max_level_ = max(level, max_level_); + if (level >= Graph::vertex_level_max) + criticalError(616, "maximum logic level exceeded"); +} + void Levelize::invalid() { @@ -597,6 +612,8 @@ Levelize::deleteEdgeBefore(Edge *edge) { if (levelized_ && loop_edges_.hasKey(edge)) { + debugPrint(debug_, "levelize", 2, "delete loop edge %s", + edge->to_string(this).c_str()); disabled_loop_edges_.erase(edge); // Relevelize if a loop edge is removed. Incremental levelization // fails because the DFS path will be missing. @@ -621,7 +638,7 @@ Levelize::relevelize() vertex->to_string(this).c_str()); if (search_pred_.searchFrom(vertex)) { if (isRoot(vertex)) { - setLevel(vertex, 0); + setLevelIncr(vertex, 0); roots_->insert(vertex); } VertexSet visited(graph_); @@ -645,7 +662,7 @@ Levelize::visit(Vertex *vertex, EdgeSeq &path) { Pin *from_pin = vertex->pin(); - setLevel(vertex, level); + setLevelIncr(vertex, level); level += level_space; visited.insert(vertex); path_vertices.insert(vertex); @@ -691,8 +708,8 @@ Levelize::isDisabledLoop(Edge *edge) const } void -Levelize::setLevel(Vertex *vertex, - Level level) +Levelize::setLevelIncr(Vertex *vertex, + Level level) { debugPrint(debug_, "levelize", 2, "set level %s %d", vertex->to_string(this).c_str(), @@ -704,7 +721,7 @@ Levelize::setLevel(Vertex *vertex, } max_level_ = max(level, max_level_); if (level >= Graph::vertex_level_max) - criticalError(616, "maximum logic level exceeded"); + criticalError(617, "maximum logic level exceeded"); } //////////////////////////////////////////////////////////////// diff --git a/search/Levelize.hh b/search/Levelize.hh index 7a5f8408..28a34603 100644 --- a/search/Levelize.hh +++ b/search/Levelize.hh @@ -74,7 +74,7 @@ protected: void levelize(); void findRoots(); VertexSeq sortedRootsWithFanout(); - VertexSeq findToplologicalOrder(); + VertexSeq findTopologicalOrder(); void assignLevels(VertexSeq &topo_sorted); void recordLoop(Edge *edge, EdgeSeq &path); @@ -96,6 +96,8 @@ protected: EdgeSeq &path); void setLevel(Vertex *vertex, Level level); + void setLevelIncr(Vertex *vertex, + Level level); void clearLoopEdges(); void deleteLoops(); void reportPath(EdgeSeq &path) const; @@ -135,6 +137,7 @@ class LevelizeObserver public: LevelizeObserver() {} virtual ~LevelizeObserver() {} + virtual void levelsChangedBefore() = 0; virtual void levelChangedBefore(Vertex *vertex) = 0; }; diff --git a/search/PathEnum.cc b/search/PathEnum.cc index 1f229946..1f39e029 100644 --- a/search/PathEnum.cc +++ b/search/PathEnum.cc @@ -384,8 +384,8 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *, Vertex *to_vertex, const RiseFall *to_rf, Tag *to_tag, - Arrival &to_arrival, - const MinMax *min_max, + Arrival & /* to_arrival */, + const MinMax * /* min_max */, const PathAnalysisPt *path_ap) { // These paths fanin to before_div_ so we know to_vertex matches. @@ -406,19 +406,9 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *, // Make the diverted path end to check slack with from_path crpr. makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy); if (div_end) { - // Only enumerate paths with greater slack. - // fuzz for difference in updatePathHeadDelays and accumulated arrivals. - float fuzz = .001; - float slack_limit = path_end_slack_ > 0 - ? path_end_slack_ * (1.0 - fuzz) - : path_end_slack_ * (1.0 + fuzz); - if (delayGreaterEqual(div_end->slack(this), slack_limit, this)) { - reportDiversion(edge, arc, from_path); - path_enum_->makeDiversion(div_end, after_div_copy); - visited_fanins_.emplace(from_vertex, arc); - } - else - delete div_end; + reportDiversion(edge, arc, from_path); + path_enum_->makeDiversion(div_end, after_div_copy); + visited_fanins_.emplace(from_vertex, arc); } } else @@ -426,8 +416,7 @@ PathEnumFaninVisitor::visitFromToPath(const Pin *, edge->to_string(this).c_str(), arc->to_string().c_str()); } - // Only enumerate slower/faster paths. - else if (delayLessEqual(to_arrival, before_div_arrival_, min_max, this)) { + else { PathEnd *div_end; Path *after_div_copy; makeDivertedPathEnd(from_path, edge, arc, div_end, after_div_copy); diff --git a/search/Search.cc b/search/Search.cc index 3f363c96..a18e436f 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -795,14 +795,30 @@ Search::arrivalInvalid(Vertex *vertex) } } +// Move any pending arrival/requireds to invalid before relevelization. +void +Search::levelsChangedBefore() +{ + if (arrivals_exist_) { + while (arrival_iter_->hasNext()) { + Vertex *vertex = arrival_iter_->next(); + arrivalInvalid(vertex); + } + while (required_iter_->hasNext()) { + Vertex *vertex = required_iter_->next(); + requiredInvalid(vertex); + } + } +} + void Search::levelChangedBefore(Vertex *vertex) { if (arrivals_exist_) { arrival_iter_->remove(vertex); required_iter_->remove(vertex); - search_->arrivalInvalid(vertex); - search_->requiredInvalid(vertex); + arrivalInvalid(vertex); + requiredInvalid(vertex); } } @@ -2760,6 +2776,30 @@ Search::setVertexArrivals(Vertex *vertex, } } +class ReportPathLess +{ +public: + ReportPathLess(const StaState *sta); + bool operator()(const Path *path1, + const Path *path2) const; + +private: + const StaState *sta_; +}; + + +ReportPathLess::ReportPathLess(const StaState *sta) : + sta_(sta) +{ +} + +bool +ReportPathLess::operator()(const Path *path1, + const Path *path2) const +{ + return tagCmp(path1->tag(sta_), path2->tag(sta_), sta_) < 0; +} + void Search::reportArrivals(Vertex *vertex) const { @@ -2767,9 +2807,14 @@ Search::reportArrivals(Vertex *vertex) const TagGroup *tag_group = tagGroup(vertex); if (tag_group) { report_->reportLine("Group %u", tag_group->index()); + std::vector paths; VertexPathIterator path_iter(vertex, this); while (path_iter.hasNext()) { const Path *path = path_iter.next(); + paths.push_back(path); + } + sort(paths.begin(), paths.end(), ReportPathLess(this)); + for (const Path *path : paths) { const Tag *tag = path->tag(this); const PathAnalysisPt *path_ap = tag->pathAnalysisPt(this); const RiseFall *rf = tag->transition(); diff --git a/search/Sta.cc b/search/Sta.cc index 4bf71fca..4a42db38 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -210,7 +210,8 @@ class StaLevelizeObserver : public LevelizeObserver { public: StaLevelizeObserver(Search *search); - virtual void levelChangedBefore(Vertex *vertex); + void levelsChangedBefore() override; + void levelChangedBefore(Vertex *vertex) override; private: Search *search_; @@ -221,6 +222,12 @@ StaLevelizeObserver::StaLevelizeObserver(Search *search) : { } +void +StaLevelizeObserver::levelsChangedBefore() +{ + search_->levelsChangedBefore(); +} + void StaLevelizeObserver::levelChangedBefore(Vertex *vertex) { diff --git a/search/Tag.cc b/search/Tag.cc index d064c0f2..d4e36bae 100644 --- a/search/Tag.cc +++ b/search/Tag.cc @@ -289,26 +289,31 @@ Tag::matchHash(bool match_crpr_clk_pin, //////////////////////////////////////////////////////////////// +TagLess::TagLess(const StaState *sta) : + sta_(sta) +{ +} + bool TagLess::operator()(const Tag *tag1, const Tag *tag2) const { - return tagCmp(tag1, tag2) < 0; + return tagCmp(tag1, tag2, sta_) < 0; } int tagCmp(const Tag *tag1, - const Tag *tag2) + const Tag *tag2, + const StaState *sta) { if (tag1 == tag2) return 0; - int rf_index1 = tag1->rfIndex(); - int rf_index2 = tag2->rfIndex(); - if (rf_index1 < rf_index2) - return -1; - if (rf_index1 > rf_index2) - return 1; + ClkInfo *clk_info1 = tag1->clkInfo(); + ClkInfo *clk_info2 = tag2->clkInfo(); + int clk_cmp = clkInfoCmp(clk_info1, clk_info2, sta); + if (clk_cmp != 0) + return clk_cmp; PathAPIndex path_ap_index1 = tag1->pathAPIndex(); PathAPIndex path_ap_index2 = tag2->pathAPIndex(); @@ -317,11 +322,11 @@ tagCmp(const Tag *tag1, if (path_ap_index1 > path_ap_index2) return 1; - size_t clk_info1 = tag1->clkInfo()->hash(); - size_t clk_info2 = tag2->clkInfo()->hash(); - if (clk_info1 < clk_info2) + int rf_index1 = tag1->rfIndex(); + int rf_index2 = tag2->rfIndex(); + if (rf_index1 < rf_index2) return -1; - if (clk_info1 > clk_info2) + if (rf_index1 > rf_index2) return 1; bool is_clk1 = tag1->isClock(); diff --git a/search/Tag.hh b/search/Tag.hh index 35d46cba..3fa91de2 100644 --- a/search/Tag.hh +++ b/search/Tag.hh @@ -112,8 +112,12 @@ private: class TagLess { public: + TagLess(const StaState *sta); bool operator()(const Tag *tag1, const Tag *tag2) const; + +private: + const StaState *sta_; }; class TagIndexLess @@ -138,7 +142,8 @@ public: int tagCmp(const Tag *tag1, - const Tag *tag2); + const Tag *tag2, + const StaState *sta); // Match tag clock edge, clock driver and exception states but not clk info. bool diff --git a/util/Report.cc b/util/Report.cc index e541606c..413d03c4 100644 --- a/util/Report.cc +++ b/util/Report.cc @@ -304,6 +304,7 @@ Report::critical(int /* id */, printToBufferAppend(fmt, args); printBufferLine(); va_end(args); + exit(1); } void