From 6eb6911d303fbc274ac09b896ba921e12adfbbd2 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Wed, 6 May 2026 08:51:10 -0700 Subject: [PATCH 1/8] regression Signed-off-by: James Cherry --- test/regression.tcl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/regression.tcl b/test/regression.tcl index 523589be..f81f00ba 100755 --- a/test/regression.tcl +++ b/test/regression.tcl @@ -66,9 +66,11 @@ proc setup {} { set valgrind_shared_lib_failure 0 if { ![file exists $app_path] } { - error "$app_path not found." + puts "$app_path not found." + exit 1 } elseif { ![file executable $app_path] } { - error "$app_path is not executable." + puts "$app_path is not executable." + exit 1 } } From 7e68e452d36c3b0278d7d839ed6e49d15b87e4e3 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Thu, 7 May 2026 11:11:32 -0700 Subject: [PATCH 2/8] mv is_object to Util.i Signed-off-by: James Cherry --- tcl/StaTclTypes.i | 39 --------------------------------------- util/Util.i | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 39 deletions(-) diff --git a/tcl/StaTclTypes.i b/tcl/StaTclTypes.i index 8136bd60..c5eb3420 100644 --- a/tcl/StaTclTypes.i +++ b/tcl/StaTclTypes.i @@ -265,45 +265,6 @@ using namespace sta; %} -//////////////////////////////////////////////////////////////// - -%inline %{ - -bool -is_object(const char *obj) -{ - // _hexaddress_p_type - const std::string s(obj); - if (s.empty() || s[0] != '_') - return false; - const size_t hex_digits = sizeof(void *) * 2; - if (s.size() < 1 + hex_digits + 3) - return false; - for (size_t i = 1; i < 1 + hex_digits; i++) { - if (!std::isxdigit(static_cast(s[i]))) - return false; - } - if (s.compare(1 + hex_digits, 3, "_p_") != 0) - return false; - for (size_t i = 1 + hex_digits + 3; i < s.size(); i++) { - char ch = s[i]; - if (!(std::isalnum(ch) || ch == '_')) - return false; - } - return true; -} - -// Assumes is_object is true. -const char * -object_type(const char *obj) -{ - if (is_object(obj)) - return &obj[1 + sizeof(void*) * 2 + 3]; - return ""; -} - -%} - //////////////////////////////////////////////////////////////// // // SWIG type definitions. diff --git a/util/Util.i b/util/Util.i index ce128f5e..3a64c735 100644 --- a/util/Util.i +++ b/util/Util.i @@ -504,4 +504,39 @@ fuzzy_equal(float value1, return fuzzyEqual(value1, value2); } +//////////////////////////////////////////////////////////////// + +bool +is_object(const char *obj) +{ + // _hexaddress_p_type + const std::string s(obj); + if (s.empty() || s[0] != '_') + return false; + const size_t hex_digits = sizeof(void *) * 2; + if (s.size() < 1 + hex_digits + 3) + return false; + for (size_t i = 1; i < 1 + hex_digits; i++) { + if (!std::isxdigit(static_cast(s[i]))) + return false; + } + if (s.compare(1 + hex_digits, 3, "_p_") != 0) + return false; + for (size_t i = 1 + hex_digits + 3; i < s.size(); i++) { + char ch = s[i]; + if (!(std::isalnum(ch) || ch == '_')) + return false; + } + return true; +} + +// Assumes is_object is true. +const char * +object_type(const char *obj) +{ + if (is_object(obj)) + return &obj[1 + sizeof(void*) * 2 + 3]; + return ""; +} + %} // inline From 8cbd4002499810554de0585e4463710a5d3f5fdf Mon Sep 17 00:00:00 2001 From: James Cherry Date: Fri, 8 May 2026 10:10:21 -0700 Subject: [PATCH 3/8] Liberty power_down_function parse resolves #428 Signed-off-by: James Cherry --- include/sta/StringUtil.hh | 3 +++ liberty/LibertyParse.yy | 42 +++++++++---------------------------- liberty/LibertyParser.cc | 7 +++++++ liberty/LibertyReader.cc | 35 +++++++------------------------ liberty/LibertyReaderPvt.hh | 4 ---- util/StringUtil.cc | 26 +++++++++++++++++++++++ 6 files changed, 53 insertions(+), 64 deletions(-) diff --git a/include/sta/StringUtil.hh b/include/sta/StringUtil.hh index 35a8cda9..d5d2e184 100644 --- a/include/sta/StringUtil.hh +++ b/include/sta/StringUtil.hh @@ -91,6 +91,9 @@ stringEqual(std::string_view s1, std::pair stringFloat(const std::string &str); +std::pair +stringLong(const std::string &str, + int base = 10); bool isDigits(const char *str); diff --git a/liberty/LibertyParse.yy b/liberty/LibertyParse.yy index f19a7c1f..2b5ce05c 100644 --- a/liberty/LibertyParse.yy +++ b/liberty/LibertyParse.yy @@ -62,7 +62,7 @@ sta::LibertyParse::error(const location_type &loc, %define api.parser.class {LibertyParse} %define api.value.type variant -%expect 2 +%expect 0 %token STRING KEYWORD %token FLOAT @@ -75,8 +75,8 @@ sta::LibertyParse::error(const location_type &loc, %type statement complex_attr simple_attr variable group file %type attr_values %type attr_value -%type string expr expr_term expr_term1 volt_expr -%type expr_op volt_op +%type string expr expr_term expr_term1 +%type expr_op %start file @@ -157,36 +157,8 @@ string: ; attr_value: - FLOAT - { $$ = reader->makeAttrValueFloat($1); } -| expr + expr { $$ = reader->makeAttrValueString(std::move($1)); } -| volt_expr - { $$ = reader->makeAttrValueString(std::move($1)); } - ; - -/* Voltage expressions are ignored. */ -/* Crafted to avoid conflicts with expr */ -volt_expr: - FLOAT volt_op FLOAT - { $$ = sta::format("{}{}{}", $1, $2, $3); } -| string volt_op FLOAT - { $$ = sta::format("{}{}{}", $1, $2, $3); } -| FLOAT volt_op string - { $$ = sta::format("{}{}{}", $1, $2, $3); } -| volt_expr volt_op FLOAT - { $$ = sta::format("{}{}{}", $1, $2, $3); } - ; - -volt_op: - '+' - { $$ = '+'; } -| '-' - { $$ = '-'; } -| '*' - { $$ = '*'; } -| '/' - { $$ = '/'; } ; expr: @@ -197,6 +169,8 @@ expr: expr_term: string +| FLOAT + { $$ = sta::format("{}", $1); } | '0' { $$ = std::string("0"); } | '1' @@ -224,6 +198,10 @@ expr_op: { $$ = '&'; } | '^' { $$ = '^'; } +| '-' + { $$ = '-'; } +| '/' + { $$ = '/'; } ; semi_opt: diff --git a/liberty/LibertyParser.cc b/liberty/LibertyParser.cc index ee9ef6c6..26c0fefc 100644 --- a/liberty/LibertyParser.cc +++ b/liberty/LibertyParser.cc @@ -513,6 +513,13 @@ LibertyGroup::findAttrInt(std::string_view attr_name, exists = exists1; return; } + else { + const std::string &int_str = attr_value.stringValue(); + auto [value1, valid1] = stringLong(int_str); + value = value1; + exists = valid1; + return; + } } exists = false; } diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index 991cf88e..56d64408 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -2344,16 +2344,13 @@ LibertyReader::readReceiverCapacitance(const LibertyGroup *timing_group, std::string cap_group_name1 = sta::format("{}_{}", cap_group_name, rf->to_string()); const LibertyGroup *cap_group = timing_group->findSubgroup(cap_group_name1); if (cap_group) { - const LibertySimpleAttr *segment_attr = cap_group->findSimpleAttr("segment"); - if (segment_attr) { - // For receiver_capacitance groups with mulitiple segments this - // overrides the index passed in beginReceiverCapacitance1Rise/Fall. - int segment; - bool exists; - getAttrInt(segment_attr, segment, exists); - if (exists) - index = segment; - } + // For receiver_capacitance groups with mulitiple segments this + // overrides the index passed in beginReceiverCapacitance1Rise/Fall. + int segment; + bool exists; + cap_group->findAttrInt("segment", segment, exists); + if (exists) + index = segment; TableModel *model = readTableModel(cap_group, rf, TableTemplateType::delay, cap_scale_, ScaleFactorType::pin_cap); if (ReceiverModel::checkAxes(model)) { @@ -3224,24 +3221,6 @@ LibertyReader::makeFloatTable(const LibertyComplexAttr *values_attr, //////////////////////////////////////////////////////////////// -void -LibertyReader::getAttrInt(const LibertySimpleAttr *attr, - // Return values. - int &value, - bool &exists) -{ - value = 0; - exists = false; - const LibertyAttrValue &attr_value = attr->value(); - if (attr_value.isFloat()) { - auto [float_val, valid] = attr_value.floatValue(); - value = static_cast(float_val); - exists = true; - } - else - warn(1268, attr, "{} attribute is not an integer.", attr->name()); -} - // Get two floats in a complex attribute. // attr(float1, float2); void diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index cd4a1627..eabdc2cc 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -418,10 +418,6 @@ protected: StateInternalValues parseStateInternalValues(StringSeq &states, const LibertySimpleAttr *attr); - void getAttrInt(const LibertySimpleAttr *attr, - // Return values. - int &value, - bool &exists); void getAttrFloat2(const LibertyComplexAttr *attr, // Return values. float &value1, diff --git a/util/StringUtil.cc b/util/StringUtil.cc index 88ad9764..5e639557 100644 --- a/util/StringUtil.cc +++ b/util/StringUtil.cc @@ -78,6 +78,32 @@ stringFloat(const std::string &str) #endif } +std::pair +stringLong(const std::string &str, + int base) +{ + long long value; +#if defined(__cpp_lib_to_chars) && __cpp_lib_to_chars >= 201611L + auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), value, base); + + // Check for success and that we consumed the entire string + if (ec == std::errc() && ptr == str.data() + str.size()) + return {value, true}; + else + return {0LL, false}; +#else + char *ptr; + errno = 0; + // strtoll handles "long long" specifically + value = std::strtoll(str.data(), &ptr, base); + + if (errno == ERANGE || *ptr != '\0' || ptr == str.data()) + return {0LL, false}; + else + return {value, true}; +#endif +} + void trimRight(std::string &str) { From 30f862bf867267234a2a326689936770dae43e3d Mon Sep 17 00:00:00 2001 From: James Cherry Date: Mon, 11 May 2026 11:09:23 -0700 Subject: [PATCH 4/8] ord ctest turds Signed-off-by: James Cherry --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index c0aabe31..eff337d1 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,6 @@ doc/messages.txt # clangd turds .cache/ + +# openroad ctest turds +cmake_test* From 4c8ef5b84ab5ad89ad364b2127c64800a293156f Mon Sep 17 00:00:00 2001 From: James Cherry Date: Tue, 12 May 2026 11:24:24 -0700 Subject: [PATCH 5/8] make report field Signed-off-by: James Cherry --- include/sta/Sta.hh | 19 +++-- network/Network.i | 10 ++- search/ReportPath.cc | 179 ++++++++++++++++++++++++------------------- search/ReportPath.hh | 112 +++++++++++++++------------ search/Search.i | 53 ++++++++----- search/Search.tcl | 40 +++------- search/Sta.cc | 31 +++++--- 7 files changed, 249 insertions(+), 195 deletions(-) diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 5237ec9a..91a3b224 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -83,6 +83,8 @@ using CheckErrorSeq = std::vector; enum class CmdNamespace { sta, sdc }; using ParasiticsNameMap = std::map>; using GraphLoopSeq = std::vector; +using ReportFieldGetValue = std::function; // Initialize sta functions that are not part of the Sta class. void initSta(); @@ -982,15 +984,16 @@ public: bool clk_gating_hold); void setReportPathFormat(ReportPathFormat format); void setReportPathFieldOrder(const StringSeq &field_names); - void setReportPathFields(bool report_input_pin, - bool report_hier_pins, - bool report_net, - bool report_cap, - bool report_slew, - bool report_fanout, - bool report_variation, - bool report_src_attr); + void setReportPathFields(const StringSeq &fields); ReportField *findReportPathField(std::string_view name); + ReportField *findReportPathFieldAbrev(std::string_view name); + void makeReportPathField(std::string_view name, + std::string_view name_abrev, + std::string_view title, + size_t width, + bool left_justify, + Unit *unit, + const ReportFieldGetValue &get_value); void setReportPathDigits(int digits); void setReportPathNoSplit(bool no_split); void reportPathEnd(PathEnd *end); diff --git a/network/Network.i b/network/Network.i index 30cfff61..b35855c8 100644 --- a/network/Network.i +++ b/network/Network.i @@ -655,6 +655,15 @@ get_attribute(const char *key) return Sta::sta()->ensureLinked()->getAttribute(self, key); } +void +set_attribute(const char *key, + const char *value) +{ + sta::Sta *sta = Sta::sta(); + sta->ensureLinked(); + sta->networkReader()->setAttribute(self, key, value); +} + } // Instance methods %extend InstanceChildIterator { @@ -813,4 +822,3 @@ bool has_next() { return self->hasNext(); } const Pin *next() { return self->next(); } void finish() { delete self; } } // NetConnectedPinIterator methods - diff --git a/search/ReportPath.cc b/search/ReportPath.cc index 50d05574..4b99f4a9 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -81,23 +81,22 @@ hierPinsThruEdge(const Edge *edge, const Graph *graph); ReportField::ReportField(std::string_view name, + std::string_view name_abrev, std::string_view title, size_t width, bool left_justify, Unit *unit, - bool enabled) : + ReportFieldGetValue get_value) : name_(name), + name_abrev_(name_abrev), title_(title), left_justify_(left_justify), unit_(unit), - enabled_(enabled) + get_value_(get_value) { setWidth(width); } -ReportField::~ReportField() -= default; - void ReportField::setProperties(std::string_view title, size_t width, @@ -121,72 +120,85 @@ ReportField::setEnabled(bool enabled) enabled_ = enabled; } +std::string +ReportField::value(const Path *path, + const StaState *sta) const +{ + return get_value_(path, sta); +} + //////////////////////////////////////////////////////////////// ReportPath::ReportPath(StaState *sta) : StaState(sta) { makeFields(); + setReportFields({"incr", "total", "edge", "description"}); setDigits(2); - setReportFields(false, false, false, false, false, false, false, false); } ReportPath::~ReportPath() { - delete field_description_; - delete field_total_; - delete field_incr_; - delete field_capacitance_; - delete field_slew_; - delete field_fanout_; - delete field_variation_; - delete field_src_attr_; - delete field_edge_; - delete field_case_; + deleteContents(fields_); } void ReportPath::makeFields() { // The order corresponds to the default field order. - field_fanout_ = makeField("fanout", "Fanout", 6, false, nullptr, true); - field_capacitance_ = makeField("capacitance", "Cap", 6, false, - units_->capacitanceUnit(), true); - field_slew_ = makeField("slew", "Slew", 6, false, units_->timeUnit(), - true); - field_incr_ = makeField("incr", "Delay", 6, false, units_->timeUnit(), - true); - field_variation_ = makeField("variation", "Variation", 6, false, - units_->timeUnit(), false); - field_total_ = makeField("total", "Time", 6, false, units_->timeUnit(), - true); - field_edge_ = makeField("edge", "", 1, false, nullptr, true); - field_case_ = makeField("case", "case", 11, false, nullptr, false); - field_description_ = makeField("description", "Description", 36, - true, nullptr, true); - field_src_attr_ = makeField("src_attr", "Src Attr", 40, - true, nullptr, true); + field_fanout_ = makeField("fanout", "fanout", "Fanout", 6, false, nullptr); + field_capacitance_ = makeField("capacitance", "cap", "Cap", 6, false, + units_->capacitanceUnit()); + field_slew_ = makeField("slew", "slew", "Slew", 6, false, units_->timeUnit()); + field_incr_ = makeField("incr", "incr", "Delay", 6, false, units_->timeUnit()); + field_variation_ = makeField("variation", "var", "Variation", 6, false, + units_->timeUnit()); + field_total_ = makeField("total", "total", "Time", 6, false, units_->timeUnit()); + field_edge_ = makeField("edge", "edge", "", 1, false, nullptr); + field_case_ = makeField("case", "case", "case", 11, false, nullptr); + field_description_ = makeField("description", "desc", "Description", 36, true, nullptr); + field_src_attr_ = makeField("src_attr", "src", "Src Attr", 40, true, nullptr); +} + +ReportField * +ReportPath::makeField(std::string_view name, + std::string_view name_abrev, + std::string_view title, + size_t width, + bool left_justify, + Unit *unit) +{ + return makeField(name, name_abrev, title, width, left_justify, unit, nullptr); } ReportField * ReportPath::makeField(std::string_view name, + std::string_view name_abrev, std::string_view title, - int width, + size_t width, bool left_justify, Unit *unit, - bool enabled) + ReportFieldGetValue get_value) { - ReportField *field = new ReportField(name, title, width, left_justify, - unit, enabled); + ReportField *field = new ReportField(name, name_abrev, title, width, left_justify, + unit, get_value); fields_.push_back(field); + field_map_[std::string(name)] = field; return field; } ReportField * -ReportPath::findField(std::string_view name) const +ReportPath::findField(std::string_view name) +{ + return findKey(field_map_, std::string(name)); +} + +ReportField * +ReportPath::findFieldAbrev(std::string_view name) { for (ReportField *field : fields_) { - if (field->name() == name) + const std::string &name_abrev = field->nameAbrev(); + if (name.substr(0, name_abrev.size()) == name_abrev) return field; } return nullptr; @@ -213,32 +225,38 @@ ReportPath::setReportFieldOrder(const StringSeq &field_names) next_fields.push_back(field); } - fields_.clear(); - for (ReportField *field : next_fields) - fields_.push_back(field); + fields_ = next_fields; } void -ReportPath::setReportFields(bool report_input_pin, - bool report_hier_pins, - bool report_net, - bool report_cap, - bool report_slew, - bool report_fanout, - bool report_variation, - bool report_src_attr) +ReportPath::setReportFields(const StringSeq &fields) { - report_input_pin_ = report_input_pin; - report_hier_pins_ = report_hier_pins; - report_net_ = report_net; - - field_capacitance_->setEnabled(report_cap); - field_slew_->setEnabled(report_slew); - field_fanout_->setEnabled(report_fanout); - field_variation_->setEnabled(report_variation); - field_src_attr_->setEnabled(report_src_attr); - // for debug - field_case_->setEnabled(false); + for (ReportField *field : fields_) + field->setEnabled(false); + field_incr_->setEnabled(true); + field_total_->setEnabled(true); + field_description_->setEnabled(true); + field_edge_->setEnabled(true); + // These are not real fields; they are flags. + report_input_pin_ = false; + report_hier_pins_ = false; + report_net_ = false; + + for (const std::string &field_name : fields) { + if (field_name == "input_pin") + report_input_pin_ = true; + else if (field_name == "hierarchical_pin") + report_hier_pins_ = true; + else if (field_name == "net") + report_net_ = true; + else { + ReportField *field = findField(field_name); + if (field) + field->setEnabled(true); + else + report_->warn(2720, "unknown path reporting field {}.", field_name); + } + } } void @@ -2454,7 +2472,7 @@ ReportPath::reportPathLine(const Path *path, // Don't show capacitance field for input pins. if (is_driver && field_capacitance_->enabled()) cap = graph_delay_calc_->loadCap(pin, rf, scene, min_max); - reportLine(what, cap, slew, field_blank_, incr, field_blank_, + reportLine(what, path, cap, slew, field_blank_, incr, field_blank_, time, false, early_late, rf, src_attr, line_case); } @@ -2823,13 +2841,13 @@ ReportPath::reportPath6(const Path *path, if (field_fanout_->enabled()) fanout = drvrFanout(vertex, scene, min_max); const std::string what = descriptionField(vertex); - reportLine(what, cap, slew, fanout, + reportLine(what, path1, cap, slew, fanout, incr, field_blank_, time, false, min_max, rf, src_attr, line_case); if (report_net_) { const std::string what2 = descriptionNet(pin); - reportLine(what2, field_blank_, field_blank_, field_blank_, + reportLine(what2, path1, field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, false, min_max, nullptr, src_attr, ""); } @@ -2842,7 +2860,7 @@ ReportPath::reportPath6(const Path *path, || (i == path_last_index) || is_clk_start) { const std::string what = descriptionField(vertex); - reportLine(what, field_blank_, slew, field_blank_, + reportLine(what, path1, field_blank_, slew, field_blank_, incr, field_blank_, time, false, min_max, rf, src_attr, line_case); prev_time = time; @@ -2867,27 +2885,27 @@ ReportPath::reportVariation(const Path *path) const switch (variables_->pocvMode()) { case PocvMode::normal: { float std_dev = arc_delay.stdDev(); - reportLine("sigma", field_blank_, field_blank_, field_blank_, + reportLine("sigma", path, field_blank_, field_blank_, field_blank_, field_blank_, std_dev, field_blank_, true, min_max, nullptr, "", ""); break; } case PocvMode::skew_normal: { float mean = arc_delay.mean(); - reportLine("mean", field_blank_, field_blank_, field_blank_, + reportLine("mean", path, field_blank_, field_blank_, field_blank_, field_blank_, mean, field_blank_, true, min_max, nullptr, "", ""); float mean_shift = arc_delay.meanShift(); - reportLine("mean_shift", field_blank_, field_blank_, field_blank_, + reportLine("mean_shift", path, field_blank_, field_blank_, field_blank_, field_blank_, mean_shift, field_blank_, true, min_max, nullptr, "", ""); float std_dev = arc_delay.stdDev(); - reportLine("std_dev", field_blank_, field_blank_, field_blank_, + reportLine("std_dev", path, field_blank_, field_blank_, field_blank_, field_blank_, std_dev, field_blank_, true, min_max, nullptr, "", ""); // skewness is dimensionless, so scale it to the field's time units. float skewness = arc_delay.skewness() * units_->timeUnit()->scale(); - reportLine("skewness", field_blank_, field_blank_, field_blank_, + reportLine("skewness", path, field_blank_, field_blank_, field_blank_, field_blank_, skewness, field_blank_, true, min_max, nullptr, "", ""); break; @@ -2915,9 +2933,9 @@ ReportPath::reportHierPinsThru(const Path *path) const if (prev_edge && prev_edge->isWire()) { for (const Pin *hpin : hierPinsThruEdge(prev_edge, network_, graph_)) { const std::string what = descriptionField(hpin); - reportLine(what, field_blank_, field_blank_, field_blank_, - field_blank_, field_blank_, field_blank_, false, path->minMax(this), - nullptr, "", ""); + reportLine(what, path, field_blank_, field_blank_, field_blank_, + field_blank_, field_blank_, field_blank_, false, + path->minMax(this), nullptr, "", ""); } } } @@ -3109,7 +3127,7 @@ ReportPath::reportLine(std::string_view what, Delay total, const EarlyLate *early_late) const { - reportLine(what, field_blank_, field_blank_, field_blank_, field_blank_, + reportLine(what, nullptr, field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, total, false, early_late, nullptr, "", ""); } @@ -3119,7 +3137,7 @@ ReportPath::reportLineNegative(std::string_view what, Delay total, const EarlyLate *early_late) const { - reportLine(what, field_blank_, field_blank_, field_blank_, + reportLine(what, nullptr, field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, total, true /* tota_with_minus */, early_late, nullptr, "", ""); } @@ -3131,7 +3149,7 @@ ReportPath::reportLine(std::string_view what, const EarlyLate *early_late, const RiseFall *rf) const { - reportLine(what, field_blank_, field_blank_, field_blank_, + reportLine(what, nullptr, field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, total, false, early_late, rf, "", ""); } @@ -3142,7 +3160,7 @@ ReportPath::reportLine(std::string_view what, const Delay &total, const EarlyLate *early_late) const { - reportLine(what, field_blank_, field_blank_, field_blank_, + reportLine(what, nullptr, field_blank_, field_blank_, field_blank_, incr, field_blank_, total, false, early_late, nullptr, "", ""); } @@ -3154,7 +3172,7 @@ ReportPath::reportLine(std::string_view what, const EarlyLate *early_late, const RiseFall *rf) const { - reportLine(what, field_blank_, field_blank_, field_blank_, + reportLine(what, nullptr, field_blank_, field_blank_, field_blank_, incr, field_blank_, total, false, early_late, rf, "", ""); } @@ -3166,12 +3184,13 @@ ReportPath::reportLine(std::string_view what, const Delay &total, const EarlyLate *early_late) const { - reportLine(what, field_blank_, slew, field_blank_, + reportLine(what, nullptr, field_blank_, slew, field_blank_, incr, field_blank_, total, false, early_late, nullptr, "", ""); } void ReportPath::reportLine(std::string_view what, + const Path *path, float cap, const Slew &slew, float fanout, @@ -3234,6 +3253,8 @@ ReportPath::reportLine(std::string_view what, } else if (field == field_case_) line += line_case; + else if (field->getValue()) + line += field->value(path, this); first_field = false; } diff --git a/search/ReportPath.hh b/search/ReportPath.hh index b8ce652d..c096e4eb 100644 --- a/search/ReportPath.hh +++ b/search/ReportPath.hh @@ -25,6 +25,7 @@ #pragma once #include +#include #include #include #include @@ -49,9 +50,51 @@ namespace sta { class Scene; class PathExpanded; -class ReportField; + +using ReportFieldGetValue = std::function; + +class ReportField +{ +public: + ReportField(std::string_view name, + std::string_view name_abrev, + std::string_view title, + size_t width, + bool left_justify, + Unit *unit, + ReportFieldGetValue get_value); + void setProperties(std::string_view title, + size_t width, + bool left_justify); + const std::string &name() const { return name_; } + const std::string &nameAbrev() const { return name_abrev_; } + const std::string &title() const { return title_; } + size_t width() const { return width_; } + void setWidth(size_t width); + bool leftJustify() const { return left_justify_; } + Unit *unit() const { return unit_; } + const std::string &blank() const { return blank_; } + void setEnabled(bool enabled); + bool enabled() const { return enabled_; } + std::string value(const Path *path, + const StaState *sta) const; + const ReportFieldGetValue &getValue() const { return get_value_; } + +protected: + std::string name_; + std::string name_abrev_; + std::string title_; + size_t width_; + bool left_justify_; + Unit *unit_; + bool enabled_{false}; + ReportFieldGetValue get_value_; + std::string blank_; +}; using ReportFieldSeq = std::vector; +using ReportFieldMap = std::map>; class ReportPath : public StaState { @@ -61,18 +104,12 @@ public: ReportPathFormat pathFormat() const { return format_; } void setPathFormat(ReportPathFormat format); void setReportFieldOrder(const 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_variation, - bool report_src_attr); + void setReportFields(const StringSeq &fields); int digits() const { return digits_; } void setDigits(int digits); void setNoSplit(bool no_split); - ReportField *findField(std::string_view name) const; + ReportField *findField(std::string_view name); + ReportField *findFieldAbrev(std::string_view name); // Header above reportPathEnd results. void reportPathEndHeader() const; @@ -165,6 +202,15 @@ public: float slack, const Scene *scene, const MinMax *min_max) const; + + ReportField *makeField(std::string_view name, + std::string_view name_abrev, + std::string_view title, + size_t width, + bool left_justify, + // nullptr for string fields. + Unit *unit, + ReportFieldGetValue get_value); ReportField *fieldSlew() const { return field_slew_; } ReportField *fieldFanout() const { return field_fanout_; } ReportField *fieldCapacitance() const { return field_capacitance_; } @@ -173,11 +219,11 @@ public: protected: void makeFields(); ReportField *makeField(std::string_view name, + std::string_view name_abrev, std::string_view title, - int width, + size_t width, bool left_justify, - Unit *unit, - bool enabled); + Unit *unit); void reportEndpointHeader(const PathEnd *end, const PathEnd *prev_end) const; void reportShort(const PathEndUnconstrained *end, @@ -370,6 +416,7 @@ protected: const Delay &total, const EarlyLate *early_late) const; void reportLine(std::string_view what, + const Path *path, float cap, const Slew &slew, float fanout, @@ -483,15 +530,14 @@ protected: // Path options. ReportPathFormat format_{ReportPathFormat::full}; - ReportFieldSeq fields_; bool report_input_pin_; bool report_hier_pins_; bool report_net_; bool no_split_{false}; int digits_; - size_t start_end_pt_width_{80}; - + ReportFieldMap field_map_; + ReportFieldSeq fields_; ReportField *field_description_; ReportField *field_total_; ReportField *field_incr_; @@ -507,41 +553,9 @@ protected: std::string minus_zero_; int field_width_extra_{5}; + size_t start_end_pt_width_{80}; static constexpr float field_blank_ = -1; static const float field_skip_; }; -class ReportField -{ -public: - ReportField(std::string_view name, - std::string_view title, - size_t width, - bool left_justify, - Unit *unit, - bool enabled); - ~ReportField(); - void setProperties(std::string_view title, - size_t width, - bool left_justify); - const std::string &name() const { return name_; } - const std::string &title() const { return title_; } - size_t width() const { return width_; } - void setWidth(size_t width); - bool leftJustify() const { return left_justify_; } - Unit *unit() const { return unit_; } - const std::string &blank() const { return blank_; } - void setEnabled(bool enabled); - bool enabled() const { return enabled_; } - -protected: - std::string name_; - std::string title_; - size_t width_; - bool left_justify_; - Unit *unit_; - bool enabled_; - std::string blank_; -}; - } // namespace sta diff --git a/search/Search.i b/search/Search.i index c378a5e8..dbf3dc0f 100644 --- a/search/Search.i +++ b/search/Search.i @@ -401,29 +401,46 @@ set_report_path_format(ReportPathFormat format) } void -set_report_path_field_order(const StringSeq &field_names) +set_report_path_field_order(StringSeq field_names) { Sta::sta()->setReportPathFieldOrder(field_names); } void -set_report_path_fields(bool report_input_pin, - bool report_hier_pins, - bool report_net, - bool report_cap, - bool report_slew, - bool report_fanout, - bool report_variation, - bool report_src_attr) -{ - Sta::sta()->setReportPathFields(report_input_pin, - report_hier_pins, - report_net, - report_cap, - report_slew, - report_fanout, - report_variation, - report_src_attr); +set_report_path_fields(StringSeq fields) +{ + Sta::sta()->setReportPathFields(fields); +} + +void +make_report_path_attr_field(std::string attr_name, + int width) +{ + Sta *sta = Sta::sta(); + sta->makeReportPathField(attr_name, attr_name, attr_name, width, true, + nullptr, + [attr_name] (const Path *path, + const StaState *sta) -> std::string { + if (path) { + const Network *network = sta->network(); + const Pin *pin = path->pin(sta); + const Instance *inst = network->instance(pin); + return network->getAttribute(inst, attr_name); + } + else + return ""; + }); +} + +const char * +find_report_path_field_abrev(const char *name) +{ + Sta *sta = Sta::sta(); + ReportField *field = sta->findReportPathFieldAbrev(name); + if (field) + return field->name().c_str(); + else + return ""; } void diff --git a/search/Search.tcl b/search/Search.tcl index 11394292..6d3c7223 100644 --- a/search/Search.tcl +++ b/search/Search.tcl @@ -158,8 +158,6 @@ proc find_timing_paths_cmd { cmd args_var } { sta_error 511 "$cmd command failed." } - check_for_key_args $cmd args - if { [info exists flags(-unconstrained)] } { set unconstrained 1 } elseif { [info exists sta_report_unconstrained_paths] } { @@ -230,7 +228,6 @@ proc find_timing_paths_cmd { cmd args_var } { sta_error 515 "positional arguments not supported." } } - set path_ends [find_path_ends $from $thrus $to $unconstrained \ $scenes $min_max \ $group_path_count $endpoint_path_count \ @@ -716,41 +713,26 @@ proc parse_report_path_options { cmd args_var default_format set path_options(num_fmt) "%.${digits}f" set_report_path_digits $digits - set report_input_pin 0 - set report_hier_pins 0 - set report_cap 0 - set report_net 0 - set report_slew 0 - set report_fanout 0 - set report_variation 0 - set report_src_attr 0 + set fields {} if { [info exists path_options(-fields)] } { foreach field $path_options(-fields) { if { [string match "input*" $field] } { - set report_input_pin 1 + lappend fields "input_pin" } elseif { [string match "hier*" $field] } { - set report_hier_pins 1 - } elseif { [string match "cap*" $field] } { - set report_cap 1 + lappend fields "hierarchical_pin" } elseif { [string match "net" $field] } { - set report_net 1 - } elseif { [string match "slew" $field] } { - set report_slew 1 - } elseif { [string match "fanout" $field] } { - set report_fanout 1 - } elseif { [string match "variation" $field] } { - set report_variation 1 - } elseif { [string match "src*" $field] } { - set report_src_attr 1 + lappend fields "net" } else { - sta_warn 168 "unknown field $field." + set field_name [find_report_path_field_abrev $field] + if { $field_name != "" } { + lappend fields $field_name + } else { + sta_warn 168 "unknown field $field." + } } } } - - set_report_path_fields $report_input_pin $report_hier_pins $report_net \ - $report_cap $report_slew $report_fanout $report_variation $report_src_attr - + set_report_path_fields $fields set_report_path_no_split [info exists path_options(-no_line_splits)] } diff --git a/search/Sta.cc b/search/Sta.cc index c5a40139..5d042594 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -2816,18 +2816,9 @@ Sta::setReportPathFieldOrder(const StringSeq &field_names) } void -Sta::setReportPathFields(bool report_input_pin, - bool report_hier_pins, - bool report_net, - bool report_cap, - bool report_slew, - bool report_fanout, - bool report_variation, - bool report_src_attr) +Sta::setReportPathFields(const StringSeq &fields) { - report_path_->setReportFields(report_input_pin, report_hier_pins, report_net, - report_cap, report_slew, report_fanout, - report_variation, report_src_attr); + report_path_->setReportFields(fields); } ReportField * @@ -2836,6 +2827,24 @@ Sta::findReportPathField(std::string_view name) return report_path_->findField(name); } +ReportField * +Sta::findReportPathFieldAbrev(std::string_view name) +{ + return report_path_->findFieldAbrev(name); +} + +void +Sta::makeReportPathField(std::string_view name, + std::string_view name_abrev, + std::string_view title, + size_t width, + bool left_justify, + Unit *unit, + const ReportFieldGetValue &get_value) +{ + report_path_->makeField(name, name_abrev, title, width, left_justify, unit, get_value); +} + void Sta::setReportPathDigits(int digits) { From 17380215ef0cde2d0eb201031945b461c6993f0b Mon Sep 17 00:00:00 2001 From: Deepashree Sengupta Date: Wed, 13 May 2026 12:59:35 -0400 Subject: [PATCH 6/8] expose levelizeobserver (#433) Signed-off-by: dsengupta0628 --- include/sta/LevelizeObserver.hh | 59 +++++++++++++++++++++++++++++++++ include/sta/Sta.hh | 5 +++ search/Levelize.hh | 10 +----- search/Sta.cc | 19 ++++------- 4 files changed, 71 insertions(+), 22 deletions(-) create mode 100644 include/sta/LevelizeObserver.hh diff --git a/include/sta/LevelizeObserver.hh b/include/sta/LevelizeObserver.hh new file mode 100644 index 00000000..787d8054 --- /dev/null +++ b/include/sta/LevelizeObserver.hh @@ -0,0 +1,59 @@ +// OpenSTA, Static Timing Analyzer +// Copyright (c) 2026, 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 . +// +// 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 + +namespace sta { + +class Vertex; +class Search; +class GraphDelayCalc; + +// Observer fired by Levelize during (re)levelization. Downstream consumers +// override the two hooks to invalidate caches that depend on vertex levels. +class LevelizeObserver +{ +public: + virtual ~LevelizeObserver() = default; + virtual void levelsChangedBefore() = 0; + virtual void levelChangedBefore(Vertex *vertex) = 0; +}; + +// Default observer installed by Sta::makeObservers. Forwards level-change +// events to Search and GraphDelayCalc so their internal caches stay +// consistent. Subclass and override to extend (call the base methods first, +// then add your own invalidation). +class StaLevelizeObserver : public LevelizeObserver +{ +public: + StaLevelizeObserver(Search *search, GraphDelayCalc *graph_delay_calc); + void levelsChangedBefore() override; + void levelChangedBefore(Vertex *vertex) override; + +private: + Search *search_; + GraphDelayCalc *graph_delay_calc_; +}; + +} // namespace sta diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 91a3b224..6bc3c8eb 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -73,6 +73,7 @@ class ClkSkews; class ReportField; class EquivCells; class StaSimObserver; +class LevelizeObserver; class GraphLoop; using ModeNameMap = std::map>; @@ -1324,6 +1325,10 @@ public: // Ensure a network has been read, linked and liberty libraries exist. Network *ensureLibLinked(); void ensureLevelized(); + // Replace the Levelize observer. Takes ownership; deletes any prior + // observer. Subclass StaLevelizeObserver to extend the default behavior + // (Search + GraphDelayCalc forwarding) without re-implementing it. + void setLevelizeObserver(LevelizeObserver *observer); // Ensure that the timing graph has been built. Graph *ensureGraph(); void ensureClkArrivals(); diff --git a/search/Levelize.hh b/search/Levelize.hh index a1b680e8..094e3d47 100644 --- a/search/Levelize.hh +++ b/search/Levelize.hh @@ -30,11 +30,11 @@ #include "Graph.hh" #include "StaState.hh" +#include "sta/LevelizeObserver.hh" namespace sta { class SearchPred; -class LevelizeObserver; class GraphLoop; using VertexEdgeIterPair = std::pair; @@ -133,12 +133,4 @@ private: EdgeSeq *edges_; }; -class LevelizeObserver -{ -public: - virtual ~LevelizeObserver() = default; - virtual void levelsChangedBefore() = 0; - virtual void levelChangedBefore(Vertex *vertex) = 0; -}; - } // namespace sta diff --git a/search/Sta.cc b/search/Sta.cc index 5d042594..bdbf6e93 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -217,19 +217,6 @@ StaSimObserver::fanoutEdgesChangeAfter(const Pin *pin) //////////////////////////////////////////////////////////////// -class StaLevelizeObserver : public LevelizeObserver -{ -public: - StaLevelizeObserver(Search *search, - GraphDelayCalc *graph_delay_calc); - void levelsChangedBefore() override; - void levelChangedBefore(Vertex *vertex) override; - -private: - Search *search_; - GraphDelayCalc *graph_delay_calc_; -}; - StaLevelizeObserver::StaLevelizeObserver(Search *search, GraphDelayCalc *graph_delay_calc) : search_(search), @@ -3755,6 +3742,12 @@ Sta::ensureLevelized() levelize_->ensureLevelized(); } +void +Sta::setLevelizeObserver(LevelizeObserver *observer) +{ + levelize_->setObserver(observer); +} + void Sta::updateGeneratedClks() { From 1475ab0fae0c7d94ded5e26052ee034303f5a145 Mon Sep 17 00:00:00 2001 From: dsengupta0628 Date: Thu, 14 May 2026 21:01:39 +0000 Subject: [PATCH 7/8] upstream changes 5/14 plus fix report generic field Signed-off-by: dsengupta0628 --- search/ReportPath.cc | 37 +++++++------------------- search/ReportPath.hh | 3 --- search/Search.tcl | 2 +- search/test/cpp/TestReportFields.hh | 13 +++++++++ search/test/cpp/TestSearchStaDesign.cc | 5 ++-- search/test/cpp/TestSearchStaInit.cc | 22 ++++++++------- search/test/cpp/TestSearchStaInitB.cc | 11 ++++---- 7 files changed, 46 insertions(+), 47 deletions(-) create mode 100644 search/test/cpp/TestReportFields.hh diff --git a/search/ReportPath.cc b/search/ReportPath.cc index 4a3e9922..4b99f4a9 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -2469,11 +2469,6 @@ ReportPath::reportPathLine(const Path *path, std::string src_attr; if (inst) src_attr = network_->getAttribute(inst, "src"); - std::string orig_name; - if (inst && field_orig_name_->enabled()) { - std::string port_name = network_->portName(pin); - orig_name = network_->getAttribute(inst, "orig_name_" + port_name); - } // Don't show capacitance field for input pins. if (is_driver && field_capacitance_->enabled()) cap = graph_delay_calc_->loadCap(pin, rf, scene, min_max); @@ -2756,11 +2751,6 @@ ReportPath::reportPath6(const Path *path, std::string src_attr; if (inst) src_attr = network_->getAttribute(inst, "src"); - std::string orig_name; - if (inst && field_orig_name_->enabled()) { - std::string port_name = network_->portName(pin); - orig_name = network_->getAttribute(inst, "orig_name_" + port_name); - } // Always show the search start point (register clk pin). // Skip reporting the clk tree unless it is requested. if (is_clk_start @@ -2853,13 +2843,13 @@ ReportPath::reportPath6(const Path *path, const std::string what = descriptionField(vertex); reportLine(what, path1, cap, slew, fanout, incr, field_blank_, time, false, min_max, rf, src_attr, - orig_name, line_case); + line_case); if (report_net_) { const std::string what2 = descriptionNet(pin); reportLine(what2, path1, field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, false, min_max, - nullptr, src_attr, "", ""); + nullptr, src_attr, ""); } prev_time = time; } @@ -2872,7 +2862,7 @@ ReportPath::reportPath6(const Path *path, const std::string what = descriptionField(vertex); reportLine(what, path1, field_blank_, slew, field_blank_, incr, field_blank_, time, false, min_max, rf, src_attr, - orig_name, line_case); + line_case); prev_time = time; } } @@ -2897,27 +2887,27 @@ ReportPath::reportVariation(const Path *path) const float std_dev = arc_delay.stdDev(); reportLine("sigma", path, field_blank_, field_blank_, field_blank_, field_blank_, std_dev, field_blank_, true, min_max, - nullptr, "", "", ""); + nullptr, "", ""); break; } case PocvMode::skew_normal: { float mean = arc_delay.mean(); reportLine("mean", path, field_blank_, field_blank_, field_blank_, field_blank_, mean, field_blank_, true, min_max, - nullptr, "", "", ""); + nullptr, "", ""); float mean_shift = arc_delay.meanShift(); reportLine("mean_shift", path, field_blank_, field_blank_, field_blank_, field_blank_, mean_shift, field_blank_, true, min_max, - nullptr, "", "", ""); + nullptr, "", ""); float std_dev = arc_delay.stdDev(); reportLine("std_dev", path, field_blank_, field_blank_, field_blank_, field_blank_, std_dev, field_blank_, true, min_max, - nullptr, "", "", ""); + nullptr, "", ""); // skewness is dimensionless, so scale it to the field's time units. float skewness = arc_delay.skewness() * units_->timeUnit()->scale(); reportLine("skewness", path, field_blank_, field_blank_, field_blank_, field_blank_, skewness, field_blank_, true, min_max, - nullptr, "", "", ""); + nullptr, "", ""); break; } default: @@ -3149,7 +3139,7 @@ ReportPath::reportLineNegative(std::string_view what, { reportLine(what, nullptr, field_blank_, field_blank_, field_blank_, field_blank_, field_blank_, total, true /* tota_with_minus */, - early_late, nullptr, "", "", ""); + early_late, nullptr, "", ""); } // Report total, and transition suffix. @@ -3211,7 +3201,6 @@ ReportPath::reportLine(std::string_view what, const EarlyLate *early_late, const RiseFall *rf, std::string_view src_attr, - std::string_view orig_name, std::string_view line_case) const { std::string line; @@ -3219,7 +3208,7 @@ ReportPath::reportLine(std::string_view what, bool first_field = true; for (const ReportField *field : fields_) { bool last_field = field_index == (fields_.size() - 1); - + if (field->enabled()) { if (!first_field) line += ' '; @@ -3262,12 +3251,6 @@ ReportPath::reportLine(std::string_view what, else reportFieldBlank(field, line); } - else if (field == field_orig_name_) { - if (orig_name != "") - reportField(orig_name, field, line); - else - reportFieldBlank(field, line); - } else if (field == field_case_) line += line_case; else if (field->getValue()) diff --git a/search/ReportPath.hh b/search/ReportPath.hh index ee04d7d1..c096e4eb 100644 --- a/search/ReportPath.hh +++ b/search/ReportPath.hh @@ -215,7 +215,6 @@ public: ReportField *fieldFanout() const { return field_fanout_; } ReportField *fieldCapacitance() const { return field_capacitance_; } ReportField *fieldSrcAttr() const { return field_src_attr_; } - ReportField *fieldOrigName() const { return field_orig_name_; } protected: void makeFields(); @@ -428,7 +427,6 @@ protected: const EarlyLate *early_late, const RiseFall *rf, std::string_view src_attr, - std::string_view orig_name, std::string_view line_case) const; void reportLineTotal(std::string_view what, const Delay &incr, @@ -548,7 +546,6 @@ protected: ReportField *field_fanout_; ReportField *field_variation_; ReportField *field_src_attr_; - ReportField *field_orig_name_; ReportField *field_edge_; ReportField *field_case_; diff --git a/search/Search.tcl b/search/Search.tcl index 1a6e1159..6d3c7223 100644 --- a/search/Search.tcl +++ b/search/Search.tcl @@ -333,7 +333,7 @@ define_cmd_args "report_checks" \ [-sort_by_slack]\ [-path_group group_name]\ [-format full|full_clock|full_clock_expanded|short|end|slack_only|summary|json]\ - [-fields capacitance|slew|fanout|input_pin|net|src_attr|orig_name]\ + [-fields capacitance|slew|fanout|input_pin|net|src_attr]\ [-digits digits]\ [-no_line_splits]\ [> filename] [>> filename]} diff --git a/search/test/cpp/TestReportFields.hh b/search/test/cpp/TestReportFields.hh new file mode 100644 index 00000000..f5a5ea94 --- /dev/null +++ b/search/test/cpp/TestReportFields.hh @@ -0,0 +1,13 @@ +// Shared report-path field name constants used by the OpenSTA gtest suites. + +#pragma once + +#include "sta/StringUtil.hh" + +namespace sta { + +inline const StringSeq kAllReportFields = { + "input_pin", "hierarchical_pin", "net", "capacitance", + "slew", "fanout", "variation", "src_attr"}; + +} // namespace sta diff --git a/search/test/cpp/TestSearchStaDesign.cc b/search/test/cpp/TestSearchStaDesign.cc index 5b0e1961..81476113 100644 --- a/search/test/cpp/TestSearchStaDesign.cc +++ b/search/test/cpp/TestSearchStaDesign.cc @@ -5,6 +5,7 @@ #include #include #include "MinMax.hh" +#include "TestReportFields.hh" #include "Transition.hh" #include "Property.hh" #include "ExceptionPath.hh" @@ -1874,7 +1875,7 @@ TEST_F(StaDesignTest, SearchReportClkInfos) { TEST_F(StaDesignTest, SetReportPathFields) { ASSERT_NO_THROW(( [&](){ - sta_->setReportPathFields(true, true, true, true, true, true, true, true, true); + sta_->setReportPathFields(kAllReportFields); }() )); } @@ -3625,7 +3626,7 @@ TEST_F(StaDesignTest, ReportPathFieldOrder) { TEST_F(StaDesignTest, ReportPathFields) { ASSERT_NO_THROW(( [&](){ - sta_->setReportPathFields(true, true, true, true, true, true, true, true, true); + sta_->setReportPathFields(kAllReportFields); }() )); } diff --git a/search/test/cpp/TestSearchStaInit.cc b/search/test/cpp/TestSearchStaInit.cc index 5091d651..83436500 100644 --- a/search/test/cpp/TestSearchStaInit.cc +++ b/search/test/cpp/TestSearchStaInit.cc @@ -2,6 +2,7 @@ #include #include #include "MinMax.hh" +#include "TestReportFields.hh" #include "Transition.hh" #include "Property.hh" #include "ExceptionPath.hh" @@ -433,13 +434,13 @@ TEST_F(StaInitTest, SetReportPathFields) { ASSERT_NE(fanout_field, nullptr); ASSERT_NE(src_attr_field, nullptr); - sta_->setReportPathFields(true, true, true, true, true, true, true, true, true); + sta_->setReportPathFields(kAllReportFields); EXPECT_TRUE(cap_field->enabled()); EXPECT_TRUE(slew_field->enabled()); EXPECT_TRUE(fanout_field->enabled()); EXPECT_TRUE(src_attr_field->enabled()); - sta_->setReportPathFields(false, false, false, false, false, false, false, false, false); + sta_->setReportPathFields(StringSeq{}); EXPECT_FALSE(cap_field->enabled()); EXPECT_FALSE(slew_field->enabled()); EXPECT_FALSE(fanout_field->enabled()); @@ -1613,8 +1614,8 @@ TEST_F(StaInitTest, ReportPathNoSplit) { TEST_F(StaInitTest, ReportPathSetReportFields) { ReportPath *rpt = sta_->reportPath(); - rpt->setReportFields(true, true, true, true, true, true, true, true, true); - rpt->setReportFields(false, false, false, false, false, false, false, false, false); + rpt->setReportFields(kAllReportFields); + rpt->setReportFields(StringSeq{}); } @@ -3706,7 +3707,9 @@ TEST_F(StaInitTest, LogicValueStringOne) { // --- ReportPath.cc: ReportField constructor and setEnabled --- TEST_F(StaInitTest, ReportFieldConstruct) { - ReportField rf("test_field", "Test Field", 10, false, nullptr, true); + ReportField rf("test_field", "test_field", "Test Field", 10, false, nullptr, + nullptr); + rf.setEnabled(true); EXPECT_EQ(rf.name(), "test_field"); EXPECT_EQ(rf.title(), "Test Field"); EXPECT_EQ(rf.width(), 10); @@ -3716,7 +3719,8 @@ TEST_F(StaInitTest, ReportFieldConstruct) { } TEST_F(StaInitTest, ReportFieldSetEnabled) { - ReportField rf("f1", "F1", 8, true, nullptr, true); + ReportField rf("f1", "f1", "F1", 8, true, nullptr, nullptr); + rf.setEnabled(true); EXPECT_TRUE(rf.enabled()); rf.setEnabled(false); EXPECT_FALSE(rf.enabled()); @@ -3725,14 +3729,14 @@ TEST_F(StaInitTest, ReportFieldSetEnabled) { } TEST_F(StaInitTest, ReportFieldSetWidth) { - ReportField rf("f2", "F2", 5, false, nullptr, true); + ReportField rf("f2", "f2", "F2", 5, false, nullptr, nullptr); EXPECT_EQ(rf.width(), 5); rf.setWidth(12); EXPECT_EQ(rf.width(), 12); } TEST_F(StaInitTest, ReportFieldSetProperties) { - ReportField rf("f3", "F3", 5, false, nullptr, true); + ReportField rf("f3", "f3", "F3", 5, false, nullptr, nullptr); rf.setProperties("New Title", 20, true); EXPECT_EQ(rf.title(), "New Title"); EXPECT_EQ(rf.width(), 20); @@ -3740,7 +3744,7 @@ TEST_F(StaInitTest, ReportFieldSetProperties) { } TEST_F(StaInitTest, ReportFieldBlank) { - ReportField rf("f4", "F4", 3, false, nullptr, true); + ReportField rf("f4", "f4", "F4", 3, false, nullptr, nullptr); const std::string &blank = rf.blank(); EXPECT_FALSE(blank.empty()); } diff --git a/search/test/cpp/TestSearchStaInitB.cc b/search/test/cpp/TestSearchStaInitB.cc index 5c4bd2ae..2e044a73 100644 --- a/search/test/cpp/TestSearchStaInitB.cc +++ b/search/test/cpp/TestSearchStaInitB.cc @@ -2,6 +2,7 @@ #include #include #include "MinMax.hh" +#include "TestReportFields.hh" #include "Transition.hh" #include "Property.hh" #include "ExceptionPath.hh" @@ -224,7 +225,7 @@ TEST_F(StaInitTest, StaReportPathEndFooter2) { TEST_F(StaInitTest, StaSetReportPathFields) { ASSERT_NO_THROW(( [&](){ - sta_->setReportPathFields(true, true, true, true, true, true, true, true, true); + sta_->setReportPathFields(kAllReportFields); }() )); } @@ -1724,8 +1725,8 @@ TEST_F(StaInitTest, SearchClassConstants2) { TEST_F(StaInitTest, ReportPathSetReportFields2) { ASSERT_NO_THROW(( [&](){ ReportPath *rpt = sta_->reportPath(); - rpt->setReportFields(true, true, true, true, true, true, true, true, true); - rpt->setReportFields(false, false, false, false, false, false, false, false, false); + rpt->setReportFields(kAllReportFields); + rpt->setReportFields(StringSeq{}); }() )); } @@ -1909,8 +1910,8 @@ TEST_F(StaInitTest, ReportPathSetReportFieldsPublic) { ASSERT_NO_THROW(( [&](){ ReportPath *rpt = sta_->reportPath(); // Call setReportFields with various combinations - rpt->setReportFields(true, false, false, false, true, false, false, false, false); - rpt->setReportFields(true, true, true, true, true, true, true, true, true); + rpt->setReportFields(StringSeq{"input_pin", "slew"}); + rpt->setReportFields(kAllReportFields); expectStaCoreState(sta_); }() )); } From 337c7382655132b67e230095ee2e5701969e115e Mon Sep 17 00:00:00 2001 From: dsengupta0628 Date: Fri, 15 May 2026 15:13:21 +0000 Subject: [PATCH 8/8] add reportField instead of line+ address Gemini feedback Signed-off-by: dsengupta0628 --- search/ReportPath.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/search/ReportPath.cc b/search/ReportPath.cc index 4b99f4a9..1bfcdfc6 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -3252,9 +3252,9 @@ ReportPath::reportLine(std::string_view what, reportFieldBlank(field, line); } else if (field == field_case_) - line += line_case; + reportField(line_case, field, line); else if (field->getValue()) - line += field->value(path, this); + reportField(field->value(path, this), field, line); first_field = false; }