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