From 8cbd4002499810554de0585e4463710a5d3f5fdf Mon Sep 17 00:00:00 2001 From: James Cherry Date: Fri, 8 May 2026 10:10:21 -0700 Subject: [PATCH] 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) {