From 398a22e97d315a3ef3601f5102ea58b0482e6dca Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 1 Feb 2025 14:49:30 -0800 Subject: [PATCH] LibExpr/spef/saif c++ parsers commit a686a6f77e555513adc40228471c1ad1af4646b3 Author: James Cherry Date: Fri Jan 31 18:45:44 2025 -0800 spef compiles Signed-off-by: James Cherry commit 986a3a00c246a927c494066c56bb627e55da8692 Author: James Cherry Date: Fri Jan 31 18:45:32 2025 -0800 spef compiles Signed-off-by: James Cherry commit e8664d21c0b404a82967201c19a087c6680b7177 Author: James Cherry Date: Fri Jan 31 16:36:19 2025 -0800 saif compiles Signed-off-by: James Cherry commit 496569018791bff19e57c534f29ac085520fc520 Author: James Cherry Date: Fri Jan 31 15:25:44 2025 -0800 mv bison error funcs to .yy Signed-off-by: James Cherry commit c1e7638840f94eb0baddee47507e607b000ab858 Author: James Cherry Date: Fri Jan 31 14:19:26 2025 -0800 parser cledanup Signed-off-by: James Cherry commit 22bc72af46114ddb4fc5876655887ef1189f2195 Author: James Cherry Date: Fri Jan 31 14:19:06 2025 -0800 parser cleanup Signed-off-by: James Cherry commit caeedc4c9e2bf8e7a2f4aceb4ee4a5758efd1b36 Author: James Cherry Date: Fri Jan 31 12:52:55 2025 -0800 LibertyParser stack stream Signed-off-by: James Cherry commit e029a01c2fc5ba0ed336978c5853d49095d07d66 Author: James Cherry Date: Fri Jan 31 12:10:35 2025 -0800 bison 3.2 required Signed-off-by: James Cherry commit 2ca9423a2d518f51fdee6c41d41348dbfd548bae Author: James Cherry Date: Fri Jan 31 12:05:19 2025 -0800 LibertyExpr -> LibExpr Signed-off-by: James Cherry commit d64df413675c2978c0f24d5594cc201032233447 Author: James Cherry Date: Fri Jan 31 11:18:05 2025 -0800 LibertyExpr -> LibExpr Signed-off-by: James Cherry commit 57cfbae240984bd7928862b1d6c3b1047ee5d71f Author: James Cherry Date: Fri Jan 31 10:25:49 2025 -0800 comment Signed-off-by: James Cherry commit 5249ac32d809ba30ce09437d61beaf4360bc2cd8 Author: James Cherry Date: Fri Jan 31 10:24:35 2025 -0800 parseError Signed-off-by: James Cherry commit 8c5442007f99c06bfb16a496e00862353c82282c Author: James Cherry Date: Fri Jan 31 10:11:46 2025 -0800 libecxpr parseError unused Signed-off-by: James Cherry commit 67dacf60db2c0d7e3f7ceeae672b4bdaf1e039b7 Author: James Cherry Date: Fri Jan 31 10:09:39 2025 -0800 reader pvt includes Signed-off-by: James Cherry commit 1d7097399b4242833bf5a478c903b5d98afe674b Author: James Cherry Date: Fri Jan 31 09:33:37 2025 -0800 libexpr life Signed-off-by: James Cherry commit cc85e357463399291cb1e7d7b628e5dd356ac8a9 Author: James Cherry Date: Fri Jan 31 09:21:12 2025 -0800 libexpr no location Signed-off-by: James Cherry commit e3ef17a746eb4e8822cce732250ae77261d53cf9 Author: James Cherry Date: Thu Jan 30 22:15:50 2025 -0800 compiles Signed-off-by: James Cherry commit 3a34874297a5c82930ee0bd131425bccf48526ce Author: James Cherry Date: Thu Jan 30 20:03:06 2025 -0800 libexpr parse Signed-off-by: James Cherry Signed-off-by: James Cherry --- CMakeLists.txt | 76 ++--- liberty/{LibertyExprLex.ll => LibExprLex.ll} | 45 ++- .../{LibertyExprParse.yy => LibExprParse.yy} | 57 ++-- liberty/{LibertyExpr.cc => LibExprReader.cc} | 102 ++---- liberty/{LibertyExpr.hh => LibExprReader.hh} | 0 ...{LibertyExprPvt.hh => LibExprReaderPvt.hh} | 24 +- liberty/LibExprScanner.hh | 62 ++++ liberty/LibertyParse.yy | 17 +- liberty/LibertyParser.cc | 19 +- liberty/LibertyReader.cc | 2 +- liberty/LibertyReaderPvt.hh | 8 +- liberty/LibertyScanner.hh | 6 +- parasitics/SpefLex.ll | 171 +++++----- parasitics/SpefParse.yy | 86 +++-- parasitics/SpefReader.cc | 120 +++---- parasitics/SpefReaderPvt.hh | 25 +- parasitics/SpefScanner.hh | 67 ++++ power/SaifLex.ll | 96 +++--- power/SaifParse.yy | 49 ++- power/SaifReader.cc | 108 ++----- power/SaifReaderPvt.hh | 28 +- power/SaifScanner.hh | 66 ++++ sdf/SdfParse.yy | 14 +- sdf/SdfReader.cc | 10 - sdf/SdfScanner.hh | 6 +- verilog/VerilogParse.yy | 9 +- verilog/VerilogReader.hh | 299 ++++++++++++++++++ verilog/VerilogScanner.hh | 6 +- 28 files changed, 942 insertions(+), 636 deletions(-) rename liberty/{LibertyExprLex.ll => LibExprLex.ll} (71%) rename liberty/{LibertyExprParse.yy => LibExprParse.yy} (58%) rename liberty/{LibertyExpr.cc => LibExprReader.cc} (60%) rename liberty/{LibertyExpr.hh => LibExprReader.hh} (100%) rename liberty/{LibertyExprPvt.hh => LibExprReaderPvt.hh} (82%) create mode 100644 liberty/LibExprScanner.hh create mode 100644 parasitics/SpefScanner.hh create mode 100644 power/SaifScanner.hh create mode 100644 verilog/VerilogReader.hh diff --git a/CMakeLists.txt b/CMakeLists.txt index c704ddc6..d6773d91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,8 +101,7 @@ set(STA_SOURCE liberty/LeakagePower.cc liberty/Liberty.cc liberty/LibertyBuilder.cc - liberty/LibertyExpr.cc - liberty/LibertyExprPvt.hh + liberty/LibExprReader.cc liberty/LibertyParser.cc liberty/LibertyReader.cc liberty/LibertyWriter.cc @@ -271,61 +270,48 @@ set(STA_TCL_FILES # Earlier versions of flex use 'register' declarations that are illegal in c++17. #find_package(FLEX 2.6.4) 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 - COMPILE_FLAGS --prefix=LibertyExprLex_) -bison_target(LibertyExprParse ${STA_HOME}/liberty/LibertyExprParse.yy - ${CMAKE_CURRENT_BINARY_DIR}/LibertyExprParse.cc - COMPILE_FLAGS --name-prefix=LibertyExprParse_ - ) -add_flex_bison_dependency(LibertyExprLex LibertyExprParse) - -# Spef scan/parse. -flex_target(SpefLex ${STA_HOME}/parasitics/SpefLex.ll ${CMAKE_CURRENT_BINARY_DIR}/SpefLex.cc - COMPILE_FLAGS --prefix=SpefLex_ - ) -bison_target(SpefParse ${STA_HOME}/parasitics/SpefParse.yy ${CMAKE_CURRENT_BINARY_DIR}/SpefParse.cc - COMPILE_FLAGS --name-prefix=SpefParse_ - ) -add_flex_bison_dependency(SpefLex SpefParse) +find_package(BISON REQUIRED 3.2) # Verilog scan/parse. flex_target(VerilogLex ${STA_HOME}/verilog/VerilogLex.ll ${CMAKE_CURRENT_BINARY_DIR}/VerilogLex.cc) bison_target(VerilogParse ${STA_HOME}/verilog/VerilogParse.yy - ${CMAKE_CURRENT_BINARY_DIR}/VerilogParse.cc - # centos7 bison 3.0.4 < 3.3.0 uses parser_class_name instead of api.parsr.class - COMPILE_FLAGS "-Wno-deprecated") + ${CMAKE_CURRENT_BINARY_DIR}/VerilogParse.cc) add_flex_bison_dependency(VerilogLex VerilogParse) +# 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) +add_flex_bison_dependency(LibertyLex LibertyParse) + +# Liberty Expr scan/parse. +flex_target(LibExprLex ${STA_HOME}/liberty/LibExprLex.ll + ${CMAKE_CURRENT_BINARY_DIR}/LibExprLex.cc) +bison_target(LibExprParse ${STA_HOME}/liberty/LibExprParse.yy + ${CMAKE_CURRENT_BINARY_DIR}/LibExprParse.cc) +add_flex_bison_dependency(LibExprLex LibExprParse) + # Sdf scan/parse. flex_target(SdfLex ${STA_HOME}/sdf/SdfLex.ll ${CMAKE_CURRENT_BINARY_DIR}/SdfLex.cc) bison_target(SdfParse ${STA_HOME}/sdf/SdfParse.yy - ${CMAKE_CURRENT_BINARY_DIR}/SdfParse.cc - # centos7 bison 3.0.4 < 3.3.0 uses parser_class_name instead of api.parsr.class - COMPILE_FLAGS "-Wno-deprecated") + ${CMAKE_CURRENT_BINARY_DIR}/SdfParse.cc) add_flex_bison_dependency(SdfLex SdfParse) +# Spef scan/parse. +flex_target(SpefLex ${STA_HOME}/parasitics/SpefLex.ll + ${CMAKE_CURRENT_BINARY_DIR}/SpefLex.cc) +bison_target(SpefParse ${STA_HOME}/parasitics/SpefParse.yy + ${CMAKE_CURRENT_BINARY_DIR}/SpefParse.cc) +add_flex_bison_dependency(SpefLex SpefParse) + # Saif scan/parse. -flex_target(SaifLex ${STA_HOME}/power/SaifLex.ll ${CMAKE_CURRENT_BINARY_DIR}/SaifLex.cc - COMPILE_FLAGS --prefix=SaifLex_ - ) -bison_target(SaifParse ${STA_HOME}/power/SaifParse.yy ${CMAKE_CURRENT_BINARY_DIR}/SaifParse.cc - COMPILE_FLAGS --name-prefix=SaifParse_ - ) +flex_target(SaifLex ${STA_HOME}/power/SaifLex.ll + ${CMAKE_CURRENT_BINARY_DIR}/SaifLex.cc) +bison_target(SaifParse ${STA_HOME}/power/SaifParse.yy + ${CMAKE_CURRENT_BINARY_DIR}/SaifParse.cc) add_flex_bison_dependency(SaifLex SaifParse) ################################################################ @@ -497,8 +483,8 @@ target_sources(OpenSTA ${STA_TCL_INIT} - ${FLEX_LibertyExprLex_OUTPUTS} - ${BISON_LibertyExprParse_OUTPUTS} + ${FLEX_LibExprLex_OUTPUTS} + ${BISON_LibExprParse_OUTPUTS} ${FLEX_LibertyLex_OUTPUTS} ${BISON_LibertyParse_OUTPUTS} diff --git a/liberty/LibertyExprLex.ll b/liberty/LibExprLex.ll similarity index 71% rename from liberty/LibertyExprLex.ll rename to liberty/LibExprLex.ll index 34a777c1..e9a3f70b 100644 --- a/liberty/LibertyExprLex.ll +++ b/liberty/LibExprLex.ll @@ -1,5 +1,4 @@ %{ - // OpenSTA, Static Timing Analyzer // Copyright (c) 2025, Parallax Software, Inc. // @@ -29,31 +28,31 @@ #include "util/FlexDisableRegister.hh" #include "Debug.hh" #include "StringUtil.hh" -#include "liberty/LibertyExprPvt.hh" +#include "liberty/LibExprReaderPvt.hh" +#include "liberty/LibExprReader.hh" +#include "liberty/LibExprScanner.hh" -using sta::libexpr_parser; using sta::stringCopy; using sta::FuncExpr; -#include "LibertyExprParse.hh" +#include "LibExprParse.hh" -#define YY_NO_INPUT +#undef YY_DECL +#define YY_DECL \ +int \ +sta::LibExprScanner::lex(sta::LibExprParse::semantic_type *const yylval) -#define YY_INPUT(buf,result,max_size) \ - result = libexpr_parser->copyInput(buf, max_size) - -void -libertyExprFlushBuffer() -{ - YY_FLUSH_BUFFER; -} +typedef sta::LibExprParse::token token; %} -/* %option debug */ +%option c++ +%option yyclass="sta::LibExprScanner" +%option prefix="LibExpr" %option noyywrap -%option nounput %option never-interactive +%option stack +/* %option debug */ %x ESCAPED_STRING @@ -67,28 +66,28 @@ EOL \r?\n %% -{OP}|{PAREN} { return ((int) LibertyExprLex_text[0]); } +{OP}|{PAREN} { return ((int) yytext[0]); } {ESCAPE}{EOL} { /* I doubt that escaped returns get thru the parser */ } -{ESCAPE}{QUOTE} { BEGIN(ESCAPED_STRING); libexpr_parser->tokenErase(); } +{ESCAPE}{QUOTE} { BEGIN(ESCAPED_STRING); token_.clear(); } -. { libexpr_parser->tokenAppend(LibertyExprLex_text[0]); } +. { token_ += yytext[0]; } {ESCAPE}{QUOTE} { BEGIN(INITIAL); - LibertyExprParse_lval.string = libexpr_parser->tokenCopy(); - return PORT; + yylval->string = stringCopy(token_.c_str()); + return token::PORT; } {PORT} { - LibertyExprParse_lval.string = stringCopy(LibertyExprLex_text); - return PORT; + yylval->string = stringCopy(yytext); + return token::PORT; } {BLANK} {} /* Send out of bound characters to parser. */ -. { return (int) LibertyExprLex_text[0]; } +. { return (int) yytext[0]; } %% diff --git a/liberty/LibertyExprParse.yy b/liberty/LibExprParse.yy similarity index 58% rename from liberty/LibertyExprParse.yy rename to liberty/LibExprParse.yy index 4e974121..336e0811 100644 --- a/liberty/LibertyExprParse.yy +++ b/liberty/LibExprParse.yy @@ -1,5 +1,3 @@ -%{ - // OpenSTA, Static Timing Analyzer // Copyright (c) 2025, Parallax Software, Inc. // @@ -26,15 +24,35 @@ // Liberty function expression parser. +%{ #include "FuncExpr.hh" -#include "liberty/LibertyExpr.hh" -#include "liberty/LibertyExprPvt.hh" +#include "liberty/LibExprReader.hh" +#include "liberty/LibExprReaderPvt.hh" +#include "liberty/LibExprScanner.hh" -int LibertyExprLex_lex(); -#define LibertyExprParse_lex LibertyExprLex_lex +#undef yylex +#define yylex scanner->lex + +// warning: variable 'yynerrs_' set but not used +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" + +void +sta::LibExprParse::error(const string &msg) +{ + reader->parseError(msg.c_str()); +} %} +%require "3.2" +%skeleton "lalr1.cc" +%debug +%define api.namespace {sta} +%define parse.assert +%parse-param{LibExprScanner *scanner} +%parse-param{LibExprReader *reader} +%define api.parser.class {LibExprParse} + %union { int int_val; const char *string; @@ -50,18 +68,15 @@ int LibertyExprLex_lex(); %type PORT %type expr terminal terminal_expr implicit_and -%{ -%} - %% result_expr: - expr { sta::libexpr_parser->setResult($1); } -| expr ';'{ sta::libexpr_parser->setResult($1); } + expr { reader->setResult($1); } +| expr ';'{ reader->setResult($1); } ; terminal: - PORT { $$ = sta::libexpr_parser->makeFuncExprPort($1); } + PORT { $$ = reader->makeFuncExprPort($1); } | '0' { $$ = sta::FuncExpr::makeZero(); } | '1' { $$ = sta::FuncExpr::makeOne(); } | '(' expr ')' { $$ = $2; } @@ -69,25 +84,25 @@ terminal: terminal_expr: terminal -| '!' terminal { $$ = sta::libexpr_parser->makeFuncExprNot($2); } -| terminal '\'' { $$ = sta::libexpr_parser->makeFuncExprNot($1); } +| '!' terminal { $$ = reader->makeFuncExprNot($2); } +| terminal '\'' { $$ = reader->makeFuncExprNot($1); } ; implicit_and: terminal_expr terminal_expr - { $$ = sta::libexpr_parser->makeFuncExprAnd($1, $2); } + { $$ = reader->makeFuncExprAnd($1, $2); } | implicit_and terminal_expr - { $$ = sta::libexpr_parser->makeFuncExprAnd($1, $2); } + { $$ = reader->makeFuncExprAnd($1, $2); } ; expr: terminal_expr | implicit_and -| expr '+' expr { $$ = sta::libexpr_parser->makeFuncExprOr($1, $3); } -| expr '|' expr { $$ = sta::libexpr_parser->makeFuncExprOr($1, $3); } -| expr '*' expr { $$ = sta::libexpr_parser->makeFuncExprAnd($1, $3); } -| expr '&' expr { $$ = sta::libexpr_parser->makeFuncExprAnd($1, $3); } -| expr '^' expr { $$ = sta::libexpr_parser->makeFuncExprXor($1, $3); } +| expr '+' expr { $$ = reader->makeFuncExprOr($1, $3); } +| expr '|' expr { $$ = reader->makeFuncExprOr($1, $3); } +| expr '*' expr { $$ = reader->makeFuncExprAnd($1, $3); } +| expr '&' expr { $$ = reader->makeFuncExprAnd($1, $3); } +| expr '^' expr { $$ = reader->makeFuncExprXor($1, $3); } ; %% diff --git a/liberty/LibertyExpr.cc b/liberty/LibExprReader.cc similarity index 60% rename from liberty/LibertyExpr.cc rename to liberty/LibExprReader.cc index ef8f31a5..232202a8 100644 --- a/liberty/LibertyExpr.cc +++ b/liberty/LibExprReader.cc @@ -24,19 +24,17 @@ #include "FuncExpr.hh" -#include // min +#include +#include + #include "Report.hh" #include "StringUtil.hh" #include "Liberty.hh" -#include "LibertyExprPvt.hh" - -extern int -LibertyExprParse_parse(); +#include "LibExprReaderPvt.hh" +#include "LibExprScanner.hh" namespace sta { -LibExprParser *libexpr_parser; - FuncExpr * parseFuncExpr(const char *func, LibertyCell *cell, @@ -44,18 +42,20 @@ parseFuncExpr(const char *func, Report *report) { if (func != nullptr && func[0] != '\0') { - LibExprParser parser(func, cell, error_msg, report); - libexpr_parser = &parser; - LibertyExprParse_parse(); - FuncExpr *expr = parser.result(); - libexpr_parser = nullptr; + string func1(func); + std::istringstream stream(func); + LibExprReader reader(func, cell, error_msg, report); + LibExprScanner scanner(stream); + LibExprParse parser(&scanner, &reader); + parser.parse(); + FuncExpr *expr = reader.result(); return expr; } else return nullptr; } -LibExprParser::LibExprParser(const char *func, +LibExprReader::LibExprReader(const char *func, LibertyCell *cell, const char *error_msg, Report *report) : @@ -63,24 +63,17 @@ LibExprParser::LibExprParser(const char *func, cell_(cell), error_msg_(error_msg), report_(report), - result_(nullptr), - token_length_(100), - token_(new char[token_length_]), - token_next_(token_) + result_(nullptr) { } -LibExprParser::~LibExprParser() -{ - stringDelete(token_); -} - +// defined in LibertyReader.cc LibertyPort * libertyReaderFindPort(LibertyCell *cell, const char *port_name); FuncExpr * -LibExprParser::makeFuncExprPort(const char *port_name) +LibExprReader::makeFuncExprPort(const char *port_name) { FuncExpr *expr = nullptr; LibertyPort *port = libertyReaderFindPort(cell_, port_name); @@ -94,7 +87,7 @@ LibExprParser::makeFuncExprPort(const char *port_name) } FuncExpr * -LibExprParser::makeFuncExprNot(FuncExpr *arg) +LibExprReader::makeFuncExprNot(FuncExpr *arg) { if (arg) return FuncExpr::makeNot(arg); @@ -103,7 +96,7 @@ LibExprParser::makeFuncExprNot(FuncExpr *arg) } FuncExpr * -LibExprParser::makeFuncExprXor(FuncExpr *arg1, +LibExprReader::makeFuncExprXor(FuncExpr *arg1, FuncExpr *arg2) { if (arg1 && arg2) @@ -113,7 +106,7 @@ LibExprParser::makeFuncExprXor(FuncExpr *arg1, } FuncExpr * -LibExprParser::makeFuncExprAnd(FuncExpr *arg1, +LibExprReader::makeFuncExprAnd(FuncExpr *arg1, FuncExpr *arg2) { if (arg1 && arg2) @@ -123,7 +116,7 @@ LibExprParser::makeFuncExprAnd(FuncExpr *arg1, } FuncExpr * -LibExprParser::makeFuncExprOr(FuncExpr *arg1, +LibExprReader::makeFuncExprOr(FuncExpr *arg1, FuncExpr *arg2) { if (arg1 && arg2) @@ -133,65 +126,22 @@ LibExprParser::makeFuncExprOr(FuncExpr *arg1, } void -LibExprParser::setResult(FuncExpr *result) +LibExprReader::setResult(FuncExpr *result) { result_ = result; } -size_t -LibExprParser::copyInput(char *buf, - size_t max_size) -{ - strncpy(buf, func_, max_size); - int count = strlen(buf); - func_ += count; - return count; -} - -char * -LibExprParser::tokenCopy() -{ - return stringCopy(token_); -} - void -LibExprParser::tokenErase() -{ - token_next_ = token_; -} - -void -LibExprParser::tokenAppend(char ch) -{ - if (token_next_ + 1 - token_ >= static_cast(token_length_)) { - size_t index = token_next_ - token_; - token_length_ *= 2; - char *prev_token = token_; - token_ = new char[token_length_]; - strcpy(token_, prev_token); - stringDelete(prev_token); - token_next_ = &token_[index]; - } - *token_next_++ = ch; - // Make sure the token is always terminated. - *token_next_ = '\0'; -} - -void -LibExprParser::parseError(const char *msg) +LibExprReader::parseError(const char *msg) { report_->error(1131, "%s %s.", error_msg_, msg); } -} // namespace - //////////////////////////////////////////////////////////////// -// Global namespace -int -LibertyExprParse_error(const char *msg) +LibExprScanner::LibExprScanner(std::istringstream &stream) : + yyFlexLexer(&stream) { - libertyExprFlushBuffer(); - sta::libexpr_parser->parseError(msg); - return 0; } + +} // namespace diff --git a/liberty/LibertyExpr.hh b/liberty/LibExprReader.hh similarity index 100% rename from liberty/LibertyExpr.hh rename to liberty/LibExprReader.hh diff --git a/liberty/LibertyExprPvt.hh b/liberty/LibExprReaderPvt.hh similarity index 82% rename from liberty/LibertyExprPvt.hh rename to liberty/LibExprReaderPvt.hh index 1eea3914..78cf21b6 100644 --- a/liberty/LibertyExprPvt.hh +++ b/liberty/LibExprReaderPvt.hh @@ -29,15 +29,15 @@ namespace sta { class Report; class LibertyCell; class FuncExpr; +class LibExprScanner; -class LibExprParser +class LibExprReader { public: - LibExprParser(const char *func, + LibExprReader(const char *func, LibertyCell *cell, const char *error_msg, Report *report); - ~LibExprParser(); FuncExpr *makeFuncExprPort(const char *port_name); FuncExpr *makeFuncExprOr(FuncExpr *arg1, FuncExpr *arg2); @@ -51,11 +51,7 @@ public: void parseError(const char *msg); size_t copyInput(char *buf, size_t max_size); - void tokenStart(); - const char *token(); - char *tokenCopy(); - void tokenErase(); - void tokenAppend(char ch); + Report *report() const { return report_; } private: const char *func_; @@ -63,18 +59,6 @@ private: const char *error_msg_; Report *report_; FuncExpr *result_; - size_t token_length_; - char *token_; - char *token_next_; }; -extern LibExprParser *libexpr_parser; - } // namespace - -// Global namespace - -void -libertyExprFlushBuffer(); -int -LibertyExprParse_error(const char *msg); diff --git a/liberty/LibExprScanner.hh b/liberty/LibExprScanner.hh new file mode 100644 index 00000000..735abfe2 --- /dev/null +++ b/liberty/LibExprScanner.hh @@ -0,0 +1,62 @@ +// 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 . +// +// 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 + +#include + +#include "LibExprParse.hh" + +#ifndef __FLEX_LEXER_H +#undef yyFlexLexer +#define yyFlexLexer LibExprFlexLexer +#include +#endif + +namespace sta { + +using std::string; + +class Report; +class LibExprParse; + +class LibExprScanner : public LibExprFlexLexer +{ +public: + LibExprScanner(std::istringstream &stream); + virtual ~LibExprScanner() {} + + virtual int lex(LibExprParse::semantic_type *const yylval); + // 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: + Report *report_; + string token_; +}; + +} // namespace diff --git a/liberty/LibertyParse.yy b/liberty/LibertyParse.yy index 9d75f238..64aeb95f 100644 --- a/liberty/LibertyParse.yy +++ b/liberty/LibertyParse.yy @@ -25,7 +25,7 @@ %{ #include -#include "StringUtil.hh" +#include "Report.hh" #include "liberty/LibertyParser.hh" #include "liberty/LibertyScanner.hh" @@ -36,6 +36,15 @@ #pragma GCC diagnostic ignored "-Wunused-but-set-variable" #define loc_line(loc) loc.begin.line + +void +sta::LibertyParse::error(const location_type &loc, + const string &msg) +{ + reader->report()->fileError(164, reader->filename().c_str(), + loc.begin.line, "%s", msg.c_str()); +} + %} %require "3.2" @@ -47,11 +56,7 @@ %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} +%define api.parser.class {LibertyParse} %expect 2 diff --git a/liberty/LibertyParser.cc b/liberty/LibertyParser.cc index c568aa20..6cf896cd 100644 --- a/liberty/LibertyParser.cc +++ b/liberty/LibertyParser.cc @@ -41,18 +41,15 @@ parseLibertyFile(const char *filename, LibertyGroupVisitor *library_visitor, Report *report) { - std::istream *stream = new gzstream::igzstream(filename); - if (stream->good()) { + gzstream::igzstream stream(filename); + if (stream.is_open()) { LibertyParser reader(filename, library_visitor, report); - LibertyScanner scanner(stream, filename, &reader, report); + LibertyScanner scanner(&stream, filename, &reader, report); LibertyParse parser(&scanner, &reader); parser.parse(); - delete stream; } - else { - delete stream; + else throw FileNotReadable(filename); - } } LibertyParser::LibertyParser(const char *filename, @@ -567,12 +564,4 @@ LibertyScanner::error(const char *msg) report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg); } -void -LibertyParse::error(const location_type &loc, - const string &msg) -{ - reader->report()->fileError(164, reader->filename().c_str(), - loc.begin.line, "%s", msg.c_str()); -} - } // namespace diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index 4acff872..cc75aa25 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -41,7 +41,7 @@ #include "LinearModel.hh" #include "Wireload.hh" #include "EquivCells.hh" -#include "LibertyExpr.hh" +#include "LibExprReader.hh" #include "Liberty.hh" #include "LibertyBuilder.hh" #include "LibertyReaderPvt.hh" diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index 7e952f09..c00083b0 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -31,15 +31,17 @@ #include "Map.hh" #include "StringSeq.hh" #include "MinMax.hh" +#include "NetworkClass.hh" #include "Transition.hh" #include "TimingArc.hh" #include "InternalPower.hh" #include "LeakagePower.hh" #include "Liberty.hh" #include "Sequential.hh" +#include "TableModel.hh" #include "LibertyParser.hh" #include "LibertyReader.hh" -#include "NetworkClass.hh" +#include "LibertyBuilder.hh" namespace sta { @@ -494,6 +496,8 @@ public: void endCcsn(LibertyGroup *group); void beginEcsmWaveform(LibertyGroup *group); void endEcsmWaveform(LibertyGroup *group); + LibertyPort *findPort(LibertyCell *cell, + const char *port_name); protected: TimingModel *makeScalarCheckModel(float value, @@ -519,8 +523,6 @@ protected: StdStringSeq parseTokenList(const char *token_str, const char separator); LibertyPort *findPort(const char *port_name); - LibertyPort *findPort(LibertyCell *cell, - const char *port_name); float defaultCap(LibertyPort *port); virtual void visitVariable(LibertyVariable *var); void visitPorts(std::function func); diff --git a/liberty/LibertyScanner.hh b/liberty/LibertyScanner.hh index 54eaf12a..93131d1e 100644 --- a/liberty/LibertyScanner.hh +++ b/liberty/LibertyScanner.hh @@ -24,15 +24,15 @@ #pragma once +#include "LibertyLocation.hh" +#include "LibertyParse.hh" + #ifndef __FLEX_LEXER_H #undef yyFlexLexer #define yyFlexLexer LibertyFlexLexer #include #endif -#include "LibertyLocation.hh" -#include "LibertyParse.hh" - namespace sta { class Report; diff --git a/parasitics/SpefLex.ll b/parasitics/SpefLex.ll index aeb2972d..ea6e08b1 100644 --- a/parasitics/SpefLex.ll +++ b/parasitics/SpefLex.ll @@ -1,5 +1,4 @@ %{ - // OpenSTA, Static Timing Analyzer // Copyright (c) 2025, Parallax Software, Inc. // @@ -31,30 +30,28 @@ #include "StringUtil.hh" #include "parasitics/SpefReaderPvt.hh" #include "SpefParse.hh" +#include "parasitics/SpefScanner.hh" -#define YY_NO_INPUT +#undef YY_DECL +#define YY_DECL \ +int \ +sta::SpefScanner::lex(sta::SpefParse::semantic_type *const yylval, \ + sta::SpefParse::location_type *loc) -static std::string spef_token; - -void -spefFlushBuffer() -{ - YY_FLUSH_BUFFER; -} - -// Reset the start condition to INITIAL. -void -spefResetScanner() -{ - BEGIN(0); -} +// update location on matching +#define YY_USER_ACTION loc->step(); loc->columns(yyleng); +typedef sta::SpefParse::token token; %} -/* %option debug */ +%option c++ +%option yyclass="sta::SpefScanner" +%option prefix="Spef" %option noyywrap -%option nounput %option never-interactive +%option stack +%option yylineno +/* %option debug */ %x COMMENT %x QUOTE @@ -93,123 +90,117 @@ INDEX "*"{POS_INTEGER} %% -"*BUS_DELIMITER" { return BUS_DELIMITER; } -"*C2_R1_C1" { return C2_R1_C1; } -"*C" { return KW_C; } -"*CAP" { return CAP; } -"*CELL" { return CELL; } -"*CONN" { return CONN; } -"*C_UNIT" { return C_UNIT; } -"*SPEF" { return SPEF; } -"*DATE" { return DATE; } -"*DEFINE" { return DEFINE; } -"*DELIMITER" { return DELIMITER; } -"*DESIGN" { return DESIGN; } -"*DESIGN_FLOW" { return DESIGN_FLOW; } -"*DIVIDER" { return DIVIDER; } -"*DRIVER" { return DRIVER; } -"*D_NET" { return D_NET; } -"*D_PNET" { return D_PNET; } -"*D" { return KW_D; } -"*END" { return END; } -"*GROUND_NETS" { return GROUND_NETS; } -"*INDUC" { return INDUC; } -"*I" { return KW_I; } -"*K" { return KW_K; } -"*L" { return KW_L; } -"*LOADS" { return LOADS; } -"*L_UNIT" { return L_UNIT; } -"*NAME_MAP" { return NAME_MAP; } -"*N" { return KW_N; } -"*PDEFINE" { return PDEFINE; } -"*PHYSICAL_PORTS" { return PHYSICAL_PORTS; } -"*PORTS" { return PORTS; } -"*POWER_NETS" { return POWER_NETS; } -"*PROGRAM" { return PROGRAM; } -"*P" { return KW_P; } -"*Q" { return KW_Q; } -"*RC" { return RC; } -"*RES" { return RES; } -"*R_NET" { return R_NET; } -"*R_PNET" { return R_PNET; } -"*R_UNIT" { return R_UNIT; } -"*S" { return KW_S; } -"*T_UNIT" { return T_UNIT; } -"*VENDOR" { return VENDOR; } -"*VERSION" { return PVERSION; } -"*V" { return KW_V; } +"*BUS_DELIMITER" { return token::BUS_DELIMITER; } +"*C2_R1_C1" { return token::C2_R1_C1; } +"*C" { return token::KW_C; } +"*CAP" { return token::CAP; } +"*CELL" { return token::CELL; } +"*CONN" { return token::CONN; } +"*C_UNIT" { return token::C_UNIT; } +"*SPEF" { return token::SPEF; } +"*DATE" { return token::DATE; } +"*DEFINE" { return token::DEFINE; } +"*DELIMITER" { return token::DELIMITER; } +"*DESIGN" { return token::DESIGN; } +"*DESIGN_FLOW" { return token::DESIGN_FLOW; } +"*DIVIDER" { return token::DIVIDER; } +"*DRIVER" { return token::DRIVER; } +"*D_NET" { return token::D_NET; } +"*D_PNET" { return token::D_PNET; } +"*D" { return token::KW_D; } +"*END" { return token::END; } +"*GROUND_NETS" { return token::GROUND_NETS; } +"*INDUC" { return token::INDUC; } +"*I" { return token::KW_I; } +"*K" { return token::KW_K; } +"*L" { return token::KW_L; } +"*LOADS" { return token::LOADS; } +"*L_UNIT" { return token::L_UNIT; } +"*NAME_MAP" { return token::NAME_MAP; } +"*N" { return token::KW_N; } +"*PDEFINE" { return token::PDEFINE; } +"*PHYSICAL_PORTS" { return token::PHYSICAL_PORTS; } +"*PORTS" { return token::PORTS; } +"*POWER_NETS" { return token::POWER_NETS; } +"*PROGRAM" { return token::PROGRAM; } +"*P" { return token::KW_P; } +"*Q" { return token::KW_Q; } +"*RC" { return token::RC; } +"*RES" { return token::RES; } +"*R_NET" { return token::R_NET; } +"*R_PNET" { return token::R_PNET; } +"*R_UNIT" { return token::R_UNIT; } +"*S" { return token::KW_S; } +"*T_UNIT" { return token::T_UNIT; } +"*VENDOR" { return token::VENDOR; } +"*VERSION" { return token::PVERSION; } +"*V" { return token::KW_V; } -"//".*\n { /* Single line comment */ - sta::spef_reader->incrLine(); - } +"//".*\n { loc->lines(); loc->step(); } /* Single line comment */ "/*" { BEGIN COMMENT; } { . -\n { sta::spef_reader->incrLine(); } +\n { loc->lines(); loc->step(); } "*/" { BEGIN INITIAL; } <> { - SpefParse_error("unterminated comment"); + error("unterminated comment"); BEGIN(INITIAL); yyterminate(); } } -"\"" { BEGIN QUOTE; spef_token.erase(); } +"\"" { BEGIN QUOTE; token_.erase(); } { -\r?\n { - sta::spef_reader->incrLine(); - } +\r?\n { loc->lines(); loc->step(); } -"\\". { spef_token += yytext[1]; } +"\\". { token_ += yytext[1]; } "\"" { BEGIN INITIAL; - SpefParse_lval.string = sta::stringCopy(spef_token.c_str()); - return QSTRING; + yylval->string = sta::stringCopy(token_.c_str()); + return token::QSTRING; } -. { spef_token += yytext[0]; } +. { token_ += yytext[0]; } <> { - SpefParse_error("unterminated quoted string"); + error("unterminated quoted string"); BEGIN(INITIAL); yyterminate(); } } -{BLANK}*\n { - sta::spef_reader->incrLine(); - } +{BLANK}*\n { loc->lines(); loc->step(); } {INTEGER} { - SpefParse_lval.integer = atoi(yytext); - return INTEGER; + yylval->integer = atoi(yytext); + return token::INTEGER; } {FLOAT} { - SpefParse_lval.number = static_cast(atof(yytext)); - return FLOAT; + yylval->number = static_cast(atof(yytext)); + return token::FLOAT; } {IDENT} { - SpefParse_lval.string = sta::spef_reader->translated(yytext); - return IDENT; + yylval->string = reader_->translated(yytext); + return token::IDENT; } {PATH}|{NAME_PAIR} { - SpefParse_lval.string = sta::spef_reader->translated(yytext); - return NAME; + yylval->string = reader_->translated(yytext); + return token::NAME; } {INDEX} { - SpefParse_lval.string = sta::stringCopy(yytext); - return INDEX; + yylval->string = sta::stringCopy(yytext); + return token::INDEX; } {HCHAR} { diff --git a/parasitics/SpefParse.yy b/parasitics/SpefParse.yy index ca1e2101..fbf37cf0 100755 --- a/parasitics/SpefParse.yy +++ b/parasitics/SpefParse.yy @@ -1,5 +1,3 @@ -%{ - // OpenSTA, Static Timing Analyzer // Copyright (c) 2025, Parallax Software, Inc. // @@ -24,19 +22,41 @@ // // This notice may not be removed or altered from any source distribution. +%{ #include +#include "Report.hh" #include "StringUtil.hh" #include "StringSeq.hh" #include "parasitics/SpefReaderPvt.hh" +#include "parasitics/SpefScanner.hh" -int SpefLex_lex(); -#define SpefParse_lex SpefLex_lex -// use yacc generated parser errors -#define YYERROR_VERBOSE +#undef yylex +#define yylex scanner->lex +// warning: variable 'yynerrs_' set but not used +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" + +void +sta::SpefParse::error(const location_type &loc, + const string &msg) +{ + reader->report()->fileError(164,reader->filename(), + loc.begin.line,"%s",msg.c_str()); +} %} +%require "3.2" +%skeleton "lalr1.cc" +%debug +%define api.namespace {sta} +%locations +%define api.location.file "SpefLocation.hh" +%define parse.assert +%parse-param { SpefScanner *scanner } +%parse-param { SpefReader *reader } +%define api.parser.class {SpefParse} + %union { char ch; char *string; @@ -195,7 +215,7 @@ vendor: design_flow: DESIGN_FLOW qstrings - { sta::spef_reader->setDesignFlow($2); } + { reader->setDesignFlow($2); } ; qstrings: @@ -209,19 +229,19 @@ qstrings: hierarchy_div_def: DIVIDER hchar - { sta::spef_reader->setDivider($2); } + { reader->setDivider($2); } ; pin_delim_def: DELIMITER hchar - { sta::spef_reader->setDelimiter($2); } + { reader->setDelimiter($2); } ; bus_delim_def: BUS_DELIMITER prefix_bus_delim - { sta::spef_reader->setBusBrackets($2, '\0'); } + { reader->setBusBrackets($2, '\0'); } | BUS_DELIMITER prefix_bus_delim suffix_bus_delim - { sta::spef_reader->setBusBrackets($2, $3); } + { reader->setBusBrackets($2, $3); } ; /****************************************************************/ @@ -235,22 +255,22 @@ unit_def: time_scale: T_UNIT pos_number IDENT - { sta::spef_reader->setTimeScale($2, $3); } + { reader->setTimeScale($2, $3); } ; cap_scale: C_UNIT pos_number IDENT - { sta::spef_reader->setCapScale($2, $3); } + { reader->setCapScale($2, $3); } ; res_scale: R_UNIT pos_number IDENT - { sta::spef_reader->setResScale($2, $3); } + { reader->setResScale($2, $3); } ; induc_scale: L_UNIT pos_number IDENT - { sta::spef_reader->setInductScale($2, $3); } + { reader->setInductScale($2, $3); } ; /****************************************************************/ @@ -267,7 +287,7 @@ name_map_entries: name_map_entry: INDEX mapped_item - { sta::spef_reader->makeNameMapEntry($1, $2); + { reader->makeNameMapEntry($1, $2); sta::stringDelete($1); } ; @@ -330,7 +350,7 @@ port_entry: direction: IDENT - { $$ = sta::spef_reader->portDirection($1); + { $$ = reader->portDirection($1); sta::stringDelete($1); } ; @@ -474,14 +494,14 @@ nets: d_net: D_NET net total_cap - { sta::spef_reader->dspfBegin($2, $3); } + { reader->dspfBegin($2, $3); } routing_conf conn_sec cap_sec res_sec induc_sec END - { sta::spef_reader->dspfFinish(); } + { reader->dspfFinish(); } ; net: name_or_index - { $$ = sta::spef_reader->findNet($1); + { $$ = reader->findNet($1); sta::stringDelete($1); } ; @@ -531,7 +551,7 @@ internal_connection: pin_name: name_or_index - { $$ = sta::spef_reader->findPin($1); + { $$ = reader->findPin($1); sta::stringDelete($1); } ; @@ -565,9 +585,9 @@ cap_elems: cap_elem: cap_id parasitic_node par_value - { sta::spef_reader->makeCapacitor($1, $2, $3); } + { reader->makeCapacitor($1, $2, $3); } | cap_id parasitic_node parasitic_node par_value - { sta::spef_reader->makeCapacitor($1, $2, $3, $4); } + { reader->makeCapacitor($1, $2, $3, $4); } ; cap_id: @@ -593,7 +613,7 @@ res_elems: res_elem: res_id parasitic_node parasitic_node par_value - { sta::spef_reader->makeResistor($1, $2, $3, $4); } + { reader->makeResistor($1, $2, $3, $4); } ; res_id: @@ -626,9 +646,9 @@ induc_id: r_net: R_NET net total_cap - { sta::spef_reader->rspfBegin($2, $3); } + { reader->rspfBegin($2, $3); } routing_conf driver_reducs END - { sta::spef_reader->rspfFinish(); } + { reader->rspfFinish(); } ; driver_reducs: @@ -638,11 +658,11 @@ driver_reducs: driver_reduc: driver_pair driver_cell pi_model - { sta::spef_reader->rspfDrvrBegin($1, $3); + { reader->rspfDrvrBegin($1, $3); sta::stringDelete($2); } load_desc - { sta::spef_reader->rspfDrvrFinish(); } + { reader->rspfDrvrFinish(); } ; driver_pair: @@ -673,9 +693,9 @@ rc_descs: rc_desc: RC pin_name par_value - { sta::spef_reader->rspfLoad($2, $3); } + { reader->rspfLoad($2, $3); } | RC pin_name par_value pole_residue_desc - { sta::spef_reader->rspfLoad($2, $3); } + { reader->rspfLoad($2, $3); } ; pole_residue_desc: @@ -810,7 +830,7 @@ pos_integer: INTEGER { int value = $1; if (value < 0) - sta::spef_reader->warn(1525, "%d is not positive.", value); + reader->warn(1525, "%d is not positive.", value); $$ = value; } ; @@ -819,13 +839,13 @@ pos_number: INTEGER { float value = static_cast($1); if (value < 0) - sta::spef_reader->warn(1526, "%.4f is not positive.", value); + reader->warn(1526, "%.4f is not positive.", value); $$ = value; } | FLOAT { float value = static_cast($1); if (value < 0) - sta::spef_reader->warn(1527, "%.4f is not positive.", value); + reader->warn(1527, "%.4f is not positive.", value); $$ = value; } ; diff --git a/parasitics/SpefReader.cc b/parasitics/SpefReader.cc index f115fbf2..2de26741 100644 --- a/parasitics/SpefReader.cc +++ b/parasitics/SpefReader.cc @@ -40,17 +40,10 @@ #include "ArcDelayCalc.hh" #include "SpefReaderPvt.hh" #include "SpefNamespace.hh" - -int -SpefParse_parse(); -void -spefResetScanner(); +#include "parasitics/SpefScanner.hh" namespace sta { -// Referenced by parser. -SpefReader *spef_reader; - bool readSpefFile(const char *filename, Instance *instance, @@ -63,35 +56,14 @@ readSpefFile(const char *filename, const MinMaxAll *min_max, StaState *sta) { - bool success = false; - const ArcDelayCalc *arc_delay_calc = sta->arcDelayCalc(); - if (reduce && !arc_delay_calc->reduceSupported()) { - sta->report()->warn(1658, "Delay calculator %s does not support reduction.", - arc_delay_calc->name()); - reduce = false; - } - // Use zlib to uncompress gzip'd files automagically. - gzFile stream = gzopen(filename, "rb"); - if (stream) { - Stats stats(sta->debug(), sta->report()); - SpefReader reader(filename, stream, instance, ap, - pin_cap_included, keep_coupling_caps, coupling_cap_factor, - reduce, corner, min_max, sta); - spef_reader = &reader; - ::spefResetScanner(); - // yyparse returns 0 on success. - success = (::SpefParse_parse() == 0); - gzclose(stream); - spef_reader = nullptr; - stats.report("Read spef"); - } - else - throw FileNotReadable(filename); + SpefReader reader(filename, instance, ap, + pin_cap_included, keep_coupling_caps, coupling_cap_factor, + reduce, corner, min_max, sta); + bool success = reader.read(); return success; } SpefReader::SpefReader(const char *filename, - gzFile stream, Instance *instance, ParasiticAnalysisPt *ap, bool pin_cap_included, @@ -110,8 +82,6 @@ SpefReader::SpefReader(const char *filename, reduce_(reduce), corner_(corner), min_max_(min_max), - stream_(stream), - line_(1), // defaults divider_('\0'), delimiter_('\0'), @@ -141,6 +111,25 @@ SpefReader::~SpefReader() stringDelete(name); } +bool +SpefReader::read() +{ + bool success; + gzstream::igzstream stream(filename_); + if (stream.is_open()) { + Stats stats(debug_, report_); + SpefScanner scanner(&stream, filename_, this, report_); + scanner_ = &scanner; + SpefParse parser(&scanner, this); + // yyparse returns 0 on success. + success = (parser.parse() == 0); + stats.report("Read spef"); + } + else + throw FileNotReadable(filename_); + return success; +} + void SpefReader::setDivider(char divider) { @@ -154,7 +143,8 @@ SpefReader::setDelimiter(char delimiter) } void -SpefReader::setBusBrackets(char left, char right) +SpefReader::setBusBrackets(char left, + char right) { if (!((left == '[' && right == ']') || (left == '{' && right == '}') @@ -196,30 +186,6 @@ SpefReader::findPortPinRelative(const char *name) return network_->findPin(instance_, name); } -void -SpefReader::getChars(char *buf, - int &result, - size_t max_size) -{ - char *status = gzgets(stream_, buf, max_size); - if (status == Z_NULL) - result = 0; // YY_nullptr - else - result = static_cast(strlen(buf)); -} - -void -SpefReader::getChars(char *buf, - size_t &result, - size_t max_size) -{ - char *status = gzgets(stream_, buf, max_size); - if (status == Z_NULL) - result = 0; // YY_nullptr - else - result = strlen(buf); -} - char * SpefReader::translated(const char *token) { @@ -227,18 +193,12 @@ SpefReader::translated(const char *token) network_->pathEscape()); } -void -SpefReader::incrLine() -{ - line_++; -} - void SpefReader::warn(int id, const char *fmt, ...) { va_list args; va_start(args, fmt); - report_->vfileWarn(id, filename_, line_, fmt, args); + report_->vfileWarn(id, filename_, scanner_->line(), fmt, args); va_end(args); } @@ -644,17 +604,23 @@ SpefTriple::value(int index) const return values_[0]; } -} // namespace - //////////////////////////////////////////////////////////////// -// Global namespace -void spefFlushBuffer(); - -int -SpefParse_error(const char *msg) +SpefScanner::SpefScanner(std::istream *stream, + const string &filename, + SpefReader *reader, + Report *report) : + yyFlexLexer(stream), + filename_(filename), + reader_(reader), + report_(report) { - spefFlushBuffer(); - sta::spef_reader->warn(1657, "%s.", msg); - return 0; } + +void +SpefScanner::error(const char *msg) +{ + report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg); +} + +} // namespace diff --git a/parasitics/SpefReaderPvt.hh b/parasitics/SpefReaderPvt.hh index 7afc2a98..b13f1f2d 100644 --- a/parasitics/SpefReaderPvt.hh +++ b/parasitics/SpefReaderPvt.hh @@ -32,15 +32,6 @@ #include "ParasiticsClass.hh" #include "StaState.hh" -// Global namespace. -#define YY_INPUT(buf,result,max_size) \ - sta::spef_reader->getChars(buf, result, max_size) - -int -SpefParse_error(const char *msg); - -//////////////////////////////////////////////////////////////// - namespace sta { class Report; @@ -48,6 +39,7 @@ class MinMaxAll; class SpefRspfPi; class SpefTriple; class Corner; +class SpefScanner; typedef std::map> SpefNameMap; @@ -55,7 +47,6 @@ class SpefReader : public StaState { public: SpefReader(const char *filename, - gzFile stream, Instance *instance, ParasiticAnalysisPt *ap, bool pin_cap_included, @@ -66,21 +57,12 @@ public: const MinMaxAll *min_max, StaState *sta); virtual ~SpefReader(); + bool read(); char divider() const { return divider_; } void setDivider(char divider); char delimiter() const { return delimiter_; } void setDelimiter(char delimiter); - void incrLine(); - int line() const { return line_; } const char *filename() const { return filename_; } - // flex YY_INPUT yy_n_chars arg changed definition from int to size_t, - // so provide both forms. - void getChars(char *buf, - int &result, - size_t max_size); - void getChars(char *buf, - size_t &result, - size_t max_size); // Translate from spf/spef namespace to sta namespace. char *translated(const char *token); void warn(int id, @@ -136,6 +118,7 @@ private: bool local_only); const char *filename_; + SpefScanner *scanner_; Instance *instance_; const ParasiticAnalysisPt *ap_; bool pin_cap_included_; @@ -144,8 +127,6 @@ private: const Corner *corner_; const MinMaxAll *min_max_; // Normally no need to keep device names. - gzFile stream_; - int line_; char divider_; char delimiter_; char bus_brkt_left_; diff --git a/parasitics/SpefScanner.hh b/parasitics/SpefScanner.hh new file mode 100644 index 00000000..5c607749 --- /dev/null +++ b/parasitics/SpefScanner.hh @@ -0,0 +1,67 @@ +// 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 . +// +// 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 + +#include "SpefLocation.hh" +#include "SpefParse.hh" + +#ifndef __FLEX_LEXER_H +#undef yyFlexLexer +#define yyFlexLexer SpefFlexLexer +#include +#endif + +namespace sta { + +class Report; + +class SpefScanner : public SpefFlexLexer +{ +public: + SpefScanner(std::istream *stream, + const string &filename, + SpefReader *reader, + Report *report); + virtual ~SpefScanner() {} + + virtual int lex(SpefParse::semantic_type *const yylval, + SpefParse::location_type *yylloc); + // YY_DECL defined in SpefLex.ll + // Method body created by flex in SpefLex.cc + + void error(const char *msg); + int line() const { return yylineno; } + + // Get rid of override virtual function warning. + using FlexLexer::yylex; + +private: + string filename_; + SpefReader *reader_; + Report *report_; + string token_; +}; + +} // namespace diff --git a/power/SaifLex.ll b/power/SaifLex.ll index ea2c484f..e602983b 100644 --- a/power/SaifLex.ll +++ b/power/SaifLex.ll @@ -1,5 +1,4 @@ %{ - // OpenSTA, Static Timing Analyzer // Copyright (c) 2025, Parallax Software, Inc. // @@ -30,23 +29,28 @@ #include "StringUtil.hh" #include "power/SaifReaderPvt.hh" #include "SaifParse.hh" +#include "power/SaifScanner.hh" -#define YY_NO_INPUT +#undef YY_DECL +#define YY_DECL \ +int \ +sta::SaifScanner::lex(sta::SaifParse::semantic_type *const yylval, \ + sta::SaifParse::location_type *loc) -static std::string saif_token; - -void -saifFlushBuffer() -{ - YY_FLUSH_BUFFER; -} +// update location on matching +#define YY_USER_ACTION loc->step(); loc->columns(yyleng); +typedef sta::SaifParse::token token; %} -/* %option debug */ +%option c++ +%option yyclass="sta::SaifScanner" +%option prefix="Saif" %option noyywrap -%option nounput %option never-interactive +%option stack +%option yylineno +/* %option debug */ %x COMMENT %x QUOTE @@ -65,74 +69,74 @@ EOL \r?\n "*/" { BEGIN INITIAL; } . -{EOL} { sta::saif_reader->incrLine(); } +{EOL} { loc->lines(); loc->step(); } <> { - SaifParse_error("unterminated comment"); + error("unterminated comment"); BEGIN(INITIAL); yyterminate(); } } -"\"" { BEGIN QUOTE; saif_token.erase(); } +"\"" { BEGIN QUOTE; token_.clear(); } { -"\\". { saif_token += yytext[1]; } +"\\". { token_ += yytext[1]; } "\"" { BEGIN INITIAL; - SaifParse_lval.string = sta::stringCopy(saif_token.c_str()); - return QSTRING; + yylval->string = sta::stringCopy(token_.c_str()); + return token::QSTRING; } -. { saif_token += yytext[0]; } +. { token_ += yytext[0]; } <> { - SaifParse_error("unterminated quoted string"); + error("unterminated quoted string"); BEGIN(INITIAL); yyterminate(); } } -"//"[^\n]*{EOL} { sta::saif_reader->incrLine(); } +"//"[^\n]*{EOL} { loc->lines(); loc->step(); } [0-9]+ { - SaifParse_lval.uint = atoll(yytext); - return UINT; + yylval->uint = atoll(yytext); + return token::UINT; } ":"|"{"|"}"|"["|"]"|","|"*"|";"|"="|"-"|"+"|"|"|"("|")"|{HCHAR} { return ((int) yytext[0]); } -SAIFILE { return SAIFILE; } -SAIFVERSION { return SAIFVERSION; } -DIRECTION { return DIRECTION; } -DESIGN { return DESIGN; } -DATE { return DATE; } -VENDOR { return VENDOR; } -PROGRAM_NAME { return PROGRAM_NAME; } -VERSION { return VERSION; } -DIVIDER { return DIVIDER; } -TIMESCALE { return TIMESCALE; } -DURATION { return DURATION; } -INSTANCE { return INSTANCE; } -NET { return NET; } -PORT { return PORT; } -T0 { return T0; } -T1 { return T1; } -TX { return TX; } -TZ { return TZ; } -TB { return TB; } -TC { return TC; } -IG { return IG; } +SAIFILE { return token::SAIFILE; } +SAIFVERSION { return token::SAIFVERSION; } +DIRECTION { return token::DIRECTION; } +DESIGN { return token::DESIGN; } +DATE { return token::DATE; } +VENDOR { return token::VENDOR; } +PROGRAM_NAME { return token::PROGRAM_NAME; } +VERSION { return token::VERSION; } +DIVIDER { return token::DIVIDER; } +TIMESCALE { return token::TIMESCALE; } +DURATION { return token::DURATION; } +INSTANCE { return token::INSTANCE; } +NET { return token::NET; } +PORT { return token::PORT; } +T0 { return token::T0; } +T1 { return token::T1; } +TX { return token::TX; } +TZ { return token::TZ; } +TB { return token::TB; } +TC { return token::TC; } +IG { return token::IG; } {ID} { - SaifParse_lval.string = sta::stringCopy(yytext); - return ID; + yylval->string = sta::stringCopy(yytext); + return token::ID; } -{EOL} { sta::saif_reader->incrLine(); } +{EOL} { loc->lines(); loc->step(); } {BLANK} { /* Ignore blanks. */ } diff --git a/power/SaifParse.yy b/power/SaifParse.yy index b0024f89..15cfd08b 100644 --- a/power/SaifParse.yy +++ b/power/SaifParse.yy @@ -1,5 +1,3 @@ -%{ - // OpenSTA, Static Timing Analyzer // Copyright (c) 2025, Parallax Software, Inc. // @@ -24,20 +22,41 @@ // // This notice may not be removed or altered from any source distribution. +%{ #include +#include "Report.hh" #include "StringUtil.hh" #include "power/SaifReaderPvt.hh" +#include "power/SaifScanner.hh" -int SaifLex_lex(); -#define SaifParse_lex SaifLex_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 + +void +sta::SaifParse::error(const location_type &loc, + const string &msg) +{ + reader->report()->fileError(164,reader->filename(),loc.begin.line,"%s",msg.c_str()); +} %} +%require "3.2" +%skeleton "lalr1.cc" +%debug +%define api.namespace {sta} +%locations +%define api.location.file "SaifLocation.hh" +%define parse.assert +%parse-param { SaifScanner *scanner } +%parse-param { SaifReader *reader } +%define api.parser.class {SaifParse} + // expected shift/reduce conflicts %expect 2 @@ -86,9 +105,9 @@ header_stmt: | '(' VENDOR QSTRING ')' { sta::stringDelete($3); } | '(' PROGRAM_NAME QSTRING ')' { sta::stringDelete($3); } | '(' VERSION QSTRING ')' { sta::stringDelete($3); } -| '(' DIVIDER hchar ')' { sta::saif_reader->setDivider($3); } -| '(' TIMESCALE UINT ID ')' { sta::saif_reader->setTimescale($3, $4); } -| '(' DURATION UINT ')' { sta::saif_reader->setDuration($3); } +| '(' DIVIDER hchar ')' { reader->setDivider($3); } +| '(' TIMESCALE UINT ID ')' { reader->setTimescale($3, $4); } +| '(' DURATION UINT ')' { reader->setDuration($3); } ; hchar: @@ -100,13 +119,13 @@ hchar: instance: '(' INSTANCE ID - { sta::saif_reader->instancePush($3); } + { reader->instancePush($3); } instance_contents ')' - { sta::saif_reader->instancePop(); } + { reader->instancePop(); } | '(' INSTANCE QSTRING ID - { sta::saif_reader->instancePush($3); } + { reader->instancePush($3); } instance_contents ')' - { sta::saif_reader->instancePop(); } + { reader->instancePop(); } ; instance_contents: @@ -128,7 +147,7 @@ nets: net: '(' ID state_durations ')' - { sta::saif_reader->setNetDurations($2, $3); } + { reader->setNetDurations($2, $3); } ; ports: diff --git a/power/SaifReader.cc b/power/SaifReader.cc index 2126545a..629e6008 100644 --- a/power/SaifReader.cc +++ b/power/SaifReader.cc @@ -29,33 +29,27 @@ #include "Error.hh" #include "Debug.hh" +#include "Stats.hh" #include "Report.hh" #include "Network.hh" #include "PortDirection.hh" #include "Sdc.hh" #include "Power.hh" #include "power/SaifReaderPvt.hh" +#include "power/SaifScanner.hh" #include "Sta.hh" -extern int -SaifParse_parse(); -extern int SaifParse_debug; - namespace sta { using std::min; -SaifReader *saif_reader = nullptr; - bool readSaif(const char *filename, const char *scope, Sta *sta) { SaifReader reader(filename, scope, sta); - saif_reader = &reader; bool success = reader.read(); - saif_reader = nullptr; return success; } @@ -65,8 +59,6 @@ SaifReader::SaifReader(const char *filename, StaState(sta), filename_(filename), scope_(scope), - stream_(nullptr), - line_(1), divider_('/'), escape_('\\'), timescale_(1.0E-9F), // default units of ns @@ -76,23 +68,16 @@ SaifReader::SaifReader(const char *filename, { } -SaifReader::~SaifReader() -{ -} - bool SaifReader::read() { - // Use zlib to uncompress gzip'd files automagically. - stream_ = gzopen(filename_, "rb"); - if (stream_) { - saif_scope_.clear(); - in_scope_level_ = 0; - annotated_pins_.clear(); - //::SaifParse_debug = 1; + gzstream::igzstream stream(filename_); + if (stream.is_open()) { + Stats stats(debug_, report_); + SaifScanner scanner(&stream, filename_, this, report_); + SaifParse parser(&scanner, this); // yyparse returns 0 on success. - bool success = (::SaifParse_parse() == 0); - gzclose(stream_); + bool success = (parser.parse() == 0); report_->reportLine("Annotated %zu pin activities.", annotated_pins_.size()); return success; } @@ -122,10 +107,10 @@ SaifReader::setTimescale(uint64_t multiplier, else if (stringEq(units, "fs")) timescale_ = multiplier * 1E-15; else - saifError(180, "TIMESCALE units not us, ns, or ps."); + report_->error(180, "SAIF TIMESCALE units not us, ns, or ps."); } else - saifError(181, "TIMESCALE multiplier not 1, 10, or 100."); + report_->error(181, "SAIF TIMESCALE multiplier not 1, 10, or 100."); stringDelete(units); } @@ -221,72 +206,23 @@ SaifReader::unescaped(const char *token) return unescaped; } -void -SaifReader::incrLine() +//////////////////////////////////////////////////////////////// + +SaifScanner::SaifScanner(std::istream *stream, + const string &filename, + SaifReader *reader, + Report *report) : + yyFlexLexer(stream), + filename_(filename), + reader_(reader), + report_(report) { - line_++; } void -SaifReader::getChars(char *buf, - size_t &result, - size_t max_size) +SaifScanner::error(const char *msg) { - char *status = gzgets(stream_, buf, max_size); - if (status == Z_NULL) - result = 0; // YY_nullptr - else - result = strlen(buf); -} - -void -SaifReader::getChars(char *buf, - int &result, - size_t max_size) -{ - char *status = gzgets(stream_, buf, max_size); - if (status == Z_NULL) - result = 0; // YY_nullptr - else - result = strlen(buf); -} - -void -SaifReader::notSupported(const char *feature) -{ - saifError(193, "%s not supported.", feature); -} - -void -SaifReader::saifWarn(int id, - const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - report_->vfileWarn(id, filename_, line_, fmt, args); - va_end(args); -} - -void -SaifReader::saifError(int id, - const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - report_->vfileError(id, filename_, line_, fmt, args); - va_end(args); + report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg); } } // namespace - -// Global namespace - -void saifFlushBuffer(); - -int -SaifParse_error(const char *msg) -{ - saifFlushBuffer(); - sta::saif_reader->saifError(196, "%s.\n", msg); - return 0; -} diff --git a/power/SaifReaderPvt.hh b/power/SaifReaderPvt.hh index bf498329..ec8d316c 100644 --- a/power/SaifReaderPvt.hh +++ b/power/SaifReaderPvt.hh @@ -38,15 +38,11 @@ // global namespace -#define YY_INPUT(buf,result,max_size) \ - sta::saif_reader->getChars(buf, result, max_size) -int -SaifParse_error(const char *msg); - namespace sta { class Sta; class Power; +class SaifScanner; using std::vector; using std::string; @@ -61,7 +57,6 @@ public: SaifReader(const char *filename, const char *scope, Sta *sta); - ~SaifReader(); bool read(); void setDivider(char divider); @@ -72,24 +67,7 @@ public: void instancePop(); void setNetDurations(const char *net_name, SaifStateDurations &durations); - - // flex YY_INPUT yy_n_chars arg changed definition from int to size_t, - // so provide both forms. - void getChars(char *buf, - size_t &result, - size_t max_size); - void getChars(char *buf, - int &result, - size_t max_size); - void incrLine(); const char *filename() { return filename_; } - int line() { return line_; } - void saifWarn(int id, - const char *fmt, ...); - void saifError(int id, - const char *fmt, - ...); - void notSupported(const char *feature); private: string unescaped(const char *token); @@ -97,8 +75,6 @@ private: const char *filename_; const char *scope_; // Divider delimited scope to begin annotation. - gzFile stream_; - int line_; char divider_; char escape_; double timescale_; @@ -111,6 +87,4 @@ private: Power *power_; }; -extern SaifReader *saif_reader; - } // namespace diff --git a/power/SaifScanner.hh b/power/SaifScanner.hh new file mode 100644 index 00000000..f4d4f486 --- /dev/null +++ b/power/SaifScanner.hh @@ -0,0 +1,66 @@ +// 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 . +// +// 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 + +#include "SaifLocation.hh" +#include "SaifParse.hh" + +#ifndef __FLEX_LEXER_H +#undef yyFlexLexer +#define yyFlexLexer SaifFlexLexer +#include +#endif + +namespace sta { + +class Report; + +class SaifScanner : public SaifFlexLexer +{ +public: + SaifScanner(std::istream *stream, + const string &filename, + SaifReader *reader, + Report *report); + virtual ~SaifScanner() {} + + virtual int lex(SaifParse::semantic_type *const yylval, + SaifParse::location_type *yylloc); + // YY_DECL defined in SaifLex.ll + // Method body created by flex in SaifLex.cc + + void error(const char *msg); + + // Get rid of override virtual function warning. + using FlexLexer::yylex; + +private: + string filename_; + SaifReader *reader_; + Report *report_; + string token_; +}; + +} // namespace diff --git a/sdf/SdfParse.yy b/sdf/SdfParse.yy index 023433b7..ee7ba2c5 100644 --- a/sdf/SdfParse.yy +++ b/sdf/SdfParse.yy @@ -33,6 +33,14 @@ // warning: variable 'yynerrs_' set but not used #pragma GCC diagnostic ignored "-Wunused-but-set-variable" + +void +sta::SdfParse::error(const location_type &loc, + const string &msg) +{ + reader->report()->fileError(164,reader->filename().c_str(), + loc.begin.line,"%s",msg.c_str()); +} %} %require "3.2" @@ -44,11 +52,7 @@ %define parse.assert %parse-param { SdfScanner *scanner } %parse-param { SdfReader *reader } - -// bison 3.0.4 for centos7 -%define parser_class_name {SdfParse} -// bison 3.3.2 -//%define api.parser.class {SdfParse} +%define api.parser.class {SdfParse} // expected shift/reduce conflicts %expect 4 diff --git a/sdf/SdfReader.cc b/sdf/SdfReader.cc index 9d561613..963db575 100644 --- a/sdf/SdfReader.cc +++ b/sdf/SdfReader.cc @@ -1103,14 +1103,4 @@ SdfScanner::error(const char *msg) report_->fileError(1866, filename_.c_str(), lineno(), "%s", msg); } -//////////////////////////////////////////////////////////////// - -void -SdfParse::error(const location_type &loc, - const string &msg) -{ - reader->report()->fileError(164,reader->filename().c_str(), - loc.begin.line,"%s",msg.c_str()); -} - } // namespace diff --git a/sdf/SdfScanner.hh b/sdf/SdfScanner.hh index 4e4bd9ec..9b1b92f1 100644 --- a/sdf/SdfScanner.hh +++ b/sdf/SdfScanner.hh @@ -24,15 +24,15 @@ #pragma once +#include "SdfLocation.hh" +#include "SdfParse.hh" + #ifndef __FLEX_LEXER_H #undef yyFlexLexer #define yyFlexLexer SdfFlexLexer #include #endif -#include "SdfLocation.hh" -#include "SdfParse.hh" - namespace sta { class Report; diff --git a/verilog/VerilogParse.yy b/verilog/VerilogParse.yy index c06bb7a7..acaf3ae0 100644 --- a/verilog/VerilogParse.yy +++ b/verilog/VerilogParse.yy @@ -44,7 +44,8 @@ void sta::VerilogParse::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(),loc.begin.line, + "%s",msg.c_str()); } %} @@ -57,11 +58,7 @@ sta::VerilogParse::error(const location_type &loc, %define parse.assert %parse-param { VerilogScanner *scanner } %parse-param { VerilogReader *reader } - -// bison 3.0.4 for centos7 -%define parser_class_name {VerilogParse} -// bison 3.3.2 -//%define api.parser.class {VerilogParse} +%define api.parser.class {VerilogParse} %union { int ival; diff --git a/verilog/VerilogReader.hh b/verilog/VerilogReader.hh new file mode 100644 index 00000000..79c5c467 --- /dev/null +++ b/verilog/VerilogReader.hh @@ -0,0 +1,299 @@ +// 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 . +// +// 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 + +#include + +#include "StringSet.hh" +#include "Vector.hh" +#include "Map.hh" +#include "NetworkClass.hh" + +namespace sta { + +class VerilogScanner; +class VerilogParse; +class Debug; +class Report; +class VerilogAttrEntry; +class VerilogAttrStmt; +class VerilogReader; +class VerilogStmt; +class VerilogNet; +class VerilogNetScalar; +class VerilogModule; +class VerilogInst; +class VerilogModuleInst; +class VerilogLibertyInst; +class VerilogDcl; +class VerilogDclBus; +class VerilogDclArg; +class VerilogAssign; +class VerilogNetConcat; +class VerilogNetConstant; +class VerilogNetBitSelect; +class VerilogNetPartSelect; +class StringRegistry; +class VerilogBindingTbl; +class VerilogNetNameIterator; +class VerilogNetPortRef; +class VerilogError; +class LibertyCell; + +typedef Map VerilogModuleMap; +typedef Vector VerilogStmtSeq; +typedef Vector VerilogNetSeq; +typedef Vector VerilogDclArgSeq; +typedef Vector VerilogAttrStmtSeq; +typedef Vector VerilogAttrEntrySeq; +typedef Vector VerilogErrorSeq; + +using std::string; +using std::vector; +using std::set; + +class VerilogReader +{ +public: + VerilogReader(NetworkReader *network); + ~VerilogReader(); + bool read(const char *filename); + + void makeModule(const string *module_name, + VerilogNetSeq *ports, + VerilogStmtSeq *stmts, + VerilogAttrStmtSeq *attr_stmts, + int line); + void makeModule(const string *module_name, + VerilogStmtSeq *port_dcls, + VerilogStmtSeq *stmts, + VerilogAttrStmtSeq *attr_stmts, + int line); + VerilogDcl *makeDcl(PortDirection *dir, + VerilogDclArgSeq *args, + VerilogAttrStmtSeq *attr_stmts, + int line); + VerilogDcl *makeDcl(PortDirection *dir, + VerilogDclArg *arg, + VerilogAttrStmtSeq *attr_stmts, + int line); + VerilogDclArg *makeDclArg(const string *net_name); + VerilogDclArg*makeDclArg(VerilogAssign *assign); + VerilogDclBus *makeDclBus(PortDirection *dir, + int from_index, + int to_index, + VerilogDclArg *arg, + VerilogAttrStmtSeq *attr_stmts, + int line); + VerilogDclBus *makeDclBus(PortDirection *dir, + int from_index, + int to_index, + VerilogDclArgSeq *args, + VerilogAttrStmtSeq *attr_stmts, + int line); + VerilogInst *makeModuleInst(const string *module_name, + const string *inst_name, + VerilogNetSeq *pins, + VerilogAttrStmtSeq *attr_stmts, + const int line); + VerilogAssign *makeAssign(VerilogNet *lhs, + VerilogNet *rhs, + int line); + VerilogNetScalar *makeNetScalar(const string *name); + VerilogNetPortRef *makeNetNamedPortRefScalarNet(const string *port_vname); + VerilogNetPortRef *makeNetNamedPortRefScalarNet(const string *port_name, + const string *net_name); + VerilogNetPortRef *makeNetNamedPortRefBitSelect(const string *port_name, + const string *bus_name, + int index); + VerilogNetPortRef *makeNetNamedPortRefScalar(const string *port_name, + VerilogNet *net); + VerilogNetPortRef *makeNetNamedPortRefBit(const string *port_name, + int index, + VerilogNet *net); + VerilogNetPortRef *makeNetNamedPortRefPart(const string *port_name, + int from_index, + int to_index, + VerilogNet *net); + VerilogNetConcat *makeNetConcat(VerilogNetSeq *nets); + VerilogNetConstant *makeNetConstant(const string *constant, + int line); + VerilogNetBitSelect *makeNetBitSelect(const string *name, + int index); + VerilogNetPartSelect *makeNetPartSelect(const string *name, + int from_index, + int to_index); + VerilogModule *module(Cell *cell); + Instance *linkNetwork(const char *top_cell_name, + bool make_black_boxes); + const char *filename() const { return filename_.c_str(); } + void incrLine(); + Report *report() const { return report_; } + void error(int id, + const char *filename, + int line, + const char *fmt, ...); + void warn(int id, + const char *filename, + int line, + const char *fmt, ...); + const string &zeroNetName() const { return zero_net_name_; } + const string &oneNetName() const { return one_net_name_; } + void deleteModules(); + void reportStmtCounts(); + const string &constant10Max() const { return constant10_max_; } + +protected: + void init(const char *filename); + void makeCellPorts(Cell *cell, + VerilogModule *module, + VerilogNetSeq *ports); + Port *makeCellPort(Cell *cell, + VerilogModule *module, + const string &port_name); + void makeNamedPortRefCellPorts(Cell *cell, + VerilogModule *module, + VerilogNet *mod_port, + StdStringSet &port_names); + void checkModuleDcls(VerilogModule *module, + set &port_names); + void makeModuleInstBody(VerilogModule *module, + Instance *inst, + VerilogBindingTbl *bindings, + bool make_black_boxes); + void makeModuleInstNetwork(VerilogModuleInst *mod_inst, + Instance *parent, + VerilogModule *parent_module, + VerilogBindingTbl *parent_bindings, + bool make_black_boxes); + void makeLibertyInst(VerilogLibertyInst *lib_inst, + Instance *parent, + VerilogModule *parent_module, + VerilogBindingTbl *parent_bindings); + void bindGlobalNets(VerilogBindingTbl *bindings); + void makeNamedInstPins1(Cell *cell, + Instance *inst, + VerilogModuleInst *mod_inst, + VerilogBindingTbl *bindings, + Instance *parent, + VerilogBindingTbl *parent_bindings, + bool is_leaf); + void makeNamedInstPins(Cell *cell, + Instance *inst, + VerilogModuleInst *mod_inst, + VerilogBindingTbl *bindings, + Instance *parent, + VerilogModule *parent_module, + VerilogBindingTbl *parent_bindings, + bool is_leaf); + void makeOrderedInstPins(Cell *cell, + Instance *inst, + VerilogModuleInst *mod_inst, + VerilogBindingTbl *bindings, + Instance *parent, + VerilogModule *parent_module, + VerilogBindingTbl *parent_bindings, + bool is_leaf); + void mergeAssignNet(VerilogAssign *assign, + VerilogModule *module, + Instance *inst, + VerilogBindingTbl *bindings); + void makeInstPin(Instance *inst, + Port *port, + VerilogNetNameIterator *net_name_iter, + VerilogBindingTbl *bindings, + Instance *parent, + VerilogBindingTbl *parent_bindings, + bool is_leaf); + void makeInstPin(Instance *inst, + Port *port, + const string &net_name, + VerilogBindingTbl *bindings, + Instance *parent, + VerilogBindingTbl *parent_bindings, + bool is_leaf); + void linkWarn(int id, + const char *filename, + int line, + const char *msg, ...) + __attribute__((format (printf, 5, 6))); + void linkError(int id, + const char *filename, + int line, + const char *msg, ...) + __attribute__((format (printf, 5, 6))); + bool reportLinkErrors(); + bool haveLinkErrors(); + Cell *makeBlackBox(VerilogModuleInst *mod_inst, + VerilogModule *parent_module); + void makeBlackBoxNamedPorts(Cell *cell, + VerilogModuleInst *mod_inst, + VerilogModule *parent_module); + void makeBlackBoxOrderedPorts(Cell *cell, + VerilogModuleInst *mod_inst, + VerilogModule *parent_module); + bool isBlackBox(Cell *cell); + bool hasScalarNamedPortRefs(LibertyCell *liberty_cell, + VerilogNetSeq *pins); + + string filename_; + Report *report_; + Debug *debug_; + NetworkReader *network_; + + Library *library_; + int black_box_index_; + VerilogModuleMap module_map_; + VerilogErrorSeq link_errors_; + const string zero_net_name_; + const string one_net_name_; + string constant10_max_; + ViewType *view_type_; + bool report_stmt_stats_; + int module_count_; + int inst_mod_count_; + int inst_lib_count_; + int inst_lib_net_arrays_; + int port_names_; + int inst_module_names_; + int inst_names_; + int dcl_count_; + int dcl_bus_count_; + int dcl_arg_count_; + int net_scalar_count_; + int net_scalar_names_; + int net_bus_names_; + int net_part_select_count_; + int net_bit_select_count_; + int net_port_ref_scalar_count_; + int net_port_ref_scalar_net_count_; + int net_port_ref_bit_count_; + int net_port_ref_part_count_; + int net_constant_count_; + int assign_count_; + int concat_count_; +}; + +} // namespace sta diff --git a/verilog/VerilogScanner.hh b/verilog/VerilogScanner.hh index 94838685..f2dbec19 100644 --- a/verilog/VerilogScanner.hh +++ b/verilog/VerilogScanner.hh @@ -24,15 +24,15 @@ #pragma once +#include "VerilogLocation.hh" +#include "VerilogParse.hh" + #ifndef __FLEX_LEXER_H #undef yyFlexLexer #define yyFlexLexer VerilogFlexLexer #include #endif -#include "VerilogLocation.hh" -#include "VerilogParse.hh" - namespace sta { class Report;