From c9a872670722370ab7152d15690f9fbfd9c22ff4 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Sat, 25 Jan 2025 11:34:04 -0700 Subject: [PATCH] c++ sdf reader commit da9f267cbb3ed711bff3d2e2c1470fa12f7de26c Author: James Cherry Date: Sat Jan 25 11:31:41 2025 -0700 zlib optional Signed-off-by: James Cherry commit dfbe36202ef77f77e1a7c42163db9f6a5d9a8380 Author: James Cherry Date: Fri Jan 24 19:24:05 2025 -0700 sdf use option for prefix Signed-off-by: James Cherry commit bd7fc399ddfa472e25606c92421c123a725181da Author: James Cherry Date: Fri Jan 24 18:57:46 2025 -0700 mv sdf error to reader Signed-off-by: James Cherry commit 088d43b0e5c90b0bc24c64384164f1bcc50c5165 Author: James Cherry Date: Fri Jan 24 18:48:28 2025 -0700 sdf lex use option for previs Signed-off-by: James Cherry commit 6ccf8c33bd8c44fdd914d9a36fa703a7594353e2 Author: James Cherry Date: Fri Jan 24 17:10:07 2025 -0700 sdf error Signed-off-by: James Cherry commit 43794955a9f79a2900bb8e4cef030a907347627a Author: James Cherry Date: Fri Jan 24 16:13:00 2025 -0700 SdfParse reorg sections Signed-off-by: James Cherry commit 666062124f5718a512092fcdd295827cfb2b6c51 Author: James Cherry Date: Fri Jan 24 16:07:51 2025 -0700 sdf lex previs Signed-off-by: James Cherry commit 83e9925e09817f39d60ae0292fd9eed5e6c40f43 Author: James Cherry Date: Fri Jan 24 16:05:11 2025 -0700 sdf clenup directives Signed-off-by: James Cherry commit dd71619af605abdaaaa9feb0800eb78e225828d6 Author: James Cherry Date: Fri Jan 24 11:41:47 2025 -0700 sdf parse valgrind pass Signed-off-by: James Cherry commit c068e6512824ac27a99fdaa6dcd9a908ee991857 Author: James Cherry Date: Fri Jan 24 08:45:39 2025 -0700 sdf parse Signed-off-by: James Cherry commit 454602fbd464387442cd1e296f3f0e3b5c366e52 Author: James Cherry Date: Thu Jan 23 21:50:24 2025 -0700 sdf parse passes Signed-off-by: James Cherry commit a352451c163f95f82446f2a25d39706f68ae98d6 Author: James Cherry Date: Thu Jan 23 19:15:09 2025 -0700 sdf parse pass all but 1 Signed-off-by: James Cherry commit 87d537582134a767a13ec4596957b7d7a8e1edfd Author: James Cherry Date: Thu Jan 23 12:53:15 2025 -0700 sdf parse report_checks4 Signed-off-by: James Cherry commit c2ee81a51d4fba1281bf452055c9113af7a0de1f Author: James Cherry Date: Thu Jan 23 12:30:25 2025 -0700 sdf link Signed-off-by: James Cherry commit d71e4b0c8f95256ab3ec9e53e26218baaa3c9f8c Author: James Cherry Date: Thu Jan 23 12:02:45 2025 -0700 sdf parse compiles Signed-off-by: James Cherry commit 6ca6800d5cd52640e275bf7eb77a8b1db85e2957 Author: James Cherry Date: Wed Jan 22 18:19:27 2025 -0700 sdf reader c++ Signed-off-by: James Cherry Signed-off-by: James Cherry --- CMakeLists.txt | 12 +- sdf/SdfLex.ll | 171 +++++++++++---------- sdf/SdfParse.yy | 184 +++++++++++----------- sdf/SdfReader.cc | 362 +++++++++++++++++++++----------------------- sdf/SdfReaderPvt.hh | 75 ++++----- sdf/SdfScanner.hh | 66 ++++++++ 6 files changed, 457 insertions(+), 413 deletions(-) create mode 100644 sdf/SdfScanner.hh diff --git a/CMakeLists.txt b/CMakeLists.txt index c69dadc2..4940f6bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -311,12 +311,12 @@ bison_target(VerilogParse ${STA_HOME}/verilog/VerilogParse.yy add_flex_bison_dependency(VerilogLex VerilogParse) # Sdf scan/parse. -flex_target(SdfLex ${STA_HOME}/sdf/SdfLex.ll ${CMAKE_CURRENT_BINARY_DIR}/SdfLex.cc - COMPILE_FLAGS --prefix=SdfLex_ - ) -bison_target(SdfParse ${STA_HOME}/sdf/SdfParse.yy ${CMAKE_CURRENT_BINARY_DIR}/SdfParse.cc - COMPILE_FLAGS --name-prefix=SdfParse_ - ) +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") add_flex_bison_dependency(SdfLex SdfParse) # Saif scan/parse. diff --git a/sdf/SdfLex.ll b/sdf/SdfLex.ll index 60940928..33d0a349 100644 --- a/sdf/SdfLex.ll +++ b/sdf/SdfLex.ll @@ -1,5 +1,4 @@ %{ - // OpenSTA, Static Timing Analyzer // Copyright (c) 2025, Parallax Software, Inc. // @@ -27,23 +26,28 @@ #include "util/FlexDisableRegister.hh" #include "sdf/SdfReaderPvt.hh" #include "SdfParse.hh" +#include "sdf/SdfScanner.hh" -#define YY_NO_INPUT +#undef YY_DECL +#define YY_DECL \ +int \ +sta::SdfScanner::lex(sta::SdfParse::semantic_type *const yylval, \ + sta::SdfParse::location_type *loc) -static std::string sdf_token; - -void -sdfFlushBuffer() -{ - YY_FLUSH_BUFFER; -} +// update location on matching +#define YY_USER_ACTION loc->step(); loc->columns(yyleng); +typedef sta::SdfParse::token token; %} -/* %option debug */ +%option c++ +%option yyclass="sta::SdfScanner" +%option prefix="Sdf" %option noyywrap -%option nounput %option never-interactive +%option stack +%option yylineno +/* %option debug */ %x COMMENT %x QUOTE @@ -62,140 +66,139 @@ EOL \r?\n "*/" { BEGIN INITIAL; } . -{EOL} { sta::sdf_reader->incrLine(); } +{EOL} { loc->lines(); loc->step(); } <> { - SdfParse_error("unterminated comment"); + error("unterminated comment"); BEGIN(INITIAL); yyterminate(); } } -"\"" { BEGIN QUOTE; sdf_token.erase(); } +"\"" { BEGIN QUOTE; token_.clear(); } { -"\\". { sdf_token += yytext[1]; } +"\\". { token_ += yytext[1]; } "\"" { BEGIN INITIAL; - SdfParse_lval.string = sta::stringCopy(sdf_token.c_str()); - return QSTRING; + yylval->string = new string(token_); + return token::QSTRING; } -. { sdf_token += yytext[0]; } +. { token_ += yytext[0]; } <> { - SdfParse_error("unterminated quoted string"); + error("unterminated quoted string"); BEGIN(INITIAL); yyterminate(); } } -"//"[^\n]*{EOL} { sta::sdf_reader->incrLine(); } +"//"[^\n]*{EOL} { loc->lines(); loc->step(); } ("-"|"+")?([0-9]*)("."[0-9]+)([eE]("-"|"+")?[0-9]+)? { - SdfParse_lval.number = static_cast(atof(yytext)); - return FNUMBER; + yylval->number = atof(yytext); + return token::FNUMBER; } "+"?[0-9]+ { - SdfParse_lval.integer = atoi(yytext); - return DNUMBER; + yylval->integer = atoi(yytext); + return token::DNUMBER; } ":"|"{"|"}"|"["|"]"|","|"*"|";"|"="|"-"|"+"|"|"|"("|")"|{HCHAR} { return ((int) yytext[0]); } -ABSOLUTE { return ABSOLUTE; } -CELL { return CELL; } -CELLTYPE { return CELLTYPE; } -DATE { return DATE; } -DELAY { return DELAY; } -DELAYFILE { return DELAYFILE; } -DESIGN { return DESIGN; } -DEVICE { return DEVICE; } -DIVIDER { return DIVIDER; } -HOLD { return HOLD; } -INCREMENTAL|INCREMENT { return INCREMENTAL; } -INSTANCE { return INSTANCE; } -INTERCONNECT { return INTERCONNECT; } -IOPATH { return IOPATH; } -NOCHANGE { return NOCHANGE; } -PERIOD { return PERIOD; } -PORT { return PORT; } -PROCESS { return PROCESS; } -PROGRAM { return PROGRAM; } -RECOVERY { return RECOVERY; } -RECREM { return RECREM; } -REMOVAL { return REMOVAL; } -RETAIN { return RETAIN; } -SDFVERSION { return SDFVERSION; } -SETUP { return SETUP; } -SETUPHOLD { return SETUPHOLD; } -SKEW { return SKEW; } -TEMPERATURE { return TEMPERATURE; } -TIMESCALE { return TIMESCALE; } -TIMINGCHECK { return TIMINGCHECK; } -VENDOR { return VENDOR; } -VERSION { return PVERSION; } -VOLTAGE { return VOLTAGE; } -WIDTH { return WIDTH; } -negedge { return NEGEDGE; } -posedge { return POSEDGE; } - -CONDELSE { return CONDELSE; } +ABSOLUTE { return token::ABSOLUTE; } +CELL { return token::CELL; } +CELLTYPE { return token::CELLTYPE; } +DATE { return token::DATE; } +DELAY { return token::DELAY; } +DELAYFILE { return token::DELAYFILE; } +DESIGN { return token::DESIGN; } +DEVICE { return token::DEVICE; } +DIVIDER { return token::DIVIDER; } +HOLD { return token::HOLD; } +INCREMENTAL|INCREMENT { return token::INCREMENTAL; } +INSTANCE { return token::INSTANCE; } +INTERCONNECT { return token::INTERCONNECT; } +IOPATH { return token::IOPATH; } +NOCHANGE { return token::NOCHANGE; } +PERIOD { return token::PERIOD; } +PORT { return token::PORT; } +PROCESS { return token::PROCESS; } +PROGRAM { return token::PROGRAM; } +RECOVERY { return token::RECOVERY; } +RECREM { return token::RECREM; } +REMOVAL { return token::REMOVAL; } +RETAIN { return token::RETAIN; } +SDFVERSION { return token::SDFVERSION; } +SETUP { return token::SETUP; } +SETUPHOLD { return token::SETUPHOLD; } +SKEW { return token::SKEW; } +TEMPERATURE { return token::TEMPERATURE; } +TIMESCALE { return token::TIMESCALE; } +TIMINGCHECK { return token::TIMINGCHECK; } +VENDOR { return token::VENDOR; } +VERSION { return token::PVERSION; } +VOLTAGE { return token::VOLTAGE; } +WIDTH { return token::WIDTH; } +negedge { return token::NEGEDGE; } +posedge { return token::POSEDGE; } +CONDELSE { return token::CONDELSE; } COND { BEGIN COND_EXPR; - sdf_token.erase(); - return COND; + token_.clear(); + return token::COND; } "("{BLANK}*IOPATH { BEGIN INITIAL; - SdfParse_lval.string = sta::stringCopy(sdf_token.c_str()); - return EXPR_OPEN_IOPATH; + yylval->string = new string(token_); + return token::EXPR_OPEN_IOPATH; } "(" { /* Timing check conditions don't allow parens, * so use the paren as a marker for the end of the expr. */ - if (sta::sdf_reader->inTimingCheck()) { + if (reader_->inTimingCheck()) { BEGIN INITIAL; - SdfParse_lval.string= sta::stringCopy(sdf_token.c_str()); - return EXPR_OPEN; - } - else - sdf_token += yytext[0]; + yylval->string = new string(token_); + return token::EXPR_OPEN; } + else + token_ += yytext[0]; +} {BLANK}+{ID}{BLANK}*")" { /* (COND expr port) */ - if (sta::sdf_reader->inTimingCheck()) { + if (reader_->inTimingCheck()) { BEGIN INITIAL; /* remove trailing ")" */ - yytext[strlen(yytext)-1] = '\0'; - sdf_token += yytext; - SdfParse_lval.string= sta::stringCopy(sdf_token.c_str()); + string cond_id(token_); + cond_id += yytext; + yylval->string = new string(cond_id.substr(0, cond_id.size() - 1)); /* No way to pass expr and id separately, so pass them together. */ - return EXPR_ID_CLOSE; + return token::EXPR_ID_CLOSE; } - else - sdf_token += yytext; - } + else + token_ += yytext[0]; +} {BLANK} {} -. { sdf_token += yytext[0]; } +. { token_ += yytext[0]; } {ID} { - SdfParse_lval.string = sta::stringCopy(yytext); - return ID; + yylval->string = new string(yytext); + return token::ID; } -{EOL} { sta::sdf_reader->incrLine(); } +{EOL} { loc->lines(); loc->step(); } {BLANK} { /* Ignore blanks. */ } diff --git a/sdf/SdfParse.yy b/sdf/SdfParse.yy index 593e6aa6..11ef84a3 100644 --- a/sdf/SdfParse.yy +++ b/sdf/SdfParse.yy @@ -1,5 +1,3 @@ -%{ - // OpenSTA, Static Timing Analyzer // Copyright (c) 2025, Parallax Software, Inc. // @@ -24,25 +22,41 @@ // // This notice may not be removed or altered from any source distribution. +%{ #include #include "sdf/SdfReaderPvt.hh" +#include "sdf/SdfScanner.hh" -int SdfLex_lex(); -#define SdfParse_lex SdfLex_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 { 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} + // expected shift/reduce conflicts %expect 4 %union { char character; - const char *string; + std::string *string; float number; float *number_ptr; int integer; @@ -72,10 +86,10 @@ int SdfLex_lex(); %type port_transition %type hchar -%start file +// Used by error recovery. +%destructor { delete $$; } QSTRING -%{ -%} +%start file %% @@ -90,23 +104,22 @@ header: // technically the ordering of these statements is fixed by the spec header_stmt: - '(' SDFVERSION QSTRING ')' { sta::stringDelete($3); } -| '(' DESIGN QSTRING ')' { sta::stringDelete($3); } -| '(' DATE QSTRING ')' { sta::stringDelete($3); } -| '(' VENDOR QSTRING ')' { sta::stringDelete($3); } -| '(' PROGRAM QSTRING ')' { sta::stringDelete($3); } -| '(' PVERSION QSTRING ')' { sta::stringDelete($3); } -| '(' DIVIDER hchar ')' { sta::sdf_reader->setDivider($3); } -| '(' VOLTAGE triple ')' { sta::sdf_reader->deleteTriple($3); } + '(' SDFVERSION QSTRING ')' { delete $3; } +| '(' DESIGN QSTRING ')' { delete $3; } +| '(' DATE QSTRING ')' { delete $3; } +| '(' VENDOR QSTRING ')' { delete $3; } +| '(' PROGRAM QSTRING ')' { delete $3; } +| '(' PVERSION QSTRING ')' { delete $3; } +| '(' DIVIDER hchar ')' { reader->setDivider($3); } +| '(' VOLTAGE triple ')' { reader->deleteTriple($3); } | '(' VOLTAGE NUMBER ')' | '(' VOLTAGE ')' // Illegal SDF (from OC). -| '(' PROCESS QSTRING ')' { sta::stringDelete($3); } +| '(' PROCESS QSTRING ')' { delete $3; } | '(' PROCESS ')' // Illegal SDF (from OC). | '(' TEMPERATURE NUMBER ')' -| '(' TEMPERATURE triple ')' { sta::sdf_reader->deleteTriple($3); } +| '(' TEMPERATURE triple ')' { reader->deleteTriple($3); } | '(' TEMPERATURE ')' // Illegal SDF (from OC). -| '(' TIMESCALE NUMBER ID ')' - { sta::sdf_reader->setTimescale($3, $4); } +| '(' TIMESCALE NUMBER ID ')' { reader->setTimescale($3, $4); } ; hchar: @@ -116,7 +129,7 @@ hchar: { $$ = '.'; } ; -number_opt: { $$ = NULL; } +number_opt: { $$ = nullptr; } | NUMBER { $$ = new float($1); } ; @@ -127,21 +140,21 @@ cells: cell: '(' CELL celltype cell_instance timing_specs ')' - { sta::sdf_reader->cellFinish(); } + { reader->cellFinish(); } ; celltype: '(' CELLTYPE QSTRING ')' - { sta::sdf_reader->setCell($3); } + { reader->setCell($3); } ; cell_instance: '(' INSTANCE ')' - { sta::sdf_reader->setInstance(NULL); } + { reader->setInstance(nullptr); } | '(' INSTANCE '*' ')' - { sta::sdf_reader->setInstanceWildcard(); } + { reader->setInstanceWildcard(); } | '(' INSTANCE path ')' - { sta::sdf_reader->setInstance($3); } + { reader->setInstance($3); } ; timing_specs: @@ -160,10 +173,10 @@ deltypes: deltype: '(' ABSOLUTE - { sta::sdf_reader->setInIncremental(false); } + { reader->setInIncremental(false); } del_defs ')' | '(' INCREMENTAL - { sta::sdf_reader->setInIncremental(true); } + { reader->setInIncremental(true); } del_defs ')' ; @@ -173,28 +186,28 @@ del_defs: path: ID - { $$ = sta::sdf_reader->unescaped($1); } + { $$ = reader->unescaped($1); } | path hchar ID - { $$ = sta::sdf_reader->makePath($1, sta::sdf_reader->unescaped($3)); } + { $$ = reader->makePath($1, reader->unescaped($3)); } ; del_def: '(' IOPATH port_spec port_instance retains delval_list ')' - { sta::sdf_reader->iopath($3, $4, $6, NULL, false); } + { reader->iopath($3, $4, $6, nullptr, false); } | '(' CONDELSE '(' IOPATH port_spec port_instance retains delval_list ')' ')' - { sta::sdf_reader->iopath($5, $6, $8, NULL, true); } + { reader->iopath($5, $6, $8, nullptr, true); } | '(' COND EXPR_OPEN_IOPATH port_spec port_instance retains delval_list ')' ')' - { sta::sdf_reader->iopath($4, $5, $7, $3, false); } + { reader->iopath($4, $5, $7, $3, false); } | '(' INTERCONNECT port_instance port_instance delval_list ')' - { sta::sdf_reader->interconnect($3, $4, $5); } + { reader->interconnect($3, $4, $5); } | '(' PORT port_instance delval_list ')' - { sta::sdf_reader->port($3, $4); } + { reader->port($3, $4); } | '(' DEVICE delval_list ')' - { sta::sdf_reader->device($3); } + { reader->device($3); } | '(' DEVICE port_instance delval_list ')' - { sta::sdf_reader->device($3, $4); } + { reader->device($3, $4); } ; retains: @@ -204,12 +217,12 @@ retains: retain: '(' RETAIN delval_list ')' - { sta::sdf_reader->deleteTripleSeq($3); } + { reader->deleteTripleSeq($3); } ; delval_list: value - { $$ = sta::sdf_reader->makeTripleSeq(); $$->push_back($1); } + { $$ = reader->makeTripleSeq(); $$->push_back($1); } | delval_list value { $1->push_back($2); $$ = $1; } ; @@ -219,80 +232,77 @@ tchk_defs: ; tchk_def: - '(' SETUP { sta::sdf_reader->setInTimingCheck(true); } + '(' SETUP { reader->setInTimingCheck(true); } port_tchk port_tchk value ')' - { sta::sdf_reader->timingCheck(sta::TimingRole::setup(), $4, $5, $6); - sta::sdf_reader->setInTimingCheck(false); + { reader->timingCheck(sta::TimingRole::setup(), $4, $5, $6); + reader->setInTimingCheck(false); } -| '(' HOLD { sta::sdf_reader->setInTimingCheck(true); } +| '(' HOLD { reader->setInTimingCheck(true); } port_tchk port_tchk value ')' - { sta::sdf_reader->timingCheck(sta::TimingRole::hold(), $4, $5, $6); - sta::sdf_reader->setInTimingCheck(false); + { reader->timingCheck(sta::TimingRole::hold(), $4, $5, $6); + reader->setInTimingCheck(false); } -| '(' SETUPHOLD { sta::sdf_reader->setInTimingCheck(true); } +| '(' SETUPHOLD { reader->setInTimingCheck(true); } port_tchk port_tchk value value ')' - { sta::sdf_reader->timingCheckSetupHold($4, $5, $6, $7); - sta::sdf_reader->setInTimingCheck(false); + { reader->timingCheckSetupHold($4, $5, $6, $7); + reader->setInTimingCheck(false); } -| '(' RECOVERY { sta::sdf_reader->setInTimingCheck(true); } +| '(' RECOVERY { reader->setInTimingCheck(true); } port_tchk port_tchk value ')' - { sta::sdf_reader->timingCheck(sta::TimingRole::recovery(),$4,$5,$6); - sta::sdf_reader->setInTimingCheck(false); + { reader->timingCheck(sta::TimingRole::recovery(),$4,$5,$6); + reader->setInTimingCheck(false); } -| '(' REMOVAL { sta::sdf_reader->setInTimingCheck(true); } +| '(' REMOVAL { reader->setInTimingCheck(true); } port_tchk port_tchk value ')' - { sta::sdf_reader->timingCheck(sta::TimingRole::removal(),$4,$5,$6); - sta::sdf_reader->setInTimingCheck(false); + { reader->timingCheck(sta::TimingRole::removal(),$4,$5,$6); + reader->setInTimingCheck(false); } -| '(' RECREM { sta::sdf_reader->setInTimingCheck(true); } +| '(' RECREM { reader->setInTimingCheck(true); } port_tchk port_tchk value value ')' - { sta::sdf_reader->timingCheckRecRem($4, $5, $6, $7); - sta::sdf_reader->setInTimingCheck(false); + { reader->timingCheckRecRem($4, $5, $6, $7); + reader->setInTimingCheck(false); } -| '(' SKEW { sta::sdf_reader->setInTimingCheck(true); } +| '(' SKEW { reader->setInTimingCheck(true); } port_tchk port_tchk value ')' // Sdf skew clk/ref are reversed from liberty. - { sta::sdf_reader->timingCheck(sta::TimingRole::skew(),$5,$4,$6); - sta::sdf_reader->setInTimingCheck(false); + { reader->timingCheck(sta::TimingRole::skew(),$5,$4,$6); + reader->setInTimingCheck(false); } -| '(' WIDTH { sta::sdf_reader->setInTimingCheck(true); } +| '(' WIDTH { reader->setInTimingCheck(true); } port_tchk value ')' - { sta::sdf_reader->timingCheckWidth($4, $5); - sta::sdf_reader->setInTimingCheck(false); + { reader->timingCheckWidth($4, $5); + reader->setInTimingCheck(false); } -| '(' PERIOD { sta::sdf_reader->setInTimingCheck(true); } +| '(' PERIOD { reader->setInTimingCheck(true); } port_tchk value ')' - { sta::sdf_reader->timingCheckPeriod($4, $5); - sta::sdf_reader->setInTimingCheck(false); + { reader->timingCheckPeriod($4, $5); + reader->setInTimingCheck(false); } -| '(' NOCHANGE { sta::sdf_reader->setInTimingCheck(true); } +| '(' NOCHANGE { reader->setInTimingCheck(true); } port_tchk port_tchk value value ')' - { sta::sdf_reader->timingCheckNochange($4, $5, $6, $7); - sta::sdf_reader->setInTimingCheck(false); + { reader->timingCheckNochange($4, $5, $6, $7); + reader->setInTimingCheck(false); } ; port: ID - { $$ = sta::sdf_reader->unescaped($1); } + { $$ = reader->unescaped($1); } | ID '[' DNUMBER ']' - { const char *bus_name = sta::sdf_reader->unescaped($1); - $$ = sta::stringPrint("%s[%d]", bus_name, $3); - sta::stringDelete(bus_name); - } + { $$ = reader->makeBusName($1, $3); } ; port_instance: port | path hchar port - { $$ = sta::sdf_reader->makePath($1, $3); } + { $$ = reader->makePath($1, $3); } ; port_spec: port_instance - { $$=sta::sdf_reader->makePortSpec(sta::Transition::riseFall(),$1,NULL); } + { $$=reader->makePortSpec(sta::Transition::riseFall(),$1,nullptr); } | '(' port_transition port_instance ')' - { $$ = sta::sdf_reader->makePortSpec($2, $3, NULL); } + { $$ = reader->makePortSpec($2, $3, nullptr); } ; port_transition: @@ -303,19 +313,19 @@ port_transition: port_tchk: port_spec | '(' COND EXPR_ID_CLOSE - { $$ = sta::sdf_reader->makeCondPortSpec($3); } + { $$ = reader->makeCondPortSpec($3); } | '(' COND EXPR_OPEN port_transition port_instance ')' ')' - { $$ = sta::sdf_reader->makePortSpec($4, $5, $3); } + { $$ = reader->makePortSpec($4, $5, $3); } ; value: '(' ')' { - $$ = sta::sdf_reader->makeTriple(); + $$ = reader->makeTriple(); } | '(' NUMBER ')' { - $$ = sta::sdf_reader->makeTriple($2); + $$ = reader->makeTriple($2); } | '(' triple ')' { $$ = $2; } ; @@ -324,17 +334,17 @@ triple: NUMBER ':' number_opt ':' number_opt { float *fp = new float($1); - $$ = sta::sdf_reader->makeTriple(fp, $3, $5); + $$ = reader->makeTriple(fp, $3, $5); } | number_opt ':' NUMBER ':' number_opt { float *fp = new float($3); - $$ = sta::sdf_reader->makeTriple($1, fp, $5); + $$ = reader->makeTriple($1, fp, $5); } | number_opt ':' number_opt ':' NUMBER { float *fp = new float($5); - $$ = sta::sdf_reader->makeTriple($1, $3, fp); + $$ = reader->makeTriple($1, $3, fp); } ; diff --git a/sdf/SdfReader.cc b/sdf/SdfReader.cc index 415f10fe..768f093e 100644 --- a/sdf/SdfReader.cc +++ b/sdf/SdfReader.cc @@ -27,8 +27,10 @@ #include #include +#include "Zlib.hh" #include "Error.hh" #include "Debug.hh" +#include "Stats.hh" #include "Report.hh" #include "MinMax.hh" #include "TimingArc.hh" @@ -39,13 +41,12 @@ #include "DcalcAnalysisPt.hh" #include "Sdc.hh" #include "sdf/SdfReaderPvt.hh" - -extern int -SdfParse_parse(); -extern int SdfParse_debug; +#include "sdf/SdfScanner.hh" namespace sta { +using std::to_string; + class SdfTriple { public: @@ -63,22 +64,20 @@ private: class SdfPortSpec { public: - SdfPortSpec(Transition *tr, - const char *port, - const char *cond); + SdfPortSpec(const Transition *tr, + const string *port, + const string *cond); ~SdfPortSpec(); - const char *port() const { return port_; } - Transition *transition() const { return tr_; } - const char *cond() const { return cond_; } + const string *port() const { return port_; } + const Transition *transition() const { return tr_; } + const string *cond() const { return cond_; } private: - Transition *tr_; - const char *port_; - const char *cond_; // timing checks only + const Transition *tr_; + const string *port_; + const string *cond_; // timing checks only }; -SdfReader *sdf_reader = nullptr; - bool readSdf(const char *filename, const char *path, @@ -95,9 +94,7 @@ readSdf(const char *filename, sta->sdc()->analysisType(), unescaped_dividers, incremental_only, cond_use, sta); - sdf_reader = &reader; bool success = reader.read(); - sdf_reader = nullptr; return success; } @@ -121,7 +118,6 @@ SdfReader::SdfReader(const char *filename, unescaped_dividers_(unescaped_dividers), is_incremental_only_(is_incremental_only), cond_use_(cond_use), - line_(1), divider_('/'), escape_('\\'), instance_(nullptr), @@ -143,13 +139,14 @@ SdfReader::~SdfReader() bool SdfReader::read() { - // Use zlib to uncompress gzip'd files automagically. - stream_ = gzopen(filename_, "rb"); - //::SdfParse_debug = 1; - if (stream_) { - // yyparse returns 0 on success. - bool success = (::SdfParse_parse() == 0); - gzclose(stream_); + gzstream::igzstream stream(filename_); + if (stream.good()) { + Stats stats(debug_, report_); + SdfScanner scanner(&stream, filename_, this, report_); + scanner_ = &scanner; + SdfParse parser(&scanner, this); + bool success = (parser.parse() == 0); + stats.report("Read sdf"); return success; } else @@ -164,28 +161,28 @@ SdfReader::setDivider(char divider) void SdfReader::setTimescale(float multiplier, - const char *units) + const string *units) { if (multiplier == 1.0 || multiplier == 10.0 || multiplier == 100.0) { - if (stringEq(units, "us")) + if (*units == "us") timescale_ = multiplier * 1E-6F; - else if (stringEq(units, "ns")) + else if (*units == "ns") timescale_ = multiplier * 1E-9F; - else if (stringEq(units, "ps")) + else if (*units == "ps") timescale_ = multiplier * 1E-12F; else sdfError(180, "TIMESCALE units not us, ns, or ps."); } else sdfError(181, "TIMESCALE multiplier not 1, 10, or 100."); - stringDelete(units); + delete units; } void -SdfReader::interconnect(const char *from_pin_name, - const char *to_pin_name, +SdfReader::interconnect(const string *from_pin_name, + const string *to_pin_name, SdfTripleSeq *triples) { // Ignore non-incremental annotations in incremental only mode. @@ -202,38 +199,41 @@ SdfReader::interconnect(const char *from_pin_name, bool to_is_hier = network_->isHierarchical(to_pin); if (from_is_hier || to_is_hier) { if (from_is_hier) - sdfError(182, "pin %s is a hierarchical pin.", from_pin_name); + sdfError(182, "pin %s is a hierarchical pin.", + from_pin_name->c_str()); if (to_is_hier) - sdfError(183, "pin %s is a hierarchical pin.", to_pin_name); + sdfError(183, "pin %s is a hierarchical pin.", + to_pin_name->c_str()); } else sdfWarn(184, "INTERCONNECT from %s to %s not found.", - from_pin_name, to_pin_name); + from_pin_name->c_str(), + to_pin_name->c_str()); } } else { if (from_pin == nullptr) - sdfWarn(185, "pin %s not found.", from_pin_name); + sdfWarn(185, "pin %s not found.", from_pin_name->c_str()); if (to_pin == nullptr) - sdfWarn(186, "pin %s not found.", to_pin_name); + sdfWarn(186, "pin %s not found.", to_pin_name->c_str()); } } - stringDelete(from_pin_name); - stringDelete(to_pin_name); + delete from_pin_name; + delete to_pin_name; deleteTripleSeq(triples); } void -SdfReader::port(const char *to_pin_name, +SdfReader::port(const string *to_pin_name, SdfTripleSeq *triples) { // Ignore non-incremental annotations in incremental only mode. if (!(is_incremental_only_ && !in_incremental_)) { Pin *to_pin = (instance_) - ? network_->findPinRelative(instance_, to_pin_name) - : network_->findPin(to_pin_name); + ? network_->findPinRelative(instance_, to_pin_name->c_str()) + : network_->findPin(to_pin_name->c_str()); if (to_pin == nullptr) - sdfWarn(187, "pin %s not found.", to_pin_name); + sdfWarn(187, "pin %s not found.", to_pin_name->c_str()); else { Vertex *vertex = graph_->pinLoadVertex(to_pin); VertexInEdgeIterator edge_iter(vertex, graph_); @@ -244,7 +244,7 @@ SdfReader::port(const char *to_pin_name, } } } - stringDelete(to_pin_name); + delete to_pin_name; deleteTripleSeq(triples); } @@ -295,16 +295,16 @@ SdfReader::setEdgeDelays(Edge *edge, } void -SdfReader::setCell(const char *cell_name) +SdfReader::setCell(const string *cell_name) { cell_name_ = cell_name; } void -SdfReader::setInstance(const char *instance_name) +SdfReader::setInstance(const string *instance_name) { if (instance_name) { - if (stringEq(instance_name, "*")) { + if (*instance_name == "*") { notSupported("INSTANCE wildcards"); instance_ = nullptr; } @@ -313,17 +313,17 @@ SdfReader::setInstance(const char *instance_name) if (instance_) { Cell *inst_cell = network_->cell(instance_); const char *inst_cell_name = network_->name(inst_cell); - if (cell_name_ && !stringEqual(inst_cell_name, cell_name_)) + if (cell_name_ && !stringEq(inst_cell_name, cell_name_->c_str())) sdfWarn(190, "instance %s cell %s does not match enclosing cell %s.", - instance_name, + instance_name->c_str(), inst_cell_name, - cell_name_); + cell_name_->c_str()); } } } else instance_ = nullptr; - stringDelete(instance_name); + delete instance_name; } void @@ -336,26 +336,26 @@ SdfReader::setInstanceWildcard() void SdfReader::cellFinish() { - stringDelete(cell_name_); + delete cell_name_; cell_name_ = nullptr; instance_ = nullptr; } void SdfReader::iopath(SdfPortSpec *from_edge, - const char *to_port_name, + const string *to_port_name, SdfTripleSeq *triples, - const char *cond, + const string *cond, bool condelse) { if (instance_) { - const char *from_port_name = from_edge->port(); + const string *from_port_name = from_edge->port(); Cell *cell = network_->cell(instance_); Port *from_port = findPort(cell, from_port_name); Port *to_port = findPort(cell, to_port_name); if (from_port && to_port) { - Pin *from_pin = network_->findPin(instance_, from_port_name); - Pin *to_pin = network_->findPin(instance_, to_port_name); + Pin *from_pin = network_->findPin(instance_, from_port); + Pin *to_pin = network_->findPin(instance_, to_port); // Do not report an error if the pin is not found because the // instance may not have the pin. if (from_pin && to_pin) { @@ -405,27 +405,27 @@ SdfReader::iopath(SdfPortSpec *from_edge, if (!matched) sdfWarn(191, "cell %s IOPATH %s -> %s not found.", network_->cellName(instance_), - from_port_name, - to_port_name); + from_port_name->c_str(), + to_port_name->c_str()); } } } } - stringDelete(to_port_name); - deletePortSpec(from_edge); + delete to_port_name; + delete from_edge; deleteTripleSeq(triples); - stringDelete(cond); + delete cond; } Port * SdfReader::findPort(const Cell *cell, - const char *port_name) + const string *port_name) { - Port *port = network_->findPort(cell, port_name); + Port *port = network_->findPort(cell, port_name->c_str()); if (port == nullptr) sdfWarn(194, "instance %s port %s not found.", network_->pathName(instance_), - port_name); + port_name->c_str()); return port; } @@ -436,16 +436,16 @@ SdfReader::timingCheck(TimingRole *role, SdfTriple *triple) { if (instance_) { - const char *data_port_name = data_edge->port(); - const char *clk_port_name = clk_edge->port(); + const string *data_port_name = data_edge->port(); + const string *clk_port_name = clk_edge->port(); Cell *cell = network_->cell(instance_); Port *data_port = findPort(cell, data_port_name); Port *clk_port = findPort(cell, clk_port_name); if (data_port && clk_port) timingCheck1(role, data_port, data_edge, clk_port, clk_edge, triple); } - deletePortSpec(data_edge); - deletePortSpec(clk_edge); + delete data_edge; + delete clk_edge; deleteTriple(triple); } @@ -514,8 +514,8 @@ SdfReader::annotateCheckEdges(Pin *data_pin, bool match_generic) { bool matched = false; - const char *cond_start = data_edge->cond(); - const char *cond_end = clk_edge->cond(); + const string *cond_start = data_edge->cond(); + const string *cond_end = clk_edge->cond(); // Timing check graph edges from clk to data. Vertex *to_vertex = graph_->pinLoadVertex(data_pin); // Fanin < fanout, so search for driver from load. @@ -556,11 +556,11 @@ SdfReader::timingCheckWidth(SdfPortSpec *edge, // Ignore non-incremental annotations in incremental only mode. if (!(is_incremental_only_ && !in_incremental_) && instance_) { - const char *port_name = edge->port(); + const string *port_name = edge->port(); Cell *cell = network_->cell(instance_); Port *port = findPort(cell, port_name); if (port) { - Pin *pin = network_->findPin(instance_, port_name); + Pin *pin = network_->findPin(instance_, port_name->c_str()); if (pin) { const RiseFall *rf = edge->transition()->asRiseFall(); Edge *edge; @@ -571,7 +571,7 @@ SdfReader::timingCheckWidth(SdfPortSpec *edge, } } } - deletePortSpec(edge); + delete edge; deleteTriple(triple); } @@ -603,8 +603,8 @@ SdfReader::timingCheckSetupHold1(SdfPortSpec *data_edge, TimingRole *setup_role, TimingRole *hold_role) { - const char *data_port_name = data_edge->port(); - const char *clk_port_name = clk_edge->port(); + const string *data_port_name = data_edge->port(); + const string *clk_port_name = clk_edge->port(); Cell *cell = network_->cell(instance_); Port *data_port = findPort(cell, data_port_name); Port *clk_port = findPort(cell, clk_port_name); @@ -612,8 +612,8 @@ SdfReader::timingCheckSetupHold1(SdfPortSpec *data_edge, timingCheck1(setup_role, data_port, data_edge, clk_port, clk_edge, setup_triple); timingCheck1(hold_role, data_port, data_edge, clk_port, clk_edge, hold_triple); } - deletePortSpec(data_edge); - deletePortSpec(clk_edge); + delete data_edge; + delete clk_edge; deleteTriple(setup_triple); deleteTriple(hold_triple); } @@ -625,12 +625,12 @@ SdfReader::timingCheckPeriod(SdfPortSpec *edge, // Ignore non-incremental annotations in incremental only mode. if (!(is_incremental_only_ && !in_incremental_) && instance_) { - const char *port_name = edge->port(); + const string *port_name = edge->port(); Cell *cell = network_->cell(instance_); Port *port = findPort(cell, port_name); if (port) { // Edge specifier is ignored for period checks. - Pin *pin = network_->findPin(instance_, port_name); + Pin *pin = network_->findPin(instance_, port_name->c_str()); if (pin) { float **values = triple->values(); float *value_ptr = values[triple_min_index_]; @@ -648,7 +648,7 @@ SdfReader::timingCheckPeriod(SdfPortSpec *edge, } } } - deletePortSpec(edge); + delete edge; deleteTriple(triple); } @@ -659,8 +659,8 @@ SdfReader::timingCheckNochange(SdfPortSpec *data_edge, SdfTriple *after_triple) { notSupported("NOCHANGE"); - deletePortSpec(data_edge); - deletePortSpec(clk_edge); + delete data_edge; + delete clk_edge; deleteTriple(before_triple); deleteTriple(after_triple); } @@ -682,7 +682,7 @@ SdfReader::device(SdfTripleSeq *triples) } void -SdfReader::device(const char *to_port_name, +SdfReader::device(const string *to_port_name, SdfTripleSeq *triples) { // Ignore non-incremental annotations in incremental only mode. @@ -691,11 +691,11 @@ SdfReader::device(const char *to_port_name, Cell *cell = network_->cell(instance_); Port *to_port = findPort(cell, to_port_name); if (to_port) { - Pin *to_pin = network_->findPin(instance_, to_port_name); + Pin *to_pin = network_->findPin(instance_, to_port_name->c_str()); setDevicePinDelays(to_pin, triples); } } - stringDelete(to_port_name); + delete to_port_name; deleteTripleSeq(triples); } @@ -798,7 +798,7 @@ SdfReader::setEdgeArcDelaysCondUse(Edge *edge, } bool -SdfReader::condMatch(const char *sdf_cond, +SdfReader::condMatch(const string *sdf_cond, const char *lib_cond) { // If the sdf is not conditional it matches any library condition. @@ -806,7 +806,7 @@ SdfReader::condMatch(const char *sdf_cond, return true; else if (sdf_cond && lib_cond) { // Match sdf_cond and lib_cond ignoring blanks. - const char *c1 = sdf_cond; + const char *c1 = sdf_cond->c_str(); const char *c2 = lib_cond; char ch1, ch2; do { @@ -827,44 +827,35 @@ SdfReader::condMatch(const char *sdf_cond, SdfPortSpec * SdfReader::makePortSpec(Transition *tr, - const char *port, - const char *cond) + const string *port, + const string *cond) { - SdfPortSpec *port_spec = new SdfPortSpec(tr, port, cond); - stringDelete(port); - stringDelete(cond); - return port_spec; + return new SdfPortSpec(tr, port, cond); } SdfPortSpec * -SdfReader::makeCondPortSpec(const char *cond_port) +SdfReader::makeCondPortSpec(const string *cond_port) { // Search from end to find port name because condition may contain spaces. - string cond_port1(cond_port); + string cond_port1(*cond_port); trimRight(cond_port1); auto port_idx = cond_port1.find_last_of(" "); if (port_idx != cond_port1.npos) { - string port1 = cond_port1.substr(port_idx + 1); + string *port1 = new string(cond_port1.substr(port_idx + 1)); auto cond_end = cond_port1.find_last_not_of(" ", port_idx); if (cond_end != cond_port1.npos) { - string cond1 = cond_port1.substr(0, cond_end + 1); + string *cond1 = new string(cond_port1.substr(0, cond_end + 1)); SdfPortSpec *port_spec = new SdfPortSpec(Transition::riseFall(), - port1.c_str(), - cond1.c_str()); - stringDelete(cond_port); + port1, + cond1); + delete cond_port; return port_spec; } } - stringDelete(cond_port); + delete cond_port; return nullptr; } -void -SdfReader::deletePortSpec(SdfPortSpec *edge) -{ - delete edge; -} - SdfTripleSeq * SdfReader::makeTripleSeq() { @@ -925,91 +916,70 @@ SdfReader::setInIncremental(bool incr) in_incremental_ = incr; } -const char * -SdfReader::unescaped(const char *token) +string * +SdfReader::unescaped(const string *token) { char path_escape = network_->pathEscape(); char path_divider = network_->pathDivider(); - char *unescaped = new char[strlen(token) + 1]; - char *u = unescaped; - size_t token_length = strlen(token); - + size_t token_length = token->size(); + string *unescaped = new string; for (size_t i = 0; i < token_length; i++) { - char ch = token[i]; + char ch = (*token)[i]; if (ch == escape_) { - char next_ch = token[i + 1]; + char next_ch = (*token)[i + 1]; if (next_ch == divider_) { // Escaped divider. // Translate sdf escape to network escape. - *u++ = path_escape; + *unescaped += path_escape; // Translate sdf divider to network divider. - *u++ = path_divider; + *unescaped += path_divider; } else if (next_ch == '[' || next_ch == ']' || next_ch == escape_) { // Escaped bus bracket or escape. // Translate sdf escape to network escape. - *u++ = path_escape; - *u++ = next_ch; + *unescaped += path_escape; + *unescaped += next_ch; } else // Escaped non-divider character. - *u++ = next_ch; + *unescaped += next_ch; i++; } else // Just the normal noises. - *u++ = ch; + *unescaped += ch; } - *u = '\0'; - debugPrint(debug_, "sdf_name", 1, "token %s -> %s", token, unescaped); - stringDelete(token); + debugPrint(debug_, "sdf_name", 1, "unescape %s -> %s", + token->c_str(), + unescaped->c_str()); + delete token; return unescaped; } -// Translate sdf divider to network divider. -char * -SdfReader::makePath(const char *head, - const char *tail) +string * +SdfReader::makePath(const string *head, + const string *tail) { - char *path = stringPrint("%s%c%s", - head, - network_->pathDivider(), - tail); - sta::stringDelete(head); - sta::stringDelete(tail); + string *path = new string(*head); + *path += network_->pathDivider(); + *path += *tail; + delete head; + delete tail; return path; } -void -SdfReader::incrLine() +string * +SdfReader::makeBusName(string *base_name, + int index) { - line_++; -} - -void -SdfReader::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); -} - -void -SdfReader::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); + string *bus_name = unescaped(base_name); + *bus_name += '['; + *bus_name += to_string(index); + *bus_name += ']'; + delete base_name; + return bus_name; } void @@ -1024,7 +994,7 @@ SdfReader::sdfWarn(int id, { va_list args; va_start(args, fmt); - report_->vfileWarn(id, filename_, line_, fmt, args); + report_->vfileWarn(id, filename_, scanner_->lineno(), fmt, args); va_end(args); } @@ -1034,35 +1004,35 @@ SdfReader::sdfError(int id, { va_list args; va_start(args, fmt); - report_->vfileError(id, filename_, line_, fmt, args); + report_->vfileError(id, filename_, scanner_->lineno(), fmt, args); va_end(args); } Pin * -SdfReader::findPin(const char *name) +SdfReader::findPin(const string *name) { if (path_) { - string path_name = path_; + string path_name(path_); path_name += divider_; - path_name += name; + path_name += *name; Pin *pin = network_->findPin(path_name.c_str()); return pin; } else - return network_->findPin(name); + return network_->findPin(name->c_str()); } Instance * -SdfReader::findInstance(const char *name) +SdfReader::findInstance(const string *name) { string inst_name; if (path_) { inst_name = path_; inst_name += divider_; - inst_name += name; + inst_name += *name; } else - inst_name = name; + inst_name = *name; Instance *inst = network_->findInstance(inst_name.c_str()); if (inst == nullptr) sdfWarn(195, "instance %s not found.", inst_name.c_str()); @@ -1071,19 +1041,19 @@ SdfReader::findInstance(const char *name) //////////////////////////////////////////////////////////////// -SdfPortSpec::SdfPortSpec(Transition *tr, - const char *port, - const char *cond) : +SdfPortSpec::SdfPortSpec(const Transition *tr, + const string *port, + const string *cond) : tr_(tr), - port_(stringCopy(port)), - cond_(stringCopy(cond)) + port_(port), + cond_(cond) { } SdfPortSpec::~SdfPortSpec() { - stringDelete(port_); - stringDelete(cond_); + delete port_; + delete cond_; } //////////////////////////////////////////////////////////////// @@ -1114,16 +1084,32 @@ SdfTriple::hasValue() const return values_[0] || values_[1] || values_[2]; } -} // namespace +//////////////////////////////////////////////////////////////// -// Global namespace - -void sdfFlushBuffer(); - -int -SdfParse_error(const char *msg) +SdfScanner::SdfScanner(std::istream *stream, + const char *filename, + SdfReader *reader, + Report *report) : + yyFlexLexer(stream), + filename_(filename), + reader_(reader), + report_(report) { - sdfFlushBuffer(); - sta::sdf_reader->sdfError(196, "%s.\n", msg); - return 0; } + +void +SdfScanner::error(const char *msg) +{ + report_->fileError(1866, filename_, lineno(), "%s", msg); +} + +//////////////////////////////////////////////////////////////// + +void +SdfParse::error(const location_type &loc, + const string &msg) +{ + reader->report()->fileError(164,reader->filename(),loc.begin.line,"%s",msg.c_str()); +} + +} // namespace diff --git a/sdf/SdfReaderPvt.hh b/sdf/SdfReaderPvt.hh index 437ed212..b70b80e8 100644 --- a/sdf/SdfReaderPvt.hh +++ b/sdf/SdfReaderPvt.hh @@ -24,7 +24,6 @@ #pragma once -#include "Zlib.hh" #include "Vector.hh" #include "TimingRole.hh" #include "Transition.hh" @@ -34,20 +33,12 @@ #include "SdcClass.hh" #include "StaState.hh" -// Header for SdfReader.cc to communicate with SdfLex.cc, SdfParse.cc - -// global namespace - -#define YY_INPUT(buf,result,max_size) \ - sta::sdf_reader->getChars(buf, result, max_size) -int -SdfParse_error(const char *msg); - namespace sta { class Report; class SdfTriple; class SdfPortSpec; +class SdfScanner; typedef Vector SdfTripleSeq; @@ -67,7 +58,8 @@ public: bool read(); void setDivider(char divider); - void setTimescale(float multiplier, const char *units); + void setTimescale(float multiplier, + const string *units); void setPortDeviceDelay(Edge *edge, SdfTripleSeq *triples, bool from_trans); @@ -88,17 +80,17 @@ public: int triple_index, int arc_delay_index, const MinMax *min_max); - void setInstance(const char *instance_name); + void setInstance(const string *instance_name); void setInstanceWildcard(); void cellFinish(); - void setCell(const char *cell_name); - void interconnect(const char *from_pin_name, - const char *to_pin_name, + void setCell(const string *cell_name); + void interconnect(const string *from_pin_name, + const string *to_pin_name, SdfTripleSeq *triples); void iopath(SdfPortSpec *from_edge, - const char *to_port_name, + const string *to_port_name, SdfTripleSeq *triples, - const char *cond, + const string *cond, bool condelse); void timingCheck(TimingRole *role, SdfPortSpec *data_edge, @@ -126,10 +118,10 @@ public: SdfPortSpec *clk_edge, SdfTriple *before_triple, SdfTriple *after_triple); - void port(const char *to_pin_name, + void port(const string *to_pin_name, SdfTripleSeq *triples); void device(SdfTripleSeq *triples); - void device(const char *to_pin_name, + void device(const string *to_pin_name, SdfTripleSeq *triples); SdfTriple *makeTriple(); @@ -141,29 +133,20 @@ public: SdfTripleSeq *makeTripleSeq(); void deleteTripleSeq(SdfTripleSeq *triples); SdfPortSpec *makePortSpec(Transition *tr, - const char *port, - const char *cond); - SdfPortSpec *makeCondPortSpec(const char *cond_port); - const char *unescaped(const char *token); - char *makePath(const char *head, - const char *tail); + const string *port, + const string *cond); + SdfPortSpec *makeCondPortSpec(const string *cond_port); + string *unescaped(const string *token); + string *makePath(const string *head, + const string *tail); // Parser state used to control lexer for COND handling. bool inTimingCheck() { return in_timing_check_; } void setInTimingCheck(bool in); bool inIncremental() const { return in_incremental_; } void setInIncremental(bool incr); - - // 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(); + string *makeBusName(string *bus_name, + int index); const char *filename() { return filename_; } - int line() { return line_; } void sdfWarn(int id, const char *fmt, ...); void sdfError(int id, @@ -178,11 +161,11 @@ private: Edge *findCheckEdge(Pin *from_pin, Pin *to_pin, TimingRole *sdf_role, - const char *cond_start, - const char *cond_end); + const string *cond_start, + const string *cond_end); Edge *findWireEdge(Pin *from_pin, Pin *to_pin); - bool condMatch(const char *sdf_cond, + bool condMatch(const string *sdf_cond, const char *lib_cond); void timingCheck1(TimingRole *role, Port *data_port, @@ -197,18 +180,18 @@ private: TimingRole *sdf_role, SdfTriple *triple, bool match_generic); - void deletePortSpec(SdfPortSpec *edge); - Pin *findPin(const char *name); - Instance *findInstance(const char *name); + Pin *findPin(const string *name); + Instance *findInstance(const string *name); void setEdgeDelays(Edge *edge, SdfTripleSeq *triples, const char *sdf_cmd); void setDevicePinDelays(Pin *to_pin, SdfTripleSeq *triples); Port *findPort(const Cell *cell, - const char *port_name); + const string *port_name); const char *filename_; + SdfScanner *scanner_; const char *path_; // Which values to pull out of the sdf triples. int triple_min_index_; @@ -221,12 +204,10 @@ private: bool is_incremental_only_; MinMaxAll *cond_use_; - int line_; - gzFile stream_; char divider_; char escape_; Instance *instance_; - const char *cell_name_; + const string *cell_name_; bool in_timing_check_; bool in_incremental_; float timescale_; @@ -234,6 +215,4 @@ private: static const int null_index_ = -1; }; -extern SdfReader *sdf_reader; - } // namespace diff --git a/sdf/SdfScanner.hh b/sdf/SdfScanner.hh new file mode 100644 index 00000000..a4e117f0 --- /dev/null +++ b/sdf/SdfScanner.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 + +#ifndef __FLEX_LEXER_H +#undef yyFlexLexer +#define yyFlexLexer SdfFlexLexer +#include +#endif + +#include "location.hh" +#include "SdfParse.hh" + +namespace sta { + +class Report; + +class SdfScanner : public SdfFlexLexer +{ +public: + SdfScanner(std::istream *stream, + const char *filename, + SdfReader *reader, + Report *report); + virtual ~SdfScanner() {} + + virtual int lex(SdfParse::semantic_type *const yylval, + SdfParse::location_type *yylloc); + // YY_DECL defined in SdfLex.ll + // Method body created by flex in SdfLex.cc + + void error(const char *msg); + + // Get rid of override virtual function warning. + using FlexLexer::yylex; + +private: + string token_; + const char *filename_; + SdfReader *reader_; + Report *report_; +}; + +} // namespace