Liberty power_down_function parse resolves #428

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2026-05-08 10:10:21 -07:00
parent 7e68e452d3
commit 8cbd400249
6 changed files with 53 additions and 64 deletions

View File

@ -91,6 +91,9 @@ stringEqual(std::string_view s1,
std::pair<float, bool>
stringFloat(const std::string &str);
std::pair<long long, bool>
stringLong(const std::string &str,
int base = 10);
bool
isDigits(const char *str);

View File

@ -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 <std::string> STRING KEYWORD
%token <float> FLOAT
@ -75,8 +75,8 @@ sta::LibertyParse::error(const location_type &loc,
%type <void *> statement complex_attr simple_attr variable group file
%type <sta::LibertyAttrValueSeq *> attr_values
%type <sta::LibertyAttrValue *> attr_value
%type <std::string> string expr expr_term expr_term1 volt_expr
%type <char> expr_op volt_op
%type <std::string> string expr expr_term expr_term1
%type <char> 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:

View File

@ -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;
}

View File

@ -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<int>(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

View File

@ -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,

View File

@ -78,6 +78,32 @@ stringFloat(const std::string &str)
#endif
}
std::pair<long long, bool>
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)
{