From c671b266fe4702a4cbbdf6771783099a3246fcae Mon Sep 17 00:00:00 2001 From: James Cherry Date: Mon, 20 Apr 2026 15:02:24 -0700 Subject: [PATCH 01/14] tidy Signed-off-by: James Cherry --- liberty/Liberty.cc | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index 97682e1e..b63e56fa 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -724,21 +724,21 @@ LibertyLibrary::makeSceneMap(LibertyLibrary *lib, // Map a cell linked in the network to the corresponding liberty cell // to use for delay calculation at a scene. void -LibertyLibrary::makeSceneMap(LibertyCell *cell1, - LibertyCell *cell2, +LibertyLibrary::makeSceneMap(LibertyCell *link_cell, + LibertyCell *scene_cell, Scene *scene, const MinMaxAll *min_max, Report *report) { for (const MinMax *mm : min_max->range()) { size_t lib_ap_index = scene->libertyIndex(mm); - cell1->setSceneCell(cell2, lib_ap_index); + link_cell->setSceneCell(scene_cell, lib_ap_index); } - LibertyCellPortBitIterator port_iter1(cell1); + LibertyCellPortBitIterator port_iter1(link_cell); while (port_iter1.hasNext()) { LibertyPort *port1 = port_iter1.next(); - LibertyPort *port2 = cell2->findLibertyPort(port1->name()); + LibertyPort *port2 = scene_cell->findLibertyPort(port1->name()); if (port2) { for (const MinMax *mm : min_max->range()) { size_t lib_ap_index = scene->libertyIndex(mm); @@ -747,15 +747,15 @@ LibertyLibrary::makeSceneMap(LibertyCell *cell1, } else report->warn(1110, "cell {}/{} port {} not found in cell {}/{}.", - cell1->library()->name(), - cell1->name(), + link_cell->library()->name(), + link_cell->name(), port1->name(), - cell2->library()->name(), - cell2->name()); + scene_cell->library()->name(), + scene_cell->name()); } - for (TimingArcSet *arc_set1 : cell1->timing_arc_sets_) { - TimingArcSet *arc_set2 = cell2->findTimingArcSet(arc_set1); + for (TimingArcSet *arc_set1 : link_cell->timing_arc_sets_) { + TimingArcSet *arc_set2 = scene_cell->findTimingArcSet(arc_set1); if (arc_set2) { const TimingArcSeq &arcs1 = arc_set1->arcs(); const TimingArcSeq &arcs2 = arc_set2->arcs(); @@ -775,13 +775,13 @@ LibertyLibrary::makeSceneMap(LibertyCell *cell1, } else report->warn(1111, "cell {}/{} {} -> {} timing group {} not found in cell {}/{}.", - cell1->library()->name(), - cell1->name(), + link_cell->library()->name(), + link_cell->name(), arc_set1->from() ? arc_set1->from()->name() : "", arc_set1->to()->name(), arc_set1->role()->to_string(), - cell2->library()->name(), - cell2->name()); + scene_cell->library()->name(), + scene_cell->name()); } } From daeb8503f9cf9fb3ab732c2abfb70ba45fe57f00 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Tue, 21 Apr 2026 10:54:40 -0700 Subject: [PATCH 02/14] cursor Signed-off-by: James Cherry --- .cursor/rules/opensta-tests.mdc | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .cursor/rules/opensta-tests.mdc diff --git a/.cursor/rules/opensta-tests.mdc b/.cursor/rules/opensta-tests.mdc new file mode 100644 index 00000000..c49f375e --- /dev/null +++ b/.cursor/rules/opensta-tests.mdc @@ -0,0 +1,13 @@ +--- +description: Where OpenSTA regression tests live (pvt/test vs public test/) +alwaysApply: true +--- + +# OpenSTA tests and regression + +- **Primary suite:** Most regression tests, Tcl drivers, and golden `.ok` files live under **`pvt/test/`** (private / separate repo, often opened as a second workspace root alongside `master`). +- **Public subset:** **`test/`** at the OpenSTA repo root holds a smaller set of tests shipped with the public tree (e.g. `test/regression`, `*.tcl`, `*.ok` there). + +When searching for a test name, regression lists, or updating goldens, **check `pvt/test` first**, then `test/`. + +Typical driver: `pvt/test/regression` (or `test/regression` for the public list). Built `sta` binary is usually `master/build/sta` relative to the main checkout. From d8c56f1d19814d3b5ac63876982798a9a4d64b53 Mon Sep 17 00:00:00 2001 From: Drew Lewis Date: Tue, 21 Apr 2026 17:59:38 -0400 Subject: [PATCH 03/14] Make defineProperty take handler by const& and clean up std::moves (#427) Signed-off-by: Drew Lewis --- include/sta/Property.hh | 20 ++++++++++---------- search/Property.cc | 22 +++++++++++----------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/include/sta/Property.hh b/include/sta/Property.hh index e5834b61..adeee3cc 100644 --- a/include/sta/Property.hh +++ b/include/sta/Property.hh @@ -99,25 +99,25 @@ public: // return PropertyValue("bar"); // }); void defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler); + const PropertyRegistry::PropertyHandler &handler); void defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler); + const PropertyRegistry::PropertyHandler &handler); void defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler); + const PropertyRegistry::PropertyHandler &handler); void defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler); + const PropertyRegistry::PropertyHandler &handler); void defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler); + const PropertyRegistry::PropertyHandler &handler); void defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler); + const PropertyRegistry::PropertyHandler &handler); void defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler); + const PropertyRegistry::PropertyHandler &handler); void defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler); + const PropertyRegistry::PropertyHandler &handler); void defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler); + const PropertyRegistry::PropertyHandler &handler); void defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler); + const PropertyRegistry::PropertyHandler &handler); protected: PropertyValue portSlew(const Port *port, diff --git a/search/Property.cc b/search/Property.cc index bef9ebb0..fe848d5e 100644 --- a/search/Property.cc +++ b/search/Property.cc @@ -1265,70 +1265,70 @@ Properties::capacitancePropertyValue(float cap) void Properties::defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler) + const PropertyRegistry::PropertyHandler &handler) { registry_library_.defineProperty(property, handler); } void Properties::defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler) + const PropertyRegistry::PropertyHandler &handler) { registry_liberty_library_.defineProperty(property, handler); } void Properties::defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler) + const PropertyRegistry::PropertyHandler &handler) { registry_cell_.defineProperty(property, handler); } void Properties::defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler) + const PropertyRegistry::PropertyHandler &handler) { registry_liberty_cell_.defineProperty(property, handler); } void Properties::defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler) + const PropertyRegistry::PropertyHandler &handler) { registry_port_.defineProperty(property, handler); } void Properties::defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler) + const PropertyRegistry::PropertyHandler &handler) { registry_liberty_port_.defineProperty(property, handler); } void Properties::defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler) + const PropertyRegistry::PropertyHandler &handler) { registry_instance_.defineProperty(property, handler); } void Properties::defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler) + const PropertyRegistry::PropertyHandler &handler) { registry_pin_.defineProperty(property, handler); } void Properties::defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler) + const PropertyRegistry::PropertyHandler &handler) { registry_net_.defineProperty(property, handler); } void Properties::defineProperty(std::string_view property, - PropertyRegistry::PropertyHandler &handler) + const PropertyRegistry::PropertyHandler &handler) { registry_clock_.defineProperty(property, handler); } @@ -1355,7 +1355,7 @@ void PropertyRegistry::defineProperty(std::string_view property, PropertyHandler handler) { - registry_[std::string(property)] = std::move(std::move(std::move(std::move(std::move(std::move(std::move(std::move(std::move(std::move(handler)))))))))); + registry_[std::string(property)] = std::move(handler); } } // namespace sta From ee5021dffcc65a9fe22e420ee15655e76362b03a Mon Sep 17 00:00:00 2001 From: Drew Lewis Date: Tue, 21 Apr 2026 18:02:29 -0400 Subject: [PATCH 04/14] Add missing headers and to StringUtil.cc for strtof fallback (#426) Signed-off-by: Drew Lewis --- util/StringUtil.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/util/StringUtil.cc b/util/StringUtil.cc index a6edc3f4..88ad9764 100644 --- a/util/StringUtil.cc +++ b/util/StringUtil.cc @@ -26,7 +26,9 @@ #include #include +#include #include +#include #include #include From c8b9ffb22da36bcf18a8c4704163ae0b6a032108 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Tue, 21 Apr 2026 12:39:06 -0700 Subject: [PATCH 05/14] tidy Signed-off-by: James Cherry --- .clang-tidy | 4 +++- dcalc/Arnoldi.hh | 1 - dcalc/ArnoldiReduce.cc | 5 ++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index c095fa1b..6d1a84c2 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -76,5 +76,7 @@ HeaderFilterRegex: '.*/(app|cmake|dcalc|graph|liberty|network|parasitics|power|s # util/gzstream.hh # util/FlexDisableRegister.hh # Bison-generated parser headers (build/{Liberty,Verilog,...}Parse.hh) -ExcludeHeaderFilterRegex: '(.*/)?(gzstream\.hh|FlexDisableRegister\.hh|(Liberty|Verilog|Sdf|Spef|Saif|LibExpr)Parse\.hh)$' +# Homebrew and MacPorts third-party headers. +ExcludeHeaderFilterRegex: '(^/opt/(homebrew|local)/.*)|((.*/)?(gzstream\.hh|FlexDisableRegister\.hh|(Liberty|Verilog|Sdf|Spef|Saif|LibExpr)Parse\.hh)$)' +SystemHeaders: false FormatStyle: none diff --git a/dcalc/Arnoldi.hh b/dcalc/Arnoldi.hh index ccfbb002..ac577565 100644 --- a/dcalc/Arnoldi.hh +++ b/dcalc/Arnoldi.hh @@ -69,7 +69,6 @@ class rcmodel : public ConcreteParasitic, public arnoldi1 { public: - rcmodel(); ~rcmodel() override; float capacitance() const override; PinSet unannotatedLoads(const Pin *drvr_pin, diff --git a/dcalc/ArnoldiReduce.cc b/dcalc/ArnoldiReduce.cc index 236c01a6..c9940ae4 100644 --- a/dcalc/ArnoldiReduce.cc +++ b/dcalc/ArnoldiReduce.cc @@ -43,12 +43,11 @@ namespace sta { // This is legacy C-style code. // NOLINTBEGIN(modernize-avoid-c-style-cast, bugprone-multi-level-implicit-pointer-conversion, bugprone-implicit-widening-of-multiplication-result) -rcmodel::rcmodel() +rcmodel::~rcmodel() { + free(pinV); } -rcmodel::~rcmodel() { free(pinV); } - float rcmodel::capacitance() const { From f9643fbf45cdcd675ffbf0088e7e146fc2b6b567 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Wed, 22 Apr 2026 11:13:25 -0700 Subject: [PATCH 06/14] set_pocv_mode warn if no lvf libs Signed-off-by: James Cherry --- include/sta/Sta.hh | 1 + network/Network.cc | 10 +++++----- search/Search.i | 6 +++--- search/Sta.cc | 26 ++++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 0d78ebba..1b74fb28 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -1609,6 +1609,7 @@ protected: Mode *mode, Parasitics *parasitics); void deleteScenes(); + void checkLibrarayPocv(); Scene *cmd_scene_{nullptr}; CmdNamespace cmd_namespace_{CmdNamespace::sdc}; diff --git a/network/Network.cc b/network/Network.cc index d096d842..3bf22cf6 100644 --- a/network/Network.cc +++ b/network/Network.cc @@ -134,16 +134,16 @@ Network::readLibertyAfter(LibertyLibrary *) LibertyCell * Network::findLibertyCell(std::string_view name) const { - LibertyLibraryIterator *iter = libertyLibraryIterator(); - while (iter->hasNext()) { - LibertyLibrary *lib = iter->next(); + LibertyLibraryIterator *lib_iter = libertyLibraryIterator(); + while (lib_iter->hasNext()) { + LibertyLibrary *lib = lib_iter->next(); LibertyCell *cell = lib->findLibertyCell(name); if (cell) { - delete iter; + delete lib_iter; return cell; } } - delete iter; + delete lib_iter; return nullptr; } diff --git a/search/Search.i b/search/Search.i index 7a89abe8..0764ae68 100644 --- a/search/Search.i +++ b/search/Search.i @@ -237,7 +237,7 @@ endpoint_slack(const Pin *pin, sta->ensureLibLinked(); if (!path_group_name.empty() && !sta->isGroupPathName(path_group_name, sta->cmdSdc())) { - sta->report()->error(1577, "{} is not a known path group name.", + sta->report()->error(1590, "{} is not a known path group name.", path_group_name); return INF; } @@ -436,7 +436,7 @@ set_report_path_field_properties(const char *field_name, if (field) field->setProperties(title, width, left_justify); else - sta->report()->warn(1575, "unknown report path field {}", field_name); + sta->report()->warn(1591, "unknown report path field {}", field_name); } void @@ -961,7 +961,7 @@ set_crpr_mode(std::string mode) else if (stringEqual(mode, "same_transition")) sta->setCrprMode(CrprMode::same_transition); else - sta->report()->error(1573, "unknown common clk pessimism mode."); + sta->report()->error(1592, "unknown common clk pessimism mode."); } const std::string & diff --git a/search/Sta.cc b/search/Sta.cc index c2cd5446..2d85c027 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -2281,9 +2281,11 @@ Sta::setPocvMode(PocvMode mode) delay_ops_ = new DelayOpsScalar(); break; case PocvMode::normal: + checkLibrarayPocv(); delay_ops_ = new DelayOpsNormal(); break; case PocvMode::skew_normal: + checkLibrarayPocv(); delay_ops_ = new DelayOpsSkewNormal(); break; } @@ -2292,6 +2294,30 @@ Sta::setPocvMode(PocvMode mode) } } +void +Sta::checkLibrarayPocv() +{ + LibertyLibraryIterator *lib_iter = network_->libertyLibraryIterator(); + while (lib_iter->hasNext()) { + LibertyLibrary *lib = lib_iter->next(); + LibertyCellIterator cell_iter(lib); + while (cell_iter.hasNext()) { + LibertyCell *cell = cell_iter.next(); + for (const TimingArcSet *arc_set : cell->timingArcSets()) { + for (const TimingArc *arc : arc_set->arcs()) { + GateTableModel *gate_model = arc->gateTableModel(); + if (gate_model) { + const TableModels *models = gate_model->delayModels(); + if (models->sigma(EarlyLate::early()) != nullptr) + return; + } + } + } + } + } + report_->warn(1578, "No liberty POCV/LVF models found."); +} + float Sta::pocvQuantile() { From 1edf4395472bdd19159891ca785597394cc6e34e Mon Sep 17 00:00:00 2001 From: James Cherry Date: Wed, 22 Apr 2026 11:13:45 -0700 Subject: [PATCH 07/14] spef allow illegal unquoted !'s Signed-off-by: James Cherry --- parasitics/SpefLex.ll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parasitics/SpefLex.ll b/parasitics/SpefLex.ll index 58975b84..0cb0dda4 100644 --- a/parasitics/SpefLex.ll +++ b/parasitics/SpefLex.ll @@ -73,11 +73,11 @@ FLOAT {DECIMAL}|{FRACTION}|{EXP} HCHAR "."|"/"|"|"|":" PREFIX_BUS_DELIM "["|"{"|"("|"<" SUFFIX_BUS_DELIM "]"|"}"|")"|">" -SPECIAL_CHAR "!"|"#"|"$"|"%"|"&"|"`"|"("|")"|"*"|"+"|","|"-"|"."|"/"|":"|";"|"<"|"="|">"|"?"|"@"|"["|"\\"|"]"|"^"|"'"|"{"|"|"|"}"|"~" +SPECIAL_CHAR "#"|"$"|"%"|"&"|"`"|"("|")"|"*"|"+"|","|"-"|"."|"/"|":"|";"|"<"|"="|">"|"?"|"@"|"["|"\\"|"]"|"^"|"'"|"{"|"|"|"}"|"~" ESCAPED_CHAR_SET {SPECIAL_CHAR}|\" ESCAPED_CHAR \\{ESCAPED_CHAR_SET} IDENT_ACHAR {ESCAPED_CHAR}|{ALPHA}|"_" -IDENT_CHAR {IDENT_ACHAR}|{DIGIT} +IDENT_CHAR {IDENT_ACHAR}|{DIGIT}|"!" ID {IDENT_ACHAR}{IDENT_CHAR}* BUS_SUB {DIGIT}|{ALPHA}|"_" BIT_IDENT {ID}({PREFIX_BUS_DELIM}{BUS_SUB}+{SUFFIX_BUS_DELIM})+ From f361dd65656d7cba561d454745b34be2fca4d1b0 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Thu, 23 Apr 2026 09:56:45 -0700 Subject: [PATCH 08/14] spice args Signed-off-by: James Cherry --- spice/WritePathSpice.cc | 2 +- spice/WriteSpice.hh | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/spice/WritePathSpice.cc b/spice/WritePathSpice.cc index 842b2620..1b90af87 100644 --- a/spice/WritePathSpice.cc +++ b/spice/WritePathSpice.cc @@ -193,7 +193,7 @@ WritePathSpice::WritePathSpice(const Path *path, void WritePathSpice::writeSpice() { - spice_stream_.open(std::string(spice_filename_)); + spice_stream_.open(spice_filename_); if (spice_stream_.is_open()) { path_expanded_.expand(path_, true); // Find subckt port names as a side-effect of writeSubckts. diff --git a/spice/WriteSpice.hh b/spice/WriteSpice.hh index 5230b72b..a1fd64a3 100644 --- a/spice/WriteSpice.hh +++ b/spice/WriteSpice.hh @@ -165,12 +165,12 @@ protected: std::string replaceFileExt(std::string_view filename, std::string_view ext); - const std::string_view spice_filename_; - const std::string_view subckt_filename_; - const std::string_view lib_subckt_filename_; - const std::string_view model_filename_; - const std::string_view power_name_; - const std::string_view gnd_name_; + const std::string spice_filename_; + const std::string subckt_filename_; + const std::string lib_subckt_filename_; + const std::string model_filename_; + const std::string power_name_; + const std::string gnd_name_; CircuitSim ckt_sim_; const Scene *scene_; const MinMax *min_max_; From a1c307713994379649f7673b8d51415b88cf64c2 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Thu, 23 Apr 2026 18:12:40 -0700 Subject: [PATCH 09/14] message ids Signed-off-by: James Cherry --- dcalc/LumpedCapDelayCalc.cc | 6 ++++-- search/MakeTimingModel.cc | 2 +- search/TagGroup.cc | 2 +- verilog/VerilogReader.cc | 4 ++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/dcalc/LumpedCapDelayCalc.cc b/dcalc/LumpedCapDelayCalc.cc index b245c1d6..41ef4250 100644 --- a/dcalc/LumpedCapDelayCalc.cc +++ b/dcalc/LumpedCapDelayCalc.cc @@ -142,8 +142,10 @@ LumpedCapDelayCalc::gateDelay(const Pin *drvr_pin, float gate_delay, drvr_slew; float in_slew1 = delayAsFloat(in_slew); // NaNs cause seg faults during table lookup. - if (std::isnan(load_cap) || std::isnan(in_slew.mean())) - report_->error(1350, "gate delay input variable is NaN"); + if (std::isnan(load_cap)) + report_->error(1350, "gate delay load cap is NaN"); + if (std::isnan(in_slew.mean())) + report_->error(1351, "gate delay input slew is NaN"); const Pvt *pvt = pinPvt(drvr_pin, scene, min_max); model->gateDelay(pvt, in_slew1, load_cap, gate_delay, drvr_slew); diff --git a/search/MakeTimingModel.cc b/search/MakeTimingModel.cc index 7e61d19c..6ca5f935 100644 --- a/search/MakeTimingModel.cc +++ b/search/MakeTimingModel.cc @@ -231,7 +231,7 @@ MakeTimingModel::checkClock(Clock *clk) { for (const Pin *pin : clk->leafPins()) { if (!network_->isTopLevelPort(pin)) - report_->warn(1355, "clock {} pin {} is inside model block.", clk->name(), + report_->warn(1380, "clock {} pin {} is inside model block.", clk->name(), network_->pathName(pin)); } } diff --git a/search/TagGroup.cc b/search/TagGroup.cc index e7afc9c5..6fbe4d93 100644 --- a/search/TagGroup.cc +++ b/search/TagGroup.cc @@ -311,7 +311,7 @@ TagGroupBldr::copyPaths(TagGroup *tag_group, if (exists2) paths[path_index2] = paths_[path_index1]; else - sta_->report()->critical(1351, "tag group missing tag"); + sta_->report()->critical(1360, "tag group missing tag"); } } diff --git a/verilog/VerilogReader.cc b/verilog/VerilogReader.cc index 263acb4a..5c6cd0f9 100644 --- a/verilog/VerilogReader.cc +++ b/verilog/VerilogReader.cc @@ -1490,12 +1490,12 @@ VerilogReader::linkNetwork(std::string_view top_cell_name, return top_instance; } else { - report_->error(1398, "{} is not a verilog module.", top_cell_name); + report_->error(1390, "{} is not a verilog module.", top_cell_name); return nullptr; } } else { - report_->error(1399, "{} is not a verilog module.", top_cell_name); + report_->error(1391, "{} is not a verilog module.", top_cell_name); return nullptr; } } From d4c13bb7cdfcea212ee45d7051228dd1f5b0cd81 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Fri, 24 Apr 2026 11:54:28 -0700 Subject: [PATCH 10/14] delays wrt clks refactor Signed-off-by: James Cherry --- include/sta/Search.hh | 5 +++++ include/sta/SearchClass.hh | 7 +++++++ include/sta/Sta.hh | 14 +++---------- search/Search.cc | 34 ++++++++++++++++++++++++++++++++ search/Sta.cc | 40 ++++++++------------------------------ 5 files changed, 57 insertions(+), 43 deletions(-) diff --git a/include/sta/Search.hh b/include/sta/Search.hh index 47fb6247..58506e1f 100644 --- a/include/sta/Search.hh +++ b/include/sta/Search.hh @@ -409,6 +409,11 @@ public: void saveEnumPath(Path *path); bool isSrchRoot(Vertex *vertex, const Mode *mode) const; + DelaysWrtClks arrivalsWrtClks(Vertex *vertex, + const Scene *scene); + DelaysWrtClks delaysWrtClks(Vertex *vertex, + const Scene *scene, + const PathDelayFunc &get_path_delay); protected: void initVars(); diff --git a/include/sta/SearchClass.hh b/include/sta/SearchClass.hh index 9e3205b9..c47ccf1b 100644 --- a/include/sta/SearchClass.hh +++ b/include/sta/SearchClass.hh @@ -24,14 +24,18 @@ #pragma once +#include #include #include #include #include "Delay.hh" #include "GraphClass.hh" +#include "LibertyClass.hh" #include "MinMaxValues.hh" #include "NetworkClass.hh" +#include "RiseFallMinMaxDelay.hh" +#include "SdcClass.hh" #include "VectorMap.hh" namespace sta { @@ -111,6 +115,9 @@ using SlackSeq = std::vector; using Crpr = Delay; using PathSeq = std::vector; using ConstPathSeq = std::vector; +// Path::slack/arrival/required function. +using PathDelayFunc = std::function; +using DelaysWrtClks = std::map; enum class ReportPathFormat { full, full_clock, diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 1b74fb28..7817b1c2 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -24,7 +24,7 @@ #pragma once -#include +#include #include #include #include @@ -82,8 +82,6 @@ using CheckError = StringSeq; using CheckErrorSeq = std::vector; enum class CmdNamespace { sta, sdc }; using ParasiticsNameMap = std::map>; -// Path::slack/arrival/required function. -using PathDelayFunc = std::function; using GraphLoopSeq = std::vector; // Initialize sta functions that are not part of the Sta class. @@ -1524,16 +1522,10 @@ protected: int digits, bool find_required, const PathDelayFunc &get_path_delay); - void reportDelaysWrtClks(Vertex *vertex, - const ClockEdge *clk_edge, - const Scene *scene, + void reportDelaysWrtClks(const ClockEdge *clk_edge, bool report_variance, int digits, - const PathDelayFunc &get_path_delay); - RiseFallMinMaxDelay findDelaysWrtClks(Vertex *vertex, - const ClockEdge *clk_edge, - const Scene *scene, - const PathDelayFunc &get_path_delay); + DelaysWrtClks &clk_delays); std::string formatDelay(const RiseFall *rf, const MinMax *min_max, const RiseFallMinMaxDelay &delays, diff --git a/search/Search.cc b/search/Search.cc index 2fc617fa..d0d6b0ca 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -57,6 +57,7 @@ #include "PortDelay.hh" #include "PortDirection.hh" #include "Report.hh" +#include "RiseFallMinMaxDelay.hh" #include "Scene.hh" #include "Sdc.hh" #include "SdcClass.hh" @@ -3997,4 +3998,37 @@ Search::wnsSlack(Vertex *vertex, return slacks[path_ap_index]; } +//////////////////////////////////////////////////////////////// + +DelaysWrtClks +Search::arrivalsWrtClks(Vertex *vertex, + const Scene *scene) +{ + return delaysWrtClks(vertex, scene, + [] (const Path *path) { + return path->arrival(); + }); +} + +DelaysWrtClks +Search::delaysWrtClks(Vertex *vertex, + const Scene *scene, + const PathDelayFunc &get_path_delay) +{ + DelaysWrtClks delays_wrt_clks; + VertexPathIterator path_iter(vertex, scene, nullptr, nullptr, this); + while (path_iter.hasNext()) { + Path *path = path_iter.next(); + Delay delay = get_path_delay(path); + if (!delayInf(delay, this)) { + const RiseFall *rf = path->transition(this); + const MinMax *min_max = path->minMax(this); + const ClockEdge *clk_edge = path->clkEdge(this); + RiseFallMinMaxDelay &delays = delays_wrt_clks[clk_edge]; + delays.mergeValue(rf, min_max, delay, this); + } + } + return delays_wrt_clks; +} + } // namespace sta diff --git a/search/Sta.cc b/search/Sta.cc index 2d85c027..dc6bfc04 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -26,6 +26,7 @@ #include #include +#include #include #include "ArcDelayCalc.hh" @@ -3346,29 +3347,25 @@ Sta::reportDelaysWrtClks(Vertex *vertex, else search_->findArrivals(vertex->level()); const Sdc *sdc = scene->sdc(); - reportDelaysWrtClks(vertex, nullptr, scene, report_variance, digits, get_path_delay); + DelaysWrtClks clk_delays = search_->delaysWrtClks(vertex, scene, get_path_delay); + reportDelaysWrtClks(nullptr, report_variance, digits, clk_delays); const ClockEdge *default_clk_edge = sdc->defaultArrivalClock()->edge(RiseFall::rise()); - reportDelaysWrtClks(vertex, default_clk_edge, scene, report_variance, - digits, get_path_delay); + reportDelaysWrtClks(default_clk_edge, report_variance, digits, clk_delays); for (const Clock *clk : sdc->sortedClocks()) { for (const RiseFall *rf : RiseFall::range()) { const ClockEdge *clk_edge = clk->edge(rf); - reportDelaysWrtClks(vertex, clk_edge, scene, report_variance, digits, - get_path_delay); + reportDelaysWrtClks(clk_edge, report_variance, digits, clk_delays); } } } void -Sta::reportDelaysWrtClks(Vertex *vertex, - const ClockEdge *clk_edge, - const Scene *scene, +Sta::reportDelaysWrtClks(const ClockEdge *clk_edge, bool report_variance, int digits, - const PathDelayFunc &get_path_delay) + DelaysWrtClks &clk_delays) { - RiseFallMinMaxDelay delays = - findDelaysWrtClks(vertex, clk_edge, scene, get_path_delay); + const RiseFallMinMaxDelay &delays = clk_delays[clk_edge]; if (!delays.empty()) { std::string clk_name; if (clk_edge) @@ -3385,27 +3382,6 @@ Sta::reportDelaysWrtClks(Vertex *vertex, } } -RiseFallMinMaxDelay -Sta::findDelaysWrtClks(Vertex *vertex, - const ClockEdge *clk_edge, - const Scene *scene, - const PathDelayFunc &get_path_delay) -{ - RiseFallMinMaxDelay delays; - VertexPathIterator path_iter(vertex, scene, nullptr, nullptr, this); - while (path_iter.hasNext()) { - Path *path = path_iter.next(); - Delay delay = get_path_delay(path); - const RiseFall *rf = path->transition(this); - const MinMax *min_max = path->minMax(this); - const ClockEdge *path_clk_edge = path->clkEdge(this); - if (path_clk_edge == clk_edge - && !delayInf(delay, this)) - delays.mergeValue(rf, min_max, delay, this); - } - return delays; -} - std::string Sta::formatDelay(const RiseFall *rf, const MinMax *min_max, From 7a236c38b77bc7155797df3fbc1ef724660b1b04 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 25 Apr 2026 10:35:42 -0700 Subject: [PATCH 11/14] flatten Clock::uncertainties Signed-off-by: James Cherry --- include/sta/Clock.hh | 4 ++-- include/sta/MinMaxValues.hh | 5 +++++ sdc/Clock.cc | 23 ++++------------------- search/PathEnd.cc | 2 +- search/Search.cc | 6 +++--- 5 files changed, 15 insertions(+), 25 deletions(-) diff --git a/include/sta/Clock.hh b/include/sta/Clock.hh index 8acc1e45..5a633ef0 100644 --- a/include/sta/Clock.hh +++ b/include/sta/Clock.hh @@ -90,7 +90,7 @@ public: // Return values. float &slew, bool &exists) const; - ClockUncertainties *uncertainties() const { return uncertainties_; } + const ClockUncertainties &uncertainties() const { return uncertainties_; } void uncertainty(const SetupHold *setup_hold, // Return values. float &uncertainty, @@ -180,7 +180,7 @@ protected: bool is_propagated_{false}; RiseFallMinMax slews_; RiseFallMinMax slew_limits_[path_clk_or_data_count]; - ClockUncertainties *uncertainties_{nullptr}; + ClockUncertainties uncertainties_; bool is_generated_{false}; // Generated clock variables. Pin *src_pin_{nullptr}; diff --git a/include/sta/MinMaxValues.hh b/include/sta/MinMaxValues.hh index 8fb8eeea..c365d613 100644 --- a/include/sta/MinMaxValues.hh +++ b/include/sta/MinMaxValues.hh @@ -169,6 +169,11 @@ public: static int cmp(const MinMaxValues *values1, const MinMaxValues *values2) { + if (!values1->exists_[MinMax::minIndex()] + && !values2->exists_[MinMax::minIndex()] + && !values1->exists_[MinMax::maxIndex()] + && !values2->exists_[MinMax::maxIndex()]) + return 0; if (!values1->exists_[MinMax::minIndex()] && values2->exists_[MinMax::minIndex()]) return -1; diff --git a/sdc/Clock.cc b/sdc/Clock.cc index c9d4d11a..21cd4d8d 100644 --- a/sdc/Clock.cc +++ b/sdc/Clock.cc @@ -240,42 +240,27 @@ Clock::uncertainty(const SetupHold *setup_hold, float &uncertainty, bool &exists) const { - if (uncertainties_) - uncertainties_->value(setup_hold, uncertainty, exists); - else { - uncertainty = 0.0F; - exists = false; - } + uncertainties_.value(setup_hold, uncertainty, exists); } void Clock::setUncertainty(const SetupHoldAll *setup_hold, float uncertainty) { - if (uncertainties_ == nullptr) - uncertainties_ = new ClockUncertainties; - uncertainties_->setValue(setup_hold, uncertainty); + uncertainties_.setValue(setup_hold, uncertainty); } void Clock::setUncertainty(const SetupHold *setup_hold, float uncertainty) { - if (uncertainties_ == nullptr) - uncertainties_ = new ClockUncertainties; - uncertainties_->setValue(setup_hold, uncertainty); + uncertainties_.setValue(setup_hold, uncertainty); } void Clock::removeUncertainty(const SetupHoldAll *setup_hold) { - if (uncertainties_) { - uncertainties_->removeValue(setup_hold); - if (uncertainties_->empty()) { - delete uncertainties_; - uncertainties_ = nullptr; - } - } + uncertainties_.removeValue(setup_hold); } void diff --git a/search/PathEnd.cc b/search/PathEnd.cc index 81920752..e917d89f 100644 --- a/search/PathEnd.cc +++ b/search/PathEnd.cc @@ -379,7 +379,7 @@ PathEnd::checkTgtClkUncertainty(const Path *tgt_clk_path, if (tgt_clk_path && tgt_clk_path->isClock(sta)) uncertainties = tgt_clk_path->clkInfo(sta)->uncertainties(); else if (tgt_clk_edge) - uncertainties = tgt_clk_edge->clock()->uncertainties(); + uncertainties = &tgt_clk_edge->clock()->uncertainties(); float uncertainty = 0.0; if (uncertainties) { bool exists; diff --git a/search/Search.cc b/search/Search.cc index d0d6b0ca..081daac8 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -1547,7 +1547,7 @@ Search::seedClkArrival(const Pin *pin, const ClockUncertainties *uncertainties = sdc->clockUncertainties(pin); if (uncertainties == nullptr) - uncertainties = clk->uncertainties(); + uncertainties = &clk->uncertainties(); // Propagate liberty "pulse_clock" transition to transitive fanout. LibertyPort *port = network_->libertyPort(pin); const RiseFall *pulse_clk_sense = (port ? port->pulseClkSense() : nullptr); @@ -1914,13 +1914,13 @@ Search::inputDelayTag(const Pin *pin, const Pin *clk_pin = nullptr; const RiseFall *clk_rf = nullptr; bool is_propagated = false; - ClockUncertainties *clk_uncertainties = nullptr; + const ClockUncertainties *clk_uncertainties = nullptr; if (clk_edge) { clk = clk_edge->clock(); clk_rf = clk_edge->transition(); clk_pin = clk->defaultPin(); is_propagated = clk->isPropagated(); - clk_uncertainties = clk->uncertainties(); + clk_uncertainties = &clk->uncertainties(); } Sdc *sdc = scene->sdc(); From 24ada4b22fee4814252b93495c8e4343f0e6a29e Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 25 Apr 2026 10:40:14 -0700 Subject: [PATCH 12/14] Scene::liberty_ use array Signed-off-by: James Cherry --- include/sta/Scene.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sta/Scene.hh b/include/sta/Scene.hh index 4807136f..2e2041d3 100644 --- a/include/sta/Scene.hh +++ b/include/sta/Scene.hh @@ -89,7 +89,7 @@ protected: std::string name_; size_t index_; Mode *mode_; - LibertySeq liberty_[MinMax::index_count]; + std::array liberty_; std::array parasitics_; friend class Scenes; From f3f608596a5323a3e144b9891f238aefe4b17d70 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 25 Apr 2026 13:46:45 -0700 Subject: [PATCH 13/14] leak Signed-off-by: James Cherry --- search/Sta.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/search/Sta.cc b/search/Sta.cc index dc6bfc04..9ccdc841 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -2309,13 +2309,16 @@ Sta::checkLibrarayPocv() GateTableModel *gate_model = arc->gateTableModel(); if (gate_model) { const TableModels *models = gate_model->delayModels(); - if (models->sigma(EarlyLate::early()) != nullptr) + if (models->sigma(EarlyLate::early()) != nullptr) { + delete lib_iter; return; + } } } } } } + delete lib_iter; report_->warn(1578, "No liberty POCV/LVF models found."); } From 1eb2e9b11d74989bb6e548f5a5d80446fc6d21f1 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 25 Apr 2026 14:45:49 -0700 Subject: [PATCH 14/14] untabify Signed-off-by: James Cherry --- dcalc/DelayNormal.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dcalc/DelayNormal.cc b/dcalc/DelayNormal.cc index c73de069..de26bfd9 100644 --- a/dcalc/DelayNormal.cc +++ b/dcalc/DelayNormal.cc @@ -121,7 +121,7 @@ DelayOpsNormal::greater(const Delay &delay1, const StaState *sta) const { return fuzzyGreater(delayAsFloat(delay1, EarlyLate::late(), sta), - delayAsFloat(delay2, EarlyLate::late(), sta)); + delayAsFloat(delay2, EarlyLate::late(), sta)); } bool @@ -130,7 +130,7 @@ DelayOpsNormal::greaterEqual(const Delay &delay1, const StaState *sta) const { return fuzzyGreaterEqual(delayAsFloat(delay1, EarlyLate::late(), sta), - delayAsFloat(delay2, EarlyLate::late(), sta)); + delayAsFloat(delay2, EarlyLate::late(), sta)); } Delay @@ -138,7 +138,7 @@ DelayOpsNormal::sum(const Delay &delay1, const Delay &delay2) const { return Delay(delay1.mean() + delay2.mean(), - delay1.stdDev2() + delay2.stdDev2()); + delay1.stdDev2() + delay2.stdDev2()); } Delay @@ -146,7 +146,7 @@ DelayOpsNormal::sum(const Delay &delay1, float delay2) const { return Delay(delay1.mean() + delay2, - delay1.stdDev2()); + delay1.stdDev2()); } Delay