liberty parser c++
commit 1abf72bc3430d34a51d82992f1c753f0274a662a
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Jan 27 08:01:04 2025 -0700
rm unused lib visitors
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 1e76acfc7829a8ba82f96d369fae6225a7361844
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 26 21:15:46 2025 -0700
verilog/sdf stream->is_open
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit c4a57c0354ffb6c4edfc3269d56a937c11ad9609
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 26 19:54:41 2025 -0700
leak
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit b992ed1124a862cb04f0c7617a4575f916c3fe01
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 26 16:39:16 2025 -0700
liberty mv string_buf to scanner
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 894cbfa5d5b731738dcc60d492689fad9d13bd40
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 26 16:29:42 2025 -0700
liberty use regex to parse include file
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 176225849d3fcac0b2be1a5b623270c386daed3d
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 26 15:48:09 2025 -0700
liberty include filename
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 516e12721d7185015d8c29e8b16fa185f0f46983
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 26 15:31:18 2025 -0700
liberty include
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 32098a2159798dfbb80140927949bb36f480093d
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 26 15:01:47 2025 -0700
liberty include
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 880214e632d756c3199b000fee88fd4fdffac371
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 26 13:55:02 2025 -0700
liberty include
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit ad1efca842a6d7ee608ffd5a19a69885786b77fa
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 26 10:11:07 2025 -0700
liberty passes all but include
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit e71cf1f39dd09e81cf2b0e5a12dcf51675f2a6fd
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 26 10:01:08 2025 -0700
liberty parser use class compiles
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 02dea0ff753b0fa12f280661a46e2c0ef2432357
Author: James Cherry <cherry@parallaxsw.com>
Date: Sat Jan 25 19:08:06 2025 -0700
liberty parser compiles
Signed-off-by: James Cherry <cherry@parallaxsw.com>
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
c9a8726707
commit
fb6e7f9fa7
|
|
@ -273,6 +273,15 @@ set(STA_TCL_FILES
|
|||
find_package(FLEX)
|
||||
find_package(BISON)
|
||||
|
||||
# Liberty scan/parse.
|
||||
flex_target(LibertyLex ${STA_HOME}/liberty/LibertyLex.ll
|
||||
${CMAKE_CURRENT_BINARY_DIR}/LibertyLex.cc)
|
||||
bison_target(LibertyParse ${STA_HOME}/liberty/LibertyParse.yy
|
||||
${CMAKE_CURRENT_BINARY_DIR}/LibertyParse.cc
|
||||
# centos7 bison 3.0.4 < 3.3.0 uses parser_class_name instead of api.parsr.class
|
||||
COMPILE_FLAGS "-Wno-deprecated")
|
||||
add_flex_bison_dependency(LibertyLex LibertyParse)
|
||||
|
||||
# LibertyExpr scan/parse.
|
||||
flex_target(LibertyExprLex ${STA_HOME}/liberty/LibertyExprLex.ll
|
||||
${CMAKE_CURRENT_BINARY_DIR}/LibertyExprLex.cc
|
||||
|
|
@ -283,15 +292,6 @@ bison_target(LibertyExprParse ${STA_HOME}/liberty/LibertyExprParse.yy
|
|||
)
|
||||
add_flex_bison_dependency(LibertyExprLex LibertyExprParse)
|
||||
|
||||
# Liberty scan/parse.
|
||||
flex_target(LibertyLex ${STA_HOME}/liberty/LibertyLex.ll ${CMAKE_CURRENT_BINARY_DIR}/LibertyLex.cc
|
||||
COMPILE_FLAGS --prefix=LibertyLex_
|
||||
)
|
||||
bison_target(LibertyParse ${STA_HOME}/liberty/LibertyParse.yy ${CMAKE_CURRENT_BINARY_DIR}/LibertyParse.cc
|
||||
COMPILE_FLAGS "--name-prefix=LibertyParse_ -v"
|
||||
)
|
||||
add_flex_bison_dependency(LibertyLex LibertyParse)
|
||||
|
||||
# Spef scan/parse.
|
||||
flex_target(SpefLex ${STA_HOME}/parasitics/SpefLex.ll ${CMAKE_CURRENT_BINARY_DIR}/SpefLex.cc
|
||||
COMPILE_FLAGS --prefix=SpefLex_
|
||||
|
|
|
|||
|
|
@ -29,33 +29,29 @@
|
|||
#include "util/FlexDisableRegister.hh"
|
||||
#include "liberty/LibertyParser.hh"
|
||||
#include "LibertyParse.hh"
|
||||
#include "liberty/LibertyScanner.hh"
|
||||
|
||||
#define YY_NO_INPUT
|
||||
#undef YY_DECL
|
||||
#define YY_DECL \
|
||||
int \
|
||||
sta::LibertyScanner::lex(sta::LibertyParse::semantic_type *const yylval, \
|
||||
sta::LibertyParse::location_type *loc)
|
||||
|
||||
#if defined(YY_FLEX_MAJOR_VERSION) \
|
||||
&& defined(YY_FLEX_MINOR_VERSION) \
|
||||
&& YY_FLEX_MAJOR_VERSION >=2 \
|
||||
&& (YY_FLEX_MINOR_VERSION > 5 \
|
||||
|| (YY_FLEX_MINOR_VERSION == 5 \
|
||||
&& defined(YY_FLEX_SUBMINOR_VERSION) \
|
||||
&& YY_FLEX_SUBMINOR_VERSION >= 31))
|
||||
#define INCLUDE_SUPPORTED
|
||||
#endif
|
||||
// update location on matching
|
||||
#define YY_USER_ACTION loc->step(); loc->columns(yyleng);
|
||||
|
||||
static std::string string_buf;
|
||||
|
||||
void
|
||||
libertyParseFlushBuffer()
|
||||
{
|
||||
YY_FLUSH_BUFFER;
|
||||
}
|
||||
typedef sta::LibertyParse::token token;
|
||||
|
||||
%}
|
||||
|
||||
/* %option debug */
|
||||
%option c++
|
||||
%option yyclass="sta::LibertyScanner"
|
||||
%option prefix="Liberty"
|
||||
%option noyywrap
|
||||
%option nounput
|
||||
%option never-interactive
|
||||
%option stack
|
||||
%option yylineno
|
||||
/* %option debug */
|
||||
|
||||
%x comment
|
||||
%x qstring
|
||||
|
|
@ -86,21 +82,20 @@ TOKEN_END {PUNCTUATION}|[ \t\r\n]
|
|||
EOL \r?\n
|
||||
%%
|
||||
|
||||
{PUNCTUATION} { return ((int) LibertyLex_text[0]); }
|
||||
{PUNCTUATION} { return ((int) yytext[0]); }
|
||||
|
||||
{FLOAT}{TOKEN_END} {
|
||||
/* Push back the TOKEN_END character. */
|
||||
yyless(LibertyLex_leng - 1);
|
||||
LibertyParse_lval.number = static_cast<float>(strtod(LibertyLex_text,
|
||||
NULL));
|
||||
return FLOAT;
|
||||
yyless(yyleng - 1);
|
||||
yylval->number = strtod(yytext, nullptr);
|
||||
return token::FLOAT;
|
||||
}
|
||||
|
||||
{ALPHA}({ALPHA}|_|{DIGIT})*{TOKEN_END} {
|
||||
/* Push back the TOKEN_END character. */
|
||||
yyless(LibertyLex_leng - 1);
|
||||
LibertyParse_lval.string = sta::stringCopy(LibertyLex_text);
|
||||
return KEYWORD;
|
||||
yyless(yyleng - 1);
|
||||
yylval->string = sta::stringCopy(yytext);
|
||||
return token::KEYWORD;
|
||||
}
|
||||
|
||||
{PIN_NAME}{TOKEN_END} |
|
||||
|
|
@ -111,106 +106,75 @@ EOL \r?\n
|
|||
{BUS_STYLE}{TOKEN_END} |
|
||||
{TOKEN}{TOKEN_END} {
|
||||
/* Push back the TOKEN_END character. */
|
||||
yyless(LibertyLex_leng - 1);
|
||||
LibertyParse_lval.string = sta::stringCopy(LibertyLex_text);
|
||||
return STRING;
|
||||
yyless(yyleng - 1);
|
||||
yylval->string = sta::stringCopy(yytext);
|
||||
return token::STRING;
|
||||
}
|
||||
|
||||
\\?{EOL} { sta::libertyIncrLine(); }
|
||||
\\?{EOL} { loc->lines(); loc->step(); }
|
||||
|
||||
"include_file"[ \t]*"(".+")"[ \t]*";"? {
|
||||
#ifdef INCLUDE_SUPPORTED
|
||||
if (sta::libertyInInclude())
|
||||
sta::libertyParseError("nested include_file's are not supported");
|
||||
else {
|
||||
char *filename = &yytext[strlen("include_file")];
|
||||
/* Skip blanks between include_file and '('. */
|
||||
while (isspace(*filename) && *filename != '\0')
|
||||
filename++;
|
||||
/* Skip '('. */
|
||||
filename++;
|
||||
/* Skip blanks between '(' and filename. */
|
||||
while (isspace(*filename) && *filename != '\0')
|
||||
filename++;
|
||||
char *filename_end = strpbrk(filename, ")");
|
||||
if (filename_end == NULL)
|
||||
sta::libertyParseError("include_file missing ')'");
|
||||
else {
|
||||
/* Trim trailing blanks. */
|
||||
while (isspace(filename_end[-1]) && filename_end > filename)
|
||||
filename_end--;
|
||||
*filename_end = '\0';
|
||||
sta::libertyIncludeBegin(filename);
|
||||
yypush_buffer_state(yy_create_buffer(nullptr, YY_BUF_SIZE));
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
}
|
||||
#else
|
||||
sta::libertyParseError("include_file is not supported.");
|
||||
#endif
|
||||
}
|
||||
if (includeBegin()) {
|
||||
BEGIN(INITIAL);
|
||||
}
|
||||
}
|
||||
|
||||
"/*" BEGIN(comment);
|
||||
|
||||
/* Straight out of the flex man page. */
|
||||
<comment>[^*\r\n]* /* eat anything that's not a '*' */
|
||||
<comment>"*"+[^*/\r\n]* /* eat up '*'s not followed by '/'s */
|
||||
<comment>{EOL} sta::libertyIncrLine();
|
||||
<comment>{EOL} { loc->lines(); loc->step(); }
|
||||
<comment>"*"+"/" BEGIN(INITIAL);
|
||||
|
||||
\" {
|
||||
string_buf.erase();
|
||||
token_.clear();
|
||||
BEGIN(qstring);
|
||||
}
|
||||
|
||||
<qstring>\" {
|
||||
BEGIN(INITIAL);
|
||||
LibertyParse_lval.string = sta::stringCopy(string_buf.c_str());
|
||||
return STRING;
|
||||
yylval->string = stringCopy(token_.c_str());
|
||||
return token::STRING;
|
||||
}
|
||||
|
||||
<qstring>{EOL} {
|
||||
LibertyParse_error("unterminated string constant");
|
||||
error("unterminated string constant");
|
||||
BEGIN(INITIAL);
|
||||
LibertyParse_lval.string = sta::stringCopy(string_buf.c_str());
|
||||
return STRING;
|
||||
yylval->string = stringCopy(token_.c_str());
|
||||
return token::STRING;
|
||||
}
|
||||
|
||||
<qstring>\\{EOL} {
|
||||
/* Line continuation. */
|
||||
sta::libertyIncrLine();
|
||||
loc->lines(); loc->step();
|
||||
}
|
||||
|
||||
<qstring>\\. {
|
||||
/* Escaped character. */
|
||||
string_buf += '\\';
|
||||
string_buf += LibertyLex_text[1];
|
||||
token_ += '\\';
|
||||
token_ += yytext[1];
|
||||
}
|
||||
|
||||
<qstring>[^\\\r\n\"]+ {
|
||||
/* Anything but escape, return or double quote */
|
||||
string_buf += LibertyLex_text;
|
||||
token_ += yytext;
|
||||
}
|
||||
|
||||
<qstring><<EOF>> {
|
||||
LibertyParse_error("unterminated string constant");
|
||||
error("unterminated string constant");
|
||||
BEGIN(INITIAL);
|
||||
yyterminate();
|
||||
}
|
||||
|
||||
{BLANK}* {}
|
||||
/* Send out of bound characters to parser. */
|
||||
. { return (int) LibertyLex_text[0]; }
|
||||
. { return (int) yytext[0]; }
|
||||
|
||||
<<EOF>> {
|
||||
#ifdef INCLUDE_SUPPORTED
|
||||
if (sta::libertyInInclude()) {
|
||||
sta::libertyIncludeEnd();
|
||||
yypop_buffer_state();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
yyterminate();
|
||||
}
|
||||
<<EOF>> { if (stream_prev_)
|
||||
fileEnd();
|
||||
else
|
||||
yyterminate();
|
||||
}
|
||||
|
||||
%%
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
%{
|
||||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2025, Parallax Software, Inc.
|
||||
//
|
||||
|
|
@ -23,25 +22,41 @@
|
|||
//
|
||||
// This notice may not be removed or altered from any source distribution.
|
||||
|
||||
%{
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "StringUtil.hh"
|
||||
#include "liberty/LibertyParser.hh"
|
||||
#include "liberty/LibertyScanner.hh"
|
||||
|
||||
int LibertyLex_lex();
|
||||
#define LibertyParse_lex LibertyLex_lex
|
||||
// Use yacc generated parser errors.
|
||||
#define YYERROR_VERBOSE
|
||||
#undef yylex
|
||||
#define yylex scanner->lex
|
||||
|
||||
#define YYDEBUG 1
|
||||
// warning: variable 'yynerrs_' set but not used
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
|
||||
#define loc_line(loc) loc.begin.line
|
||||
%}
|
||||
|
||||
%require "3.0"
|
||||
%skeleton "lalr1.cc"
|
||||
%debug
|
||||
%define api.namespace {sta}
|
||||
%locations
|
||||
%define parse.assert
|
||||
%parse-param { LibertyScanner *scanner }
|
||||
%parse-param { LibertyParser *reader }
|
||||
|
||||
// bison 3.0.4 for centos7
|
||||
%define parser_class_name {LibertyParse}
|
||||
// bison 3.3.2
|
||||
//%define api.parser.class {LibertyParse}
|
||||
|
||||
%expect 2
|
||||
|
||||
%union {
|
||||
char *string;
|
||||
float number;
|
||||
int line;
|
||||
char ch;
|
||||
sta::LibertyAttrValue *attr_value;
|
||||
sta::LibertyAttrValueSeq *attr_values;
|
||||
|
|
@ -61,16 +76,10 @@ int LibertyLex_lex();
|
|||
%type <attr_values> attr_values
|
||||
%type <attr_value> attr_value
|
||||
%type <string> string expr expr_term expr_term1 volt_expr
|
||||
%type <line> line
|
||||
%type <ch> expr_op volt_op
|
||||
|
||||
%expect 2
|
||||
|
||||
%start file
|
||||
|
||||
%{
|
||||
%}
|
||||
|
||||
%%
|
||||
|
||||
file:
|
||||
|
|
@ -78,26 +87,22 @@ file:
|
|||
;
|
||||
|
||||
group:
|
||||
KEYWORD '(' ')' line '{'
|
||||
{ sta::libertyGroupBegin($1, nullptr, $4); }
|
||||
KEYWORD '(' ')' '{'
|
||||
{ reader->groupBegin($1, nullptr, loc_line(@1)); }
|
||||
'}' semi_opt
|
||||
{ $$ = sta::libertyGroupEnd(); }
|
||||
| KEYWORD '(' ')' line '{'
|
||||
{ sta::libertyGroupBegin($1, nullptr, $4); }
|
||||
{ $$ = reader->groupEnd(); }
|
||||
| KEYWORD '(' ')' '{'
|
||||
{ reader->groupBegin($1, nullptr, loc_line(@1)); }
|
||||
statements '}' semi_opt
|
||||
{ $$ = sta::libertyGroupEnd(); }
|
||||
| KEYWORD '(' attr_values ')' line '{'
|
||||
{ sta::libertyGroupBegin($1, $3, $5); }
|
||||
{ $$ = reader->groupEnd(); }
|
||||
| KEYWORD '(' attr_values ')' '{'
|
||||
{ reader->groupBegin($1, $3, loc_line(@1)); }
|
||||
'}' semi_opt
|
||||
{ $$ = sta::libertyGroupEnd(); }
|
||||
| KEYWORD '(' attr_values ')' line '{'
|
||||
{ sta::libertyGroupBegin($1, $3, $5); }
|
||||
{ $$ = reader->groupEnd(); }
|
||||
| KEYWORD '(' attr_values ')' '{'
|
||||
{ reader->groupBegin($1, $3, loc_line(@1)); }
|
||||
statements '}' semi_opt
|
||||
{ $$ = sta::libertyGroupEnd(); }
|
||||
;
|
||||
|
||||
line: /* empty */
|
||||
{ $$ = sta::libertyLine(); }
|
||||
{ $$ = reader->groupEnd(); }
|
||||
;
|
||||
|
||||
statements:
|
||||
|
|
@ -113,15 +118,15 @@ statement:
|
|||
;
|
||||
|
||||
simple_attr:
|
||||
KEYWORD ':' attr_value line semi_opt
|
||||
{ $$ = sta::makeLibertySimpleAttr($1, $3, $4); }
|
||||
KEYWORD ':' attr_value semi_opt
|
||||
{ $$ = reader->makeSimpleAttr($1, $3, loc_line(@1)); }
|
||||
;
|
||||
|
||||
complex_attr:
|
||||
KEYWORD '(' ')' line semi_opt
|
||||
{ $$ = sta::makeLibertyComplexAttr($1, nullptr, $4); }
|
||||
| KEYWORD '(' attr_values ')' line semi_opt
|
||||
{ $$ = sta::makeLibertyComplexAttr($1, $3, $5); }
|
||||
KEYWORD '(' ')' semi_opt
|
||||
{ $$ = reader->makeComplexAttr($1, nullptr, loc_line(@1)); }
|
||||
| KEYWORD '(' attr_values ')' semi_opt
|
||||
{ $$ = reader->makeComplexAttr($1, $3, loc_line(@1)); }
|
||||
;
|
||||
|
||||
attr_values:
|
||||
|
|
@ -140,8 +145,8 @@ attr_values:
|
|||
;
|
||||
|
||||
variable:
|
||||
string '=' FLOAT line semi_opt
|
||||
{ $$ = sta::makeLibertyVariable($1, $3, $4); }
|
||||
string '=' FLOAT semi_opt
|
||||
{ $$ = reader->makeVariable($1, $3, loc_line(@1)); }
|
||||
;
|
||||
|
||||
string:
|
||||
|
|
@ -153,11 +158,11 @@ string:
|
|||
|
||||
attr_value:
|
||||
FLOAT
|
||||
{ $$ = sta::makeLibertyFloatAttrValue($1); }
|
||||
{ $$ = reader->makeFloatAttrValue($1); }
|
||||
| expr
|
||||
{ $$ = sta::makeLibertyStringAttrValue($1); }
|
||||
{ $$ = reader->makeStringAttrValue($1); }
|
||||
| volt_expr
|
||||
{ $$ = sta::makeLibertyStringAttrValue($1); }
|
||||
{ $$ = reader->makeStringAttrValue($1); }
|
||||
;
|
||||
|
||||
/* Voltage expressions are ignored. */
|
||||
|
|
|
|||
|
|
@ -26,106 +26,124 @@
|
|||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <regex>
|
||||
|
||||
#include "Zlib.hh"
|
||||
#include "Report.hh"
|
||||
#include "Error.hh"
|
||||
#include "StringUtil.hh"
|
||||
|
||||
// Global namespace
|
||||
|
||||
int
|
||||
LibertyParse_parse();
|
||||
#include "LibertyScanner.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
typedef Vector<LibertyGroup*> LibertyGroupSeq;
|
||||
|
||||
static const char *liberty_filename;
|
||||
static gzFile liberty_stream;
|
||||
static int liberty_line;
|
||||
// Previous lex reader state for include files.
|
||||
static const char *liberty_filename_prev;
|
||||
static int liberty_line_prev;
|
||||
static gzFile liberty_stream_prev;
|
||||
|
||||
static LibertyGroupVisitor *liberty_group_visitor;
|
||||
static LibertyGroupSeq liberty_group_stack;
|
||||
static Report *liberty_report;
|
||||
|
||||
static LibertyStmt *
|
||||
makeLibertyDefine(LibertyAttrValueSeq *values,
|
||||
int line);
|
||||
static LibertyAttrType
|
||||
attrValueType(const char *value_type_name);
|
||||
static LibertyGroupType
|
||||
groupType(const char *group_type_name);
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
parseLibertyFile(const char *filename,
|
||||
LibertyGroupVisitor *library_visitor,
|
||||
Report *report)
|
||||
{
|
||||
liberty_stream = gzopen(filename, "r");
|
||||
if (liberty_stream) {
|
||||
liberty_group_visitor = library_visitor;
|
||||
liberty_group_stack.clear();
|
||||
liberty_filename = filename;
|
||||
liberty_filename_prev = nullptr;
|
||||
liberty_stream_prev = nullptr;
|
||||
liberty_line = 1;
|
||||
liberty_report = report;
|
||||
LibertyParse_parse();
|
||||
gzclose(liberty_stream);
|
||||
std::istream *stream = new gzstream::igzstream(filename);
|
||||
if (stream->good()) {
|
||||
LibertyParser reader(filename, library_visitor, report);
|
||||
LibertyScanner scanner(stream, filename, &reader, report);
|
||||
LibertyParse parser(&scanner, &reader);
|
||||
parser.parse();
|
||||
delete stream;
|
||||
}
|
||||
else {
|
||||
delete stream;
|
||||
throw FileNotReadable(filename);
|
||||
}
|
||||
}
|
||||
|
||||
LibertyParser::LibertyParser(const char *filename,
|
||||
LibertyGroupVisitor *library_visitor,
|
||||
Report *report) :
|
||||
filename_(filename),
|
||||
group_visitor_(library_visitor),
|
||||
report_(report)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
LibertyParser::setFilename(const string &filename)
|
||||
{
|
||||
filename_ = filename;
|
||||
}
|
||||
|
||||
LibertyStmt *
|
||||
LibertyParser::makeDefine(LibertyAttrValueSeq *values,
|
||||
int line)
|
||||
{
|
||||
LibertyDefine *define = nullptr;
|
||||
if (values->size() == 3) {
|
||||
const char *define_name = (*values)[0]->stringValue();
|
||||
const char *group_type_name = (*values)[1]->stringValue();
|
||||
const char *value_type_name = (*values)[2]->stringValue();
|
||||
LibertyAttrType value_type = attrValueType(value_type_name);
|
||||
LibertyGroupType group_type = groupType(group_type_name);
|
||||
define = new LibertyDefine(stringCopy(define_name), group_type,
|
||||
value_type, line);
|
||||
LibertyGroup *group = this->group();
|
||||
group->addDefine(define);
|
||||
}
|
||||
else
|
||||
throw FileNotReadable(filename);
|
||||
report_->fileWarn(24, filename_.c_str(), line,
|
||||
"define does not have three arguments.");
|
||||
return define;
|
||||
}
|
||||
|
||||
void
|
||||
libertyGetChars(char *buf,
|
||||
int &result,
|
||||
size_t max_size)
|
||||
// The Liberty User Guide Version 2001.08 fails to define the strings
|
||||
// used to define valid attribute types. Beyond "string" these are
|
||||
// guesses.
|
||||
LibertyAttrType
|
||||
LibertyParser::attrValueType(const char *value_type_name)
|
||||
{
|
||||
char *status = gzgets(liberty_stream, buf, max_size);
|
||||
if (status == Z_NULL)
|
||||
result = 0; // YY_nullptr
|
||||
if (stringEq(value_type_name, "string"))
|
||||
return LibertyAttrType::attr_string;
|
||||
else if (stringEq(value_type_name, "integer"))
|
||||
return LibertyAttrType::attr_int;
|
||||
else if (stringEq(value_type_name, "float"))
|
||||
return LibertyAttrType::attr_double;
|
||||
else if (stringEq(value_type_name, "boolean"))
|
||||
return LibertyAttrType::attr_boolean;
|
||||
else
|
||||
result = strlen(buf);
|
||||
return LibertyAttrType::attr_unknown;
|
||||
}
|
||||
|
||||
void
|
||||
libertyGetChars(char *buf,
|
||||
size_t &result,
|
||||
size_t max_size)
|
||||
LibertyGroupType
|
||||
LibertyParser::groupType(const char *group_type_name)
|
||||
{
|
||||
char *status = gzgets(liberty_stream, buf, max_size);
|
||||
if (status == Z_NULL)
|
||||
result = 0; // YY_nullptr
|
||||
if (stringEq(group_type_name, "library"))
|
||||
return LibertyGroupType::library;
|
||||
else if (stringEq(group_type_name, "cell"))
|
||||
return LibertyGroupType::cell;
|
||||
else if (stringEq(group_type_name, "pin"))
|
||||
return LibertyGroupType::pin;
|
||||
else if (stringEq(group_type_name, "timing"))
|
||||
return LibertyGroupType::timing;
|
||||
else
|
||||
result = strlen(buf);
|
||||
return LibertyGroupType::unknown;
|
||||
}
|
||||
|
||||
void
|
||||
libertyGroupBegin(const char *type,
|
||||
LibertyAttrValueSeq *params,
|
||||
int line)
|
||||
LibertyParser::groupBegin(const char *type,
|
||||
LibertyAttrValueSeq *params,
|
||||
int line)
|
||||
{
|
||||
LibertyGroup *group = new LibertyGroup(type, params, line);
|
||||
liberty_group_visitor->begin(group);
|
||||
liberty_group_stack.push_back(group);
|
||||
group_visitor_->begin(group);
|
||||
group_stack_.push_back(group);
|
||||
}
|
||||
|
||||
LibertyGroup *
|
||||
libertyGroupEnd()
|
||||
LibertyParser::groupEnd()
|
||||
{
|
||||
LibertyGroup *group = libertyGroup();
|
||||
liberty_group_visitor->end(group);
|
||||
liberty_group_stack.pop_back();
|
||||
LibertyGroup *group = this->group();
|
||||
group_visitor_->end(group);
|
||||
group_stack_.pop_back();
|
||||
LibertyGroup *parent =
|
||||
liberty_group_stack.empty() ? nullptr : liberty_group_stack.back();
|
||||
if (parent && liberty_group_visitor->save(group)) {
|
||||
group_stack_.empty() ? nullptr : group_stack_.back();
|
||||
if (parent && group_visitor_->save(group)) {
|
||||
parent->addSubgroup(group);
|
||||
return group;
|
||||
}
|
||||
|
|
@ -135,6 +153,92 @@ libertyGroupEnd()
|
|||
}
|
||||
}
|
||||
|
||||
LibertyGroup *
|
||||
LibertyParser::group()
|
||||
{
|
||||
return group_stack_.back();
|
||||
}
|
||||
|
||||
void
|
||||
LibertyParser::deleteGroups()
|
||||
{
|
||||
group_stack_.deleteContentsClear();
|
||||
}
|
||||
|
||||
LibertyStmt *
|
||||
LibertyParser::makeSimpleAttr(const char *name,
|
||||
LibertyAttrValue *value,
|
||||
int line)
|
||||
{
|
||||
LibertyAttr *attr = new LibertySimpleAttr(name, value, line);
|
||||
group_visitor_->visitAttr(attr);
|
||||
LibertyGroup *group = this->group();
|
||||
if (group && group_visitor_->save(attr)) {
|
||||
group->addAttribute(attr);
|
||||
return attr;
|
||||
}
|
||||
else {
|
||||
delete attr;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
LibertyStmt *
|
||||
LibertyParser::makeComplexAttr(const char *name,
|
||||
LibertyAttrValueSeq *values,
|
||||
int line)
|
||||
{
|
||||
// Defines have the same syntax as complex attributes.
|
||||
// Detect and convert them.
|
||||
if (stringEq(name, "define")) {
|
||||
LibertyStmt *define = makeDefine(values, line);
|
||||
stringDelete(name);
|
||||
LibertyAttrValueSeq::Iterator attr_iter(values);
|
||||
while (attr_iter.hasNext())
|
||||
delete attr_iter.next();
|
||||
delete values;
|
||||
return define;
|
||||
}
|
||||
else {
|
||||
LibertyAttr *attr = new LibertyComplexAttr(name, values, line);
|
||||
group_visitor_->visitAttr(attr);
|
||||
if (group_visitor_->save(attr)) {
|
||||
LibertyGroup *group = this->group();
|
||||
group->addAttribute(attr);
|
||||
return attr;
|
||||
}
|
||||
delete attr;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
LibertyStmt *
|
||||
LibertyParser::makeVariable(char *var,
|
||||
float value,
|
||||
int line)
|
||||
{
|
||||
LibertyVariable *variable = new LibertyVariable(var, value, line);
|
||||
group_visitor_->visitVariable(variable);
|
||||
if (group_visitor_->save(variable))
|
||||
return variable;
|
||||
else {
|
||||
delete variable;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
LibertyAttrValue *
|
||||
LibertyParser::makeStringAttrValue(char *value)
|
||||
{
|
||||
return new LibertyStringAttrValue(value);
|
||||
}
|
||||
|
||||
LibertyAttrValue *
|
||||
LibertyParser::makeFloatAttrValue(float value)
|
||||
{
|
||||
return new LibertyFloatAttrValue(value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyStmt::LibertyStmt(int line) :
|
||||
|
|
@ -274,31 +378,6 @@ LibertyAttr::~LibertyAttr()
|
|||
stringDelete(name_);
|
||||
}
|
||||
|
||||
LibertyStmt *
|
||||
makeLibertySimpleAttr(const char *name,
|
||||
LibertyAttrValue *value,
|
||||
int line)
|
||||
{
|
||||
LibertyAttr *attr = new LibertySimpleAttr(name, value, line);
|
||||
if (liberty_group_visitor)
|
||||
liberty_group_visitor->visitAttr(attr);
|
||||
LibertyGroup *group = libertyGroup();
|
||||
if (group && liberty_group_visitor->save(attr)) {
|
||||
group->addAttribute(attr);
|
||||
return attr;
|
||||
}
|
||||
else {
|
||||
delete attr;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
LibertyGroup *
|
||||
libertyGroup()
|
||||
{
|
||||
return liberty_group_stack.back();
|
||||
}
|
||||
|
||||
LibertySimpleAttr::LibertySimpleAttr(const char *name,
|
||||
LibertyAttrValue *value,
|
||||
int line) :
|
||||
|
|
@ -319,37 +398,6 @@ LibertySimpleAttr::values() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
LibertyStmt *
|
||||
makeLibertyComplexAttr(const char *name,
|
||||
LibertyAttrValueSeq *values,
|
||||
int line)
|
||||
{
|
||||
// Defines have the same syntax as complex attributes.
|
||||
// Detect and convert them.
|
||||
if (stringEq(name, "define")) {
|
||||
LibertyStmt *define = makeLibertyDefine(values, line);
|
||||
stringDelete(name);
|
||||
LibertyAttrValueSeq::Iterator attr_iter(values);
|
||||
while (attr_iter.hasNext())
|
||||
delete attr_iter.next();
|
||||
delete values;
|
||||
return define;
|
||||
}
|
||||
else {
|
||||
LibertyAttr *attr = new LibertyComplexAttr(name, values, line);
|
||||
if (liberty_group_visitor) {
|
||||
liberty_group_visitor->visitAttr(attr);
|
||||
if (liberty_group_visitor->save(attr)) {
|
||||
LibertyGroup *group = libertyGroup();
|
||||
group->addAttribute(attr);
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
delete attr;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
LibertyComplexAttr::LibertyComplexAttr(const char *name,
|
||||
LibertyAttrValueSeq *values,
|
||||
int line) :
|
||||
|
|
@ -375,12 +423,6 @@ LibertyComplexAttr::firstValue()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
LibertyAttrValue *
|
||||
makeLibertyStringAttrValue(char *value)
|
||||
{
|
||||
return new LibertyStringAttrValue(value);
|
||||
}
|
||||
|
||||
LibertyStringAttrValue::LibertyStringAttrValue(const char *value) :
|
||||
LibertyAttrValue(),
|
||||
value_(value)
|
||||
|
|
@ -405,12 +447,6 @@ LibertyStringAttrValue::stringValue()
|
|||
return value_;
|
||||
}
|
||||
|
||||
LibertyAttrValue *
|
||||
makeLibertyFloatAttrValue(float value)
|
||||
{
|
||||
return new LibertyFloatAttrValue(value);
|
||||
}
|
||||
|
||||
LibertyFloatAttrValue::LibertyFloatAttrValue(float value) :
|
||||
value_(value)
|
||||
{
|
||||
|
|
@ -431,61 +467,6 @@ LibertyFloatAttrValue::stringValue()
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
static LibertyStmt *
|
||||
makeLibertyDefine(LibertyAttrValueSeq *values,
|
||||
int line)
|
||||
{
|
||||
LibertyDefine *define = nullptr;
|
||||
if (values->size() == 3) {
|
||||
const char *define_name = (*values)[0]->stringValue();
|
||||
const char *group_type_name = (*values)[1]->stringValue();
|
||||
const char *value_type_name = (*values)[2]->stringValue();
|
||||
LibertyAttrType value_type = attrValueType(value_type_name);
|
||||
LibertyGroupType group_type = groupType(group_type_name);
|
||||
define = new LibertyDefine(stringCopy(define_name), group_type,
|
||||
value_type, line);
|
||||
LibertyGroup *group = libertyGroup();
|
||||
group->addDefine(define);
|
||||
}
|
||||
else
|
||||
liberty_report->fileWarn(24, liberty_filename, line,
|
||||
"define does not have three arguments.");
|
||||
return define;
|
||||
}
|
||||
|
||||
// The Liberty User Guide Version 2001.08 fails to define the strings
|
||||
// used to define valid attribute types. Beyond "string" these are
|
||||
// guesses.
|
||||
static LibertyAttrType
|
||||
attrValueType(const char *value_type_name)
|
||||
{
|
||||
if (stringEq(value_type_name, "string"))
|
||||
return LibertyAttrType::attr_string;
|
||||
else if (stringEq(value_type_name, "integer"))
|
||||
return LibertyAttrType::attr_int;
|
||||
else if (stringEq(value_type_name, "float"))
|
||||
return LibertyAttrType::attr_double;
|
||||
else if (stringEq(value_type_name, "boolean"))
|
||||
return LibertyAttrType::attr_boolean;
|
||||
else
|
||||
return LibertyAttrType::attr_unknown;
|
||||
}
|
||||
|
||||
static LibertyGroupType
|
||||
groupType(const char *group_type_name)
|
||||
{
|
||||
if (stringEq(group_type_name, "library"))
|
||||
return LibertyGroupType::library;
|
||||
else if (stringEq(group_type_name, "cell"))
|
||||
return LibertyGroupType::cell;
|
||||
else if (stringEq(group_type_name, "pin"))
|
||||
return LibertyGroupType::pin;
|
||||
else if (stringEq(group_type_name, "timing"))
|
||||
return LibertyGroupType::timing;
|
||||
else
|
||||
return LibertyGroupType::unknown;
|
||||
}
|
||||
|
||||
LibertyDefine::LibertyDefine(const char *name,
|
||||
LibertyGroupType group_type,
|
||||
LibertyAttrType value_type,
|
||||
|
|
@ -504,21 +485,6 @@ LibertyDefine::~LibertyDefine()
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyStmt *
|
||||
makeLibertyVariable(char *var,
|
||||
float value,
|
||||
int line)
|
||||
{
|
||||
LibertyVariable *variable = new LibertyVariable(var, value, line);
|
||||
liberty_group_visitor->visitVariable(variable);
|
||||
if (liberty_group_visitor->save(variable))
|
||||
return variable;
|
||||
else {
|
||||
delete variable;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
LibertyVariable::LibertyVariable(const char *var,
|
||||
float value,
|
||||
int line) :
|
||||
|
|
@ -535,82 +501,78 @@ LibertyVariable::~LibertyVariable()
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyScanner::LibertyScanner(std::istream *stream,
|
||||
const char *filename,
|
||||
LibertyParser *reader,
|
||||
Report *report) :
|
||||
yyFlexLexer(stream),
|
||||
stream_(stream),
|
||||
filename_(filename),
|
||||
reader_(reader),
|
||||
report_(report),
|
||||
stream_prev_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
libertyInInclude()
|
||||
LibertyScanner::includeBegin()
|
||||
{
|
||||
return liberty_filename_prev != nullptr;
|
||||
}
|
||||
if (stream_prev_ != nullptr)
|
||||
error("nested include_file's are not supported");
|
||||
else {
|
||||
// include_file(filename);
|
||||
std::regex include_regexp("include_file *\\( *([^)]+) *\\) *;?");
|
||||
std::cmatch matches;
|
||||
if (std::regex_match(yytext, matches, include_regexp)) {
|
||||
string filename = matches[1].str();
|
||||
gzstream::igzstream *stream = new gzstream::igzstream(filename.c_str());
|
||||
if (stream->is_open()) {
|
||||
yypush_buffer_state(yy_create_buffer(stream, 256));
|
||||
|
||||
void
|
||||
libertyIncludeBegin(const char *filename)
|
||||
{
|
||||
gzFile stream = gzopen(filename, "r" );
|
||||
if (stream) {
|
||||
liberty_stream_prev = liberty_stream;
|
||||
liberty_filename_prev = liberty_filename;
|
||||
liberty_line_prev = liberty_line;
|
||||
filename_prev_ = filename_;
|
||||
stream_prev_ = stream_;
|
||||
|
||||
liberty_stream = stream;
|
||||
liberty_filename = filename;
|
||||
liberty_line = 1;
|
||||
filename_ = filename;
|
||||
reader_->setFilename(filename);
|
||||
stream_ = stream;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
report_->fileWarn(25, filename_.c_str(), yylineno,
|
||||
"cannot open include file %s.", filename.c_str());
|
||||
delete stream;
|
||||
}
|
||||
}
|
||||
else
|
||||
error("include_file syntax error.");
|
||||
}
|
||||
else
|
||||
liberty_report->fileWarn(25, sta::liberty_filename, sta::liberty_line,
|
||||
"cannot open include file %s.", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
libertyIncludeEnd()
|
||||
LibertyScanner::fileEnd()
|
||||
{
|
||||
gzclose(liberty_stream);
|
||||
liberty_stream = liberty_stream_prev;
|
||||
liberty_filename = liberty_filename_prev;
|
||||
liberty_line = liberty_line_prev;
|
||||
if (stream_prev_)
|
||||
delete stream_;
|
||||
stream_ = stream_prev_;
|
||||
filename_ = filename_prev_;
|
||||
stream_prev_ = nullptr;
|
||||
|
||||
liberty_filename_prev = nullptr;
|
||||
liberty_stream_prev = nullptr;
|
||||
yypop_buffer_state();
|
||||
}
|
||||
|
||||
void
|
||||
libertyIncrLine()
|
||||
LibertyScanner::error(const char *msg)
|
||||
{
|
||||
sta::liberty_line++;
|
||||
}
|
||||
|
||||
int
|
||||
libertyLine()
|
||||
{
|
||||
return liberty_line;
|
||||
report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg);
|
||||
}
|
||||
|
||||
void
|
||||
libertyParseError(const char *fmt, ...)
|
||||
LibertyParse::error(const location_type &loc,
|
||||
const string &msg)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
sta::liberty_report->vfileError(25, sta::liberty_filename, sta::liberty_line,
|
||||
fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
deleteLibertyGroups()
|
||||
{
|
||||
liberty_group_stack.deleteContentsClear();
|
||||
reader->report()->fileError(164, reader->filename().c_str(),
|
||||
loc.begin.line, "%s", msg.c_str());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
// Global namespace
|
||||
|
||||
void libertyParseFlushBuffer();
|
||||
|
||||
int
|
||||
LibertyParse_error(const char *msg)
|
||||
{
|
||||
libertyParseFlushBuffer();
|
||||
sta::liberty_report->fileError(26, sta::liberty_filename, sta::liberty_line,
|
||||
"%s.", msg);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ class LibertyAttrValue;
|
|||
class LibertyVariable;
|
||||
class LibertySubgroupIterator;
|
||||
class LibertyAttrIterator;
|
||||
class LibertyScanner;
|
||||
|
||||
typedef Vector<LibertyStmt*> LibertyStmtSeq;
|
||||
typedef Vector<LibertyGroup*> LibertyGroupSeq;
|
||||
|
|
@ -53,25 +54,50 @@ typedef Vector<LibertyAttrValue*> LibertyAttrValueSeq;
|
|||
typedef Map<const char *, float, CharPtrLess> LibertyVariableMap;
|
||||
typedef Map<const char*,LibertyGroupVisitor*,CharPtrLess>LibertyGroupVisitorMap;
|
||||
typedef LibertyAttrValueSeq::Iterator LibertyAttrValueIterator;
|
||||
typedef Vector<LibertyGroup*> LibertyGroupSeq;
|
||||
|
||||
enum class LibertyAttrType { attr_string, attr_int, attr_double,
|
||||
attr_boolean, attr_unknown };
|
||||
|
||||
enum class LibertyGroupType { library, cell, pin, timing, unknown };
|
||||
|
||||
// flex YY_INPUT yy_n_chars arg changed definition from int to size_t,
|
||||
// so provide both forms.
|
||||
void
|
||||
libertyGetChars(char *buf,
|
||||
size_t &result,
|
||||
size_t max_size);
|
||||
void
|
||||
libertyGetChars(char *buf,
|
||||
int &result,
|
||||
size_t max_size);
|
||||
class LibertyParser
|
||||
{
|
||||
public:
|
||||
LibertyParser(const char *filename,
|
||||
LibertyGroupVisitor *library_visitor,
|
||||
Report *report);
|
||||
const string &filename() const { return filename_; }
|
||||
void setFilename(const string &filename);
|
||||
Report *report() const { return report_; }
|
||||
LibertyStmt *makeDefine(LibertyAttrValueSeq *values,
|
||||
int line);
|
||||
LibertyAttrType attrValueType(const char *value_type_name);
|
||||
LibertyGroupType groupType(const char *group_type_name);
|
||||
void groupBegin(const char *type,
|
||||
LibertyAttrValueSeq *params,
|
||||
int line);
|
||||
LibertyGroup *groupEnd();
|
||||
LibertyGroup *group();
|
||||
void deleteGroups();
|
||||
LibertyStmt *makeSimpleAttr(const char *name,
|
||||
LibertyAttrValue *value,
|
||||
int line);
|
||||
LibertyStmt *makeComplexAttr(const char *name,
|
||||
LibertyAttrValueSeq *values,
|
||||
int line);
|
||||
LibertyAttrValue *makeStringAttrValue(char *value);
|
||||
LibertyAttrValue *makeFloatAttrValue(float value);
|
||||
LibertyStmt *makeVariable(char *var,
|
||||
float value,
|
||||
int line);
|
||||
|
||||
#define YY_INPUT(buf,result,max_size) \
|
||||
sta::libertyGetChars(buf, result, max_size)
|
||||
private:
|
||||
string filename_;
|
||||
LibertyGroupVisitor *group_visitor_;
|
||||
Report *report_;
|
||||
LibertyGroupSeq group_stack_;
|
||||
};
|
||||
|
||||
// Abstract base class for liberty statements.
|
||||
class LibertyStmt
|
||||
|
|
@ -289,52 +315,8 @@ public:
|
|||
virtual bool save(LibertyVariable *variable) = 0;
|
||||
};
|
||||
|
||||
void
|
||||
libertyIncludeBegin(const char *filename);
|
||||
void
|
||||
libertyIncludeEnd();
|
||||
bool
|
||||
libertyInInclude();
|
||||
void
|
||||
libertyIncrLine();
|
||||
void
|
||||
libertyParseError(const char *fmt,
|
||||
...);
|
||||
int
|
||||
libertyLine();
|
||||
|
||||
void
|
||||
parseLibertyFile(const char *filename,
|
||||
LibertyGroupVisitor *library_visitor,
|
||||
Report *report);
|
||||
void
|
||||
libertyGroupBegin(const char *type,
|
||||
LibertyAttrValueSeq *params,
|
||||
int line);
|
||||
LibertyGroup *
|
||||
libertyGroupEnd();
|
||||
LibertyGroup *
|
||||
libertyGroup();
|
||||
LibertyStmt *
|
||||
makeLibertyComplexAttr(const char *name,
|
||||
LibertyAttrValueSeq *values,
|
||||
int line);
|
||||
LibertyStmt *
|
||||
makeLibertySimpleAttr(const char *name,
|
||||
LibertyAttrValue *value,
|
||||
int line);
|
||||
LibertyAttrValue *
|
||||
makeLibertyFloatAttrValue(float value);
|
||||
LibertyAttrValue *
|
||||
makeLibertyStringAttrValue(char *value);
|
||||
LibertyStmt *
|
||||
makeLibertyVariable(char *var,
|
||||
float value,
|
||||
int line);
|
||||
|
||||
} // namespace
|
||||
|
||||
// Global namespace.
|
||||
int
|
||||
LibertyParse_error(const char *msg);
|
||||
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ LibertyReader::init(const char *filename,
|
|||
in_bus_ = false;
|
||||
in_bundle_ = false;
|
||||
in_ccsn_ = false;
|
||||
in_ecsm_waveform_ = false;
|
||||
sequential_ = nullptr;
|
||||
statetable_ = nullptr;
|
||||
timing_ = nullptr;
|
||||
|
|
@ -570,6 +571,9 @@ LibertyReader::defineVisitors()
|
|||
&LibertyReader::endCcsn);
|
||||
defineGroupVisitor("output_ccb", &LibertyReader::beginCcsn,
|
||||
&LibertyReader::endCcsn);
|
||||
|
||||
defineGroupVisitor("ecsm_waveform", &LibertyReader::beginEcsmWaveform,
|
||||
&LibertyReader::endEcsmWaveform);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1520,7 +1524,7 @@ LibertyReader::visitIndex(int index,
|
|||
{
|
||||
if (tbl_template_
|
||||
// Ignore index_xx in ecsm_waveform groups.
|
||||
&& !stringEq(libertyGroup()->type(), "ecsm_waveform")) {
|
||||
&& !in_ecsm_waveform_) {
|
||||
FloatSeq *axis_values = readFloatSeq(attr, 1.0F);
|
||||
if (axis_values) {
|
||||
if (axis_values->empty())
|
||||
|
|
@ -4657,7 +4661,7 @@ LibertyReader::visitValues(LibertyAttr *attr)
|
|||
{
|
||||
if (tbl_template_
|
||||
// Ignore values in ecsm_waveform groups.
|
||||
&& !stringEq(libertyGroup()->type(), "ecsm_waveform"))
|
||||
&& !in_ecsm_waveform_)
|
||||
makeTable(attr, table_model_scale_);
|
||||
}
|
||||
|
||||
|
|
@ -5667,6 +5671,32 @@ LibertyReader::visitVoltageName(LibertyAttr *attr)
|
|||
}
|
||||
}
|
||||
|
||||
// Contents Ignored.
|
||||
void
|
||||
LibertyReader::beginCcsn(LibertyGroup *)
|
||||
{
|
||||
in_ccsn_ = true;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyReader::endCcsn(LibertyGroup *)
|
||||
{
|
||||
in_ccsn_ = false;
|
||||
}
|
||||
|
||||
// Contents Ignored.
|
||||
void
|
||||
LibertyReader::beginEcsmWaveform(LibertyGroup *)
|
||||
{
|
||||
in_ecsm_waveform_ = true;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyReader::endEcsmWaveform(LibertyGroup *)
|
||||
{
|
||||
in_ecsm_waveform_ = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyFunc::LibertyFunc(const char *expr,
|
||||
|
|
|
|||
|
|
@ -490,30 +490,10 @@ public:
|
|||
void visitDriverWaveformRiseFall(LibertyAttr *attr,
|
||||
const RiseFall *rf);
|
||||
|
||||
// ccsn (not implemented, this is needed to properly ignore ccsn groups)
|
||||
void beginCcsn(LibertyGroup *) { in_ccsn_ = true; }
|
||||
void endCcsn(LibertyGroup *) { in_ccsn_ = false; }
|
||||
|
||||
// Visitors for derived classes to overload.
|
||||
virtual void beginGroup1(LibertyGroup *) {}
|
||||
virtual void beginGroup2(LibertyGroup *) {}
|
||||
virtual void beginGroup3(LibertyGroup *) {}
|
||||
virtual void beginGroup4(LibertyGroup *) {}
|
||||
virtual void beginGroup5(LibertyGroup *) {}
|
||||
virtual void endGroup1(LibertyGroup *) {}
|
||||
virtual void endGroup2(LibertyGroup *) {}
|
||||
virtual void endGroup3(LibertyGroup *) {}
|
||||
virtual void endGroup4(LibertyGroup *) {}
|
||||
virtual void endGroup5(LibertyGroup *) {}
|
||||
virtual void visitAttr1(LibertyAttr *) {}
|
||||
virtual void visitAttr2(LibertyAttr *) {}
|
||||
virtual void visitAttr3(LibertyAttr *) {}
|
||||
virtual void visitAttr4(LibertyAttr *) {}
|
||||
virtual void visitAttr5(LibertyAttr *) {}
|
||||
virtual void visitAttr6(LibertyAttr *) {}
|
||||
virtual void visitAttr7(LibertyAttr *) {}
|
||||
virtual void visitAttr8(LibertyAttr *) {}
|
||||
virtual void visitAttr9(LibertyAttr *) {}
|
||||
void beginCcsn(LibertyGroup *group);
|
||||
void endCcsn(LibertyGroup *group);
|
||||
void beginEcsmWaveform(LibertyGroup *group);
|
||||
void endEcsmWaveform(LibertyGroup *group);
|
||||
|
||||
protected:
|
||||
TimingModel *makeScalarCheckModel(float value,
|
||||
|
|
@ -641,6 +621,7 @@ protected:
|
|||
bool in_bus_;
|
||||
bool in_bundle_;
|
||||
bool in_ccsn_;
|
||||
bool in_ecsm_waveform_;
|
||||
TableAxisVariable axis_var_[3];
|
||||
FloatSeq *axis_values_[3];
|
||||
int type_bit_from_;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2025, 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 <https://www.gnu.org/licenses/>.
|
||||
//
|
||||
// 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
|
||||
|
||||
#ifndef __FLEX_LEXER_H
|
||||
#undef yyFlexLexer
|
||||
#define yyFlexLexer LibertyFlexLexer
|
||||
#include <FlexLexer.h>
|
||||
#endif
|
||||
|
||||
#include "location.hh"
|
||||
#include "LibertyParse.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
class Report;
|
||||
class LibertyParser;
|
||||
|
||||
class LibertyScanner : public LibertyFlexLexer
|
||||
{
|
||||
public:
|
||||
LibertyScanner(std::istream *stream,
|
||||
const char *filename,
|
||||
LibertyParser *reader,
|
||||
Report *report);
|
||||
virtual ~LibertyScanner() {}
|
||||
|
||||
virtual int lex(LibertyParse::semantic_type *const yylval,
|
||||
LibertyParse::location_type *yylloc);
|
||||
// YY_DECL defined in LibertyLex.ll
|
||||
// Method body created by flex in LibertyLex.cc
|
||||
|
||||
// Get rid of override virtual function warning.
|
||||
using FlexLexer::yylex;
|
||||
|
||||
private:
|
||||
bool includeBegin();
|
||||
void fileEnd();
|
||||
void error(const char *msg);
|
||||
|
||||
std::istream *stream_;
|
||||
string filename_;
|
||||
LibertyParser *reader_;
|
||||
Report *report_;
|
||||
string token_;
|
||||
|
||||
// Previous lex state for include files.
|
||||
string filename_prev_;
|
||||
std::istream *stream_prev_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
@ -33,8 +33,6 @@
|
|||
|
||||
// warning: variable 'yynerrs_' set but not used
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
|
||||
#define loc_line(loc) loc.begin.line
|
||||
%}
|
||||
|
||||
%require "3.0"
|
||||
|
|
|
|||
|
|
@ -139,8 +139,8 @@ SdfReader::~SdfReader()
|
|||
bool
|
||||
SdfReader::read()
|
||||
{
|
||||
gzstream::igzstream stream(filename_);
|
||||
if (stream.good()) {
|
||||
gzstream::igzstream stream(filename_.c_str());
|
||||
if (stream.is_open()) {
|
||||
Stats stats(debug_, report_);
|
||||
SdfScanner scanner(&stream, filename_, this, report_);
|
||||
scanner_ = &scanner;
|
||||
|
|
@ -150,7 +150,7 @@ SdfReader::read()
|
|||
return success;
|
||||
}
|
||||
else
|
||||
throw FileNotReadable(filename_);
|
||||
throw FileNotReadable(filename_.c_str());
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -994,7 +994,7 @@ SdfReader::sdfWarn(int id,
|
|||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
report_->vfileWarn(id, filename_, scanner_->lineno(), fmt, args);
|
||||
report_->vfileWarn(id, filename_.c_str(), scanner_->lineno(), fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
|
@ -1004,7 +1004,7 @@ SdfReader::sdfError(int id,
|
|||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
report_->vfileError(id, filename_, scanner_->lineno(), fmt, args);
|
||||
report_->vfileError(id, filename_.c_str(), scanner_->lineno(), fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
|
@ -1087,7 +1087,7 @@ SdfTriple::hasValue() const
|
|||
////////////////////////////////////////////////////////////////
|
||||
|
||||
SdfScanner::SdfScanner(std::istream *stream,
|
||||
const char *filename,
|
||||
const string &filename,
|
||||
SdfReader *reader,
|
||||
Report *report) :
|
||||
yyFlexLexer(stream),
|
||||
|
|
@ -1100,7 +1100,7 @@ SdfScanner::SdfScanner(std::istream *stream,
|
|||
void
|
||||
SdfScanner::error(const char *msg)
|
||||
{
|
||||
report_->fileError(1866, filename_, lineno(), "%s", msg);
|
||||
report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1109,7 +1109,8 @@ void
|
|||
SdfParse::error(const location_type &loc,
|
||||
const string &msg)
|
||||
{
|
||||
reader->report()->fileError(164,reader->filename(),loc.begin.line,"%s",msg.c_str());
|
||||
reader->report()->fileError(164,reader->filename().c_str(),
|
||||
loc.begin.line,"%s",msg.c_str());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ public:
|
|||
void setInIncremental(bool incr);
|
||||
string *makeBusName(string *bus_name,
|
||||
int index);
|
||||
const char *filename() { return filename_; }
|
||||
const string &filename() const { return filename_; }
|
||||
void sdfWarn(int id,
|
||||
const char *fmt, ...);
|
||||
void sdfError(int id,
|
||||
|
|
@ -190,7 +190,7 @@ private:
|
|||
Port *findPort(const Cell *cell,
|
||||
const string *port_name);
|
||||
|
||||
const char *filename_;
|
||||
string filename_;
|
||||
SdfScanner *scanner_;
|
||||
const char *path_;
|
||||
// Which values to pull out of the sdf triples.
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ class SdfScanner : public SdfFlexLexer
|
|||
{
|
||||
public:
|
||||
SdfScanner(std::istream *stream,
|
||||
const char *filename,
|
||||
const string &filename,
|
||||
SdfReader *reader,
|
||||
Report *report);
|
||||
virtual ~SdfScanner() {}
|
||||
|
|
@ -57,10 +57,10 @@ public:
|
|||
using FlexLexer::yylex;
|
||||
|
||||
private:
|
||||
string token_;
|
||||
const char *filename_;
|
||||
string filename_;
|
||||
SdfReader *reader_;
|
||||
Report *report_;
|
||||
string token_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -193,7 +193,8 @@ public:
|
|||
igzstream() : std::istream( &buf) {}
|
||||
igzstream( const char* name, int open_mode = std::ios::in)
|
||||
: gzstreambase( name, open_mode), std::istream( &buf) {}
|
||||
gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
|
||||
int is_open() { return buf.is_open(); }
|
||||
gzstreambuf* rdbuf() { return gzstreambase::rdbuf(); }
|
||||
void open( const char* name, int open_mode = std::ios::in) {
|
||||
gzstreambase::open( name, open_mode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ bool
|
|||
VerilogReader::read(const char *filename)
|
||||
{
|
||||
gzstream::igzstream stream(filename);
|
||||
if (stream.good()) {
|
||||
if (stream.is_open()) {
|
||||
Stats stats(debug_, report_);
|
||||
VerilogScanner scanner(&stream, filename, report_);
|
||||
VerilogParse parser(&scanner, this);
|
||||
|
|
|
|||
Loading…
Reference in New Issue