read_saif
commit bd5c1fc5a8e933ff63728f890bc7e03bf1155328
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Sep 23 18:02:40 2024 -0700
read_saif doc, rename read_power_activities to read_vcd
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 16a18595b13e9f72ea2a4fc6bca84b21ab98757f
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Sep 23 17:37:05 2024 -0700
saif parser
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 18f2448fb5fa8e83ee93fc9a3d15f4fe055d3a66
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Sep 23 16:11:47 2024 -0700
read saif basically matches vcd
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit a31be85f7557f847134e5bf47ead0ff78ce8c407
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Sep 22 20:15:00 2024 -0700
saif light
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 2aef1731f20421caf762c2908bef62279d3564b7
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Sep 22 18:36:17 2024 -0700
saif reader
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit a7933ec57bc023893240b59fe1637cf33a2a95cd
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Sep 22 15:24:00 2024 -0700
saif parser success
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 6deab8231345c6e28b3bc891dc56c82cdfe18ff0
Author: James Cherry <cherry@parallaxsw.com>
Date: Sat Sep 21 20:13:05 2024 -0700
saif reader
Signed-off-by: James Cherry <cherry@parallaxsw.com>
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
7de907223b
commit
64f3c0d758
|
|
@ -200,6 +200,7 @@ set(STA_SOURCE
|
||||||
|
|
||||||
power/Power.cc
|
power/Power.cc
|
||||||
power/ReadVcdActivities.cc
|
power/ReadVcdActivities.cc
|
||||||
|
power/SaifReader.cc
|
||||||
power/Vcd.cc
|
power/Vcd.cc
|
||||||
power/VcdReader.cc
|
power/VcdReader.cc
|
||||||
|
|
||||||
|
|
@ -308,6 +309,15 @@ bison_target(SdfParser ${STA_HOME}/sdf/SdfParse.yy ${CMAKE_CURRENT_BINARY_DIR}/S
|
||||||
add_flex_bison_dependency(SdfLex SdfParser)
|
add_flex_bison_dependency(SdfLex SdfParser)
|
||||||
|
|
||||||
|
|
||||||
|
# Saif scan/parse.
|
||||||
|
flex_target(SaifLex ${STA_HOME}/power/SaifLex.ll ${CMAKE_CURRENT_BINARY_DIR}/SaifLex.cc
|
||||||
|
COMPILE_FLAGS --prefix=SaifLex_
|
||||||
|
)
|
||||||
|
bison_target(SaifParser ${STA_HOME}/power/SaifParse.yy ${CMAKE_CURRENT_BINARY_DIR}/SaifParse.cc
|
||||||
|
COMPILE_FLAGS --name-prefix=SaifParse_
|
||||||
|
)
|
||||||
|
add_flex_bison_dependency(SaifLex SaifParser)
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
set(STA_TCL_INIT ${CMAKE_CURRENT_BINARY_DIR}/StaTclInitVar.cc)
|
set(STA_TCL_INIT ${CMAKE_CURRENT_BINARY_DIR}/StaTclInitVar.cc)
|
||||||
|
|
@ -513,6 +523,9 @@ target_sources(OpenSTA
|
||||||
|
|
||||||
${FLEX_VerilogLex_OUTPUTS}
|
${FLEX_VerilogLex_OUTPUTS}
|
||||||
${BISON_VerilogParser_OUTPUTS}
|
${BISON_VerilogParser_OUTPUTS}
|
||||||
|
|
||||||
|
${FLEX_SaifLex_OUTPUTS}
|
||||||
|
${BISON_SaifParser_OUTPUTS}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(OpenSTA
|
target_link_libraries(OpenSTA
|
||||||
|
|
|
||||||
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
|
@ -8,5 +8,5 @@ read_spef gcd_sky130hd.spef
|
||||||
# Generate vcd file
|
# Generate vcd file
|
||||||
# iverilog -o gcd_tb gcd_tb.v
|
# iverilog -o gcd_tb gcd_tb.v
|
||||||
# vvp gcd_tb
|
# vvp gcd_tb
|
||||||
read_power_activities -scope gcd_tb/gcd1 -vcd gcd_sky130hd.vcd
|
read_vcd -scope gcd_tb/gcd1 gcd_sky130hd.vcd
|
||||||
report_power
|
report_power
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ enum class PwrActivityOrigin
|
||||||
input,
|
input,
|
||||||
user,
|
user,
|
||||||
vcd,
|
vcd,
|
||||||
|
saif,
|
||||||
propagated,
|
propagated,
|
||||||
clock,
|
clock,
|
||||||
constant,
|
constant,
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ static EnumNameMap<PwrActivityOrigin> pwr_activity_origin_map =
|
||||||
{PwrActivityOrigin::input, "input"},
|
{PwrActivityOrigin::input, "input"},
|
||||||
{PwrActivityOrigin::user, "user"},
|
{PwrActivityOrigin::user, "user"},
|
||||||
{PwrActivityOrigin::vcd, "vcd"},
|
{PwrActivityOrigin::vcd, "vcd"},
|
||||||
|
{PwrActivityOrigin::saif, "saif"},
|
||||||
{PwrActivityOrigin::propagated, "propagated"},
|
{PwrActivityOrigin::propagated, "propagated"},
|
||||||
{PwrActivityOrigin::clock, "clock"},
|
{PwrActivityOrigin::clock, "clock"},
|
||||||
{PwrActivityOrigin::constant, "constant"},
|
{PwrActivityOrigin::constant, "constant"},
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
#include "power/Power.hh"
|
#include "power/Power.hh"
|
||||||
#include "power/VcdReader.hh"
|
#include "power/VcdReader.hh"
|
||||||
#include "power/ReadVcdActivities.hh"
|
#include "power/ReadVcdActivities.hh"
|
||||||
|
#include "power/SaifReader.hh"
|
||||||
|
|
||||||
using namespace sta;
|
using namespace sta;
|
||||||
|
|
||||||
|
|
@ -103,8 +104,10 @@ set_power_pin_activity(const Pin *pin,
|
||||||
return power->setUserActivity(pin, activity, duty, PwrActivityOrigin::user);
|
return power->setUserActivity(pin, activity, duty, PwrActivityOrigin::user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
void
|
||||||
read_vcd_activities(const char *filename,
|
read_vcd_file(const char *filename,
|
||||||
const char *scope)
|
const char *scope)
|
||||||
{
|
{
|
||||||
Sta *sta = Sta::sta();
|
Sta *sta = Sta::sta();
|
||||||
|
|
@ -128,4 +131,15 @@ report_vcd_var_values(const char *filename,
|
||||||
reportVcdVarValues(filename, var_name, sta);
|
reportVcdVarValues(filename, var_name, sta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool
|
||||||
|
read_saif_file(const char *filename,
|
||||||
|
const char *scope)
|
||||||
|
{
|
||||||
|
Sta *sta = Sta::sta();
|
||||||
|
cmdLinkedNetwork();
|
||||||
|
return readSaif(filename, scope, sta);
|
||||||
|
}
|
||||||
|
|
||||||
%} // inline
|
%} // inline
|
||||||
|
|
|
||||||
|
|
@ -283,7 +283,41 @@ proc read_power_activities { args } {
|
||||||
if { [info exists keys(-scope)] } {
|
if { [info exists keys(-scope)] } {
|
||||||
set scope $keys(-scope)
|
set scope $keys(-scope)
|
||||||
}
|
}
|
||||||
read_vcd_activities $filename $scope
|
sta_warn 304 "read_power_activities is deprecated. Use read_vcd."
|
||||||
|
read_vcd_file $filename $scope
|
||||||
|
}
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
define_cmd_args "read_vcd" { [-scope scope] filename }
|
||||||
|
|
||||||
|
proc read_vcd { args } {
|
||||||
|
parse_key_args "read_vcd" args \
|
||||||
|
keys {-scope} flags {}
|
||||||
|
|
||||||
|
check_argc_eq1 "read_vcd" $args
|
||||||
|
set filename [file nativename [lindex $args 0]]
|
||||||
|
set scope ""
|
||||||
|
if { [info exists keys(-scope)] } {
|
||||||
|
set scope $keys(-scope)
|
||||||
|
}
|
||||||
|
read_vcd_file $filename $scope
|
||||||
|
}
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
define_cmd_args "read_saif" { [-scope scope] filename }
|
||||||
|
|
||||||
|
proc read_saif { args } {
|
||||||
|
parse_key_args "read_saif" args keys {-scope} flags {}
|
||||||
|
|
||||||
|
check_argc_eq1 "read_saif" $args
|
||||||
|
set filename [file nativename [lindex $args 0]]
|
||||||
|
set scope ""
|
||||||
|
if { [info exists keys(-scope)] } {
|
||||||
|
set scope $keys(-scope)
|
||||||
|
}
|
||||||
|
read_saif_file $filename $scope
|
||||||
}
|
}
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#include "ReadVcdActivities.hh"
|
#include "ReadVcdActivities.hh"
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "VcdReader.hh"
|
#include "VcdReader.hh"
|
||||||
#include "Debug.hh"
|
#include "Debug.hh"
|
||||||
|
|
@ -33,8 +34,6 @@ using std::abs;
|
||||||
using std::min;
|
using std::min;
|
||||||
using std::to_string;
|
using std::to_string;
|
||||||
|
|
||||||
typedef Set<const Pin*> ConstPinSet;
|
|
||||||
|
|
||||||
class ReadVcdActivities : public StaState
|
class ReadVcdActivities : public StaState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -66,7 +65,7 @@ private:
|
||||||
double clk_period_;
|
double clk_period_;
|
||||||
Sta *sta_;
|
Sta *sta_;
|
||||||
Power *power_;
|
Power *power_;
|
||||||
ConstPinSet annotated_pins_;
|
std::set<const Pin*> annotated_pins_;
|
||||||
|
|
||||||
static constexpr double sim_clk_period_tolerance_ = .1;
|
static constexpr double sim_clk_period_tolerance_ = .1;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
%{
|
||||||
|
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2024, 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/>.
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "util/FlexDisableRegister.hh"
|
||||||
|
#include "StringUtil.hh"
|
||||||
|
#include "power/SaifReaderPvt.hh"
|
||||||
|
#include "SaifParse.hh"
|
||||||
|
|
||||||
|
#define YY_NO_INPUT
|
||||||
|
|
||||||
|
static std::string saif_token;
|
||||||
|
|
||||||
|
void
|
||||||
|
saifFlushBuffer()
|
||||||
|
{
|
||||||
|
YY_FLUSH_BUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
/* %option debug */
|
||||||
|
%option noyywrap
|
||||||
|
%option nounput
|
||||||
|
%option never-interactive
|
||||||
|
|
||||||
|
%x COMMENT
|
||||||
|
%x QUOTE
|
||||||
|
%x COND_EXPR
|
||||||
|
|
||||||
|
ID ([A-Za-z_])([A-Za-z0-9_$\[\]\\.])*
|
||||||
|
HCHAR "."|"/"
|
||||||
|
BLANK [ \n\t\r\b]
|
||||||
|
EOL \r?\n
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
"/*" { BEGIN COMMENT; }
|
||||||
|
<COMMENT>{
|
||||||
|
|
||||||
|
"*/" { BEGIN INITIAL; }
|
||||||
|
|
||||||
|
.
|
||||||
|
{EOL} { sta::saif_reader->incrLine(); }
|
||||||
|
|
||||||
|
<<EOF>> {
|
||||||
|
SaifParse_error("unterminated comment");
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
yyterminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"\"" { BEGIN QUOTE; saif_token.erase(); }
|
||||||
|
<QUOTE>{
|
||||||
|
|
||||||
|
"\\". { saif_token += yytext[1]; }
|
||||||
|
|
||||||
|
"\"" {
|
||||||
|
BEGIN INITIAL;
|
||||||
|
SaifParse_lval.string = sta::stringCopy(saif_token.c_str());
|
||||||
|
return QSTRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
. { saif_token += yytext[0]; }
|
||||||
|
|
||||||
|
<<EOF>> {
|
||||||
|
SaifParse_error("unterminated quoted string");
|
||||||
|
BEGIN(INITIAL);
|
||||||
|
yyterminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"//"[^\n]*{EOL} { sta::saif_reader->incrLine(); }
|
||||||
|
|
||||||
|
[0-9]+ {
|
||||||
|
SaifParse_lval.uint = atoll(yytext);
|
||||||
|
return UINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
":"|"{"|"}"|"["|"]"|","|"*"|";"|"="|"-"|"+"|"|"|"("|")"|{HCHAR} {
|
||||||
|
return ((int) yytext[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
SAIFILE { return SAIFILE; }
|
||||||
|
SAIFVERSION { return SAIFVERSION; }
|
||||||
|
DIRECTION { return DIRECTION; }
|
||||||
|
DESIGN { return DESIGN; }
|
||||||
|
DATE { return DATE; }
|
||||||
|
VENDOR { return VENDOR; }
|
||||||
|
PROGRAM_NAME { return PROGRAM_NAME; }
|
||||||
|
VERSION { return VERSION; }
|
||||||
|
DIVIDER { return DIVIDER; }
|
||||||
|
TIMESCALE { return TIMESCALE; }
|
||||||
|
DURATION { return DURATION; }
|
||||||
|
INSTANCE { return INSTANCE; }
|
||||||
|
NET { return NET; }
|
||||||
|
PORT { return PORT; }
|
||||||
|
T0 { return T0; }
|
||||||
|
T1 { return T1; }
|
||||||
|
TX { return TX; }
|
||||||
|
TZ { return TZ; }
|
||||||
|
TB { return TB; }
|
||||||
|
TC { return TC; }
|
||||||
|
IG { return IG; }
|
||||||
|
|
||||||
|
{ID} {
|
||||||
|
SaifParse_lval.string = sta::stringCopy(yytext);
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
{EOL} { sta::saif_reader->incrLine(); }
|
||||||
|
|
||||||
|
{BLANK} { /* Ignore blanks. */ }
|
||||||
|
|
||||||
|
/* Send out of bound characters to parser. */
|
||||||
|
. { return ((int) yytext[0]); }
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
@ -0,0 +1,159 @@
|
||||||
|
%{
|
||||||
|
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2024, 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/>.
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
#include "StringUtil.hh"
|
||||||
|
#include "power/SaifReaderPvt.hh"
|
||||||
|
|
||||||
|
int SaifLex_lex();
|
||||||
|
#define SaifParse_lex SaifLex_lex
|
||||||
|
// use yacc generated parser errors
|
||||||
|
#define YYERROR_VERBOSE
|
||||||
|
|
||||||
|
#define YYDEBUG 1
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
// expected shift/reduce conflicts
|
||||||
|
%expect 2
|
||||||
|
|
||||||
|
%union {
|
||||||
|
char character;
|
||||||
|
const char *string;
|
||||||
|
uint64_t uint;
|
||||||
|
sta::SaifState state;
|
||||||
|
sta::SaifStateDurations state_durations;
|
||||||
|
}
|
||||||
|
|
||||||
|
%token SAIFILE SAIFVERSION DIRECTION DESIGN DATE VENDOR PROGRAM_NAME VERSION
|
||||||
|
%token DIVIDER TIMESCALE DURATION
|
||||||
|
%token INSTANCE NET PORT
|
||||||
|
%token T0 T1 TX TZ TB TC IG
|
||||||
|
%token QSTRING ID FNUMBER DNUMBER UINT
|
||||||
|
|
||||||
|
%type <uint> UINT
|
||||||
|
%type <string> QSTRING ID
|
||||||
|
%type <character> hchar
|
||||||
|
%type <state> state
|
||||||
|
%type <state_durations> state_durations
|
||||||
|
|
||||||
|
%start file
|
||||||
|
|
||||||
|
%{
|
||||||
|
%}
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
file:
|
||||||
|
'(' SAIFILE header instance ')' {}
|
||||||
|
;
|
||||||
|
|
||||||
|
header:
|
||||||
|
header_stmt
|
||||||
|
| header header_stmt
|
||||||
|
;
|
||||||
|
|
||||||
|
header_stmt:
|
||||||
|
'(' SAIFVERSION QSTRING ')' { sta::stringDelete($3); }
|
||||||
|
| '(' DIRECTION QSTRING ')' { sta::stringDelete($3); }
|
||||||
|
| '(' DESIGN QSTRING ')' { sta::stringDelete($3); }
|
||||||
|
| '(' DESIGN ')' { }
|
||||||
|
| '(' DATE QSTRING ')' { sta::stringDelete($3); }
|
||||||
|
| '(' VENDOR QSTRING ')' { sta::stringDelete($3); }
|
||||||
|
| '(' PROGRAM_NAME QSTRING ')' { sta::stringDelete($3); }
|
||||||
|
| '(' VERSION QSTRING ')' { sta::stringDelete($3); }
|
||||||
|
| '(' DIVIDER hchar ')' { sta::saif_reader->setDivider($3); }
|
||||||
|
| '(' TIMESCALE UINT ID ')' { sta::saif_reader->setTimescale($3, $4); }
|
||||||
|
| '(' DURATION UINT ')' { sta::saif_reader->setDuration($3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
hchar:
|
||||||
|
'/'
|
||||||
|
{ $$ = '/'; }
|
||||||
|
| '.'
|
||||||
|
{ $$ = '.'; }
|
||||||
|
;
|
||||||
|
|
||||||
|
instance:
|
||||||
|
'(' INSTANCE ID
|
||||||
|
{ sta::saif_reader->instancePush($3); }
|
||||||
|
instance_contents ')'
|
||||||
|
{ sta::saif_reader->instancePop(); }
|
||||||
|
| '(' INSTANCE QSTRING ID
|
||||||
|
{ sta::saif_reader->instancePush($3); }
|
||||||
|
instance_contents ')'
|
||||||
|
{ sta::saif_reader->instancePop(); }
|
||||||
|
;
|
||||||
|
|
||||||
|
instance_contents:
|
||||||
|
/* empty */
|
||||||
|
| instance_content
|
||||||
|
| instance_contents instance_content
|
||||||
|
;
|
||||||
|
|
||||||
|
instance_content:
|
||||||
|
'(' PORT ports ')'
|
||||||
|
| '(' NET nets ')'
|
||||||
|
| instance
|
||||||
|
;
|
||||||
|
|
||||||
|
nets:
|
||||||
|
net
|
||||||
|
| nets net
|
||||||
|
;
|
||||||
|
|
||||||
|
net:
|
||||||
|
'(' ID state_durations ')'
|
||||||
|
{ sta::saif_reader->setNetDurations($2, $3); }
|
||||||
|
;
|
||||||
|
|
||||||
|
ports:
|
||||||
|
port
|
||||||
|
| ports port
|
||||||
|
;
|
||||||
|
|
||||||
|
port:
|
||||||
|
'(' ID state_durations ')'
|
||||||
|
;
|
||||||
|
|
||||||
|
state_durations:
|
||||||
|
'(' state UINT ')'
|
||||||
|
{ $$[static_cast<int>($2)] = $3; }
|
||||||
|
| state_durations '(' state UINT ')'
|
||||||
|
{ $$[static_cast<int>($3)] = $4; }
|
||||||
|
;
|
||||||
|
|
||||||
|
state:
|
||||||
|
T0
|
||||||
|
{ $$ = sta::SaifState::T0; }
|
||||||
|
| T1
|
||||||
|
{ $$ = sta::SaifState::T1; }
|
||||||
|
| TX
|
||||||
|
{ $$ = sta::SaifState::TX; }
|
||||||
|
| TZ
|
||||||
|
{ $$ = sta::SaifState::TZ; }
|
||||||
|
| TB
|
||||||
|
{ $$ = sta::SaifState::TB; }
|
||||||
|
| TC
|
||||||
|
{ $$ = sta::SaifState::TC; }
|
||||||
|
| IG
|
||||||
|
{ $$ = sta::SaifState::IG; }
|
||||||
|
;
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
@ -0,0 +1,290 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2024, 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/>.
|
||||||
|
|
||||||
|
#include "power/SaifReader.hh"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "Error.hh"
|
||||||
|
#include "Debug.hh"
|
||||||
|
#include "Report.hh"
|
||||||
|
#include "Network.hh"
|
||||||
|
#include "Sdc.hh"
|
||||||
|
#include "Power.hh"
|
||||||
|
#include "power/SaifReaderPvt.hh"
|
||||||
|
#include "Sta.hh"
|
||||||
|
|
||||||
|
extern int
|
||||||
|
SaifParse_parse();
|
||||||
|
extern int SaifParse_debug;
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
using std::min;
|
||||||
|
|
||||||
|
SaifReader *saif_reader = nullptr;
|
||||||
|
|
||||||
|
bool
|
||||||
|
readSaif(const char *filename,
|
||||||
|
const char *scope,
|
||||||
|
Sta *sta)
|
||||||
|
{
|
||||||
|
SaifReader reader(filename, scope, sta);
|
||||||
|
saif_reader = &reader;
|
||||||
|
bool success = reader.read();
|
||||||
|
saif_reader = nullptr;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
SaifReader::SaifReader(const char *filename,
|
||||||
|
const char *scope,
|
||||||
|
Sta *sta) :
|
||||||
|
StaState(sta),
|
||||||
|
filename_(filename),
|
||||||
|
scope_(scope),
|
||||||
|
stream_(nullptr),
|
||||||
|
line_(1),
|
||||||
|
divider_('/'),
|
||||||
|
escape_('\\'),
|
||||||
|
timescale_(1.0E-9F), // default units of ns
|
||||||
|
duration_(0.0),
|
||||||
|
clk_period_(0.0),
|
||||||
|
in_scope_level_(0),
|
||||||
|
power_(sta->power())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SaifReader::~SaifReader()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SaifReader::read()
|
||||||
|
{
|
||||||
|
// Use zlib to uncompress gzip'd files automagically.
|
||||||
|
stream_ = gzopen(filename_, "rb");
|
||||||
|
if (stream_) {
|
||||||
|
clk_period_ = INF;
|
||||||
|
for (Clock *clk : *sdc_->clocks())
|
||||||
|
clk_period_ = min(static_cast<double>(clk->period()), clk_period_);
|
||||||
|
|
||||||
|
saif_scope_.clear();
|
||||||
|
in_scope_level_ = 0;
|
||||||
|
annotated_pins_.clear();
|
||||||
|
//::SaifParse_debug = 1;
|
||||||
|
// yyparse returns 0 on success.
|
||||||
|
bool success = (::SaifParse_parse() == 0);
|
||||||
|
gzclose(stream_);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw FileNotReadable(filename_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SaifReader::setDivider(char divider)
|
||||||
|
{
|
||||||
|
divider_ = divider;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SaifReader::setTimescale(uint64_t multiplier,
|
||||||
|
const char *units)
|
||||||
|
{
|
||||||
|
if (multiplier == 1
|
||||||
|
|| multiplier == 10
|
||||||
|
|| multiplier == 100) {
|
||||||
|
if (stringEq(units, "us"))
|
||||||
|
timescale_ = multiplier * 1E-6;
|
||||||
|
else if (stringEq(units, "ns"))
|
||||||
|
timescale_ = multiplier * 1E-9;
|
||||||
|
else if (stringEq(units, "ps"))
|
||||||
|
timescale_ = multiplier * 1E-12;
|
||||||
|
else if (stringEq(units, "fs"))
|
||||||
|
timescale_ = multiplier * 1E-15;
|
||||||
|
else
|
||||||
|
saifError(180, "TIMESCALE units not us, ns, or ps.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
saifError(181, "TIMESCALE multiplier not 1, 10, or 100.");
|
||||||
|
stringDelete(units);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SaifReader::setDuration(uint64_t duration)
|
||||||
|
{
|
||||||
|
duration_ = duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SaifReader::instancePush(const char *instance_name)
|
||||||
|
{
|
||||||
|
if (in_scope_level_ == 0) {
|
||||||
|
// Check for a match to the annotation scope.
|
||||||
|
saif_scope_.push_back(instance_name);
|
||||||
|
|
||||||
|
string saif_scope;
|
||||||
|
bool first = true;
|
||||||
|
for (string &inst : saif_scope_) {
|
||||||
|
if (!first)
|
||||||
|
saif_scope += network_->pathDivider();
|
||||||
|
saif_scope += inst;
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
if (stringEq(saif_scope.c_str(), scope_))
|
||||||
|
in_scope_level_ = saif_scope_.size();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Inside annotation scope.
|
||||||
|
Instance *parent = path_.empty() ? network_->topInstance() : path_.back();
|
||||||
|
Instance *child = network_->findChild(parent, instance_name);
|
||||||
|
path_.push_back(child);
|
||||||
|
}
|
||||||
|
stringDelete(instance_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SaifReader::instancePop()
|
||||||
|
{
|
||||||
|
if (in_scope_level_ == 0)
|
||||||
|
saif_scope_.pop_back();
|
||||||
|
if (!path_.empty())
|
||||||
|
path_.pop_back();
|
||||||
|
if (saif_scope_.size() < in_scope_level_)
|
||||||
|
in_scope_level_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SaifReader::setNetDurations(const char *net_name,
|
||||||
|
SaifStateDurations &durations)
|
||||||
|
{
|
||||||
|
if (in_scope_level_ > 0) {
|
||||||
|
Instance *parent = path_.empty() ? network_->topInstance() : path_.back();
|
||||||
|
if (parent) {
|
||||||
|
const char *net_name1 = unescaped(net_name);
|
||||||
|
const Pin *pin = sdc_network_->findPin(parent, net_name1);
|
||||||
|
if (pin) {
|
||||||
|
double t1 = durations[static_cast<int>(SaifState::T1)];
|
||||||
|
float duty = t1 / duration_;
|
||||||
|
double tc = durations[static_cast<int>(SaifState::TC)];
|
||||||
|
float activity = tc / (duration_ * timescale_ / clk_period_);
|
||||||
|
debugPrint(debug_, "read_saif", 2,
|
||||||
|
"%s duty %.0f / %llu = %.2f tc %.0f activity %.2f",
|
||||||
|
sdc_network_->pathName(pin),
|
||||||
|
t1,
|
||||||
|
duration_,
|
||||||
|
duty,
|
||||||
|
tc,
|
||||||
|
activity);
|
||||||
|
power_->setUserActivity(pin, activity, duty, PwrActivityOrigin::saif);
|
||||||
|
annotated_pins_.insert(pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
SaifReader::unescaped(const char *token)
|
||||||
|
{
|
||||||
|
char *unescaped = new char[strlen(token) + 1];
|
||||||
|
char *u = unescaped;
|
||||||
|
size_t token_length = strlen(token);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < token_length; i++) {
|
||||||
|
char ch = token[i];
|
||||||
|
if (ch == escape_) {
|
||||||
|
char next_ch = token[i + 1];
|
||||||
|
*u++ = next_ch;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// Just the normal noises.
|
||||||
|
*u++ = ch;
|
||||||
|
}
|
||||||
|
*u = '\0';
|
||||||
|
debugPrint(debug_, "saif_name", 1, "token %s -> %s", token, unescaped);
|
||||||
|
return unescaped;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SaifReader::incrLine()
|
||||||
|
{
|
||||||
|
line_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SaifReader::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
|
||||||
|
SaifReader::getChars(char *buf,
|
||||||
|
int &result,
|
||||||
|
size_t max_size)
|
||||||
|
{
|
||||||
|
char *status = gzgets(stream_, buf, max_size);
|
||||||
|
if (status == Z_NULL)
|
||||||
|
result = 0; // YY_nullptr
|
||||||
|
else
|
||||||
|
result = strlen(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SaifReader::notSupported(const char *feature)
|
||||||
|
{
|
||||||
|
saifError(193, "%s not supported.", feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SaifReader::saifWarn(int id,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
report_->vfileWarn(id, filename_, line_, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SaifReader::saifError(int id,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
report_->vfileError(id, filename_, line_, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// Global namespace
|
||||||
|
|
||||||
|
void saifFlushBuffer();
|
||||||
|
|
||||||
|
int
|
||||||
|
SaifParse_error(const char *msg)
|
||||||
|
{
|
||||||
|
saifFlushBuffer();
|
||||||
|
sta::saif_reader->saifError(196, "%s.\n", msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2024, 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/>.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
class Sta;
|
||||||
|
|
||||||
|
bool
|
||||||
|
readSaif(const char *filename,
|
||||||
|
const char *scope,
|
||||||
|
Sta *sta);
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2024, 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/>.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include "Zlib.hh"
|
||||||
|
#include "NetworkClass.hh"
|
||||||
|
#include "StaState.hh"
|
||||||
|
|
||||||
|
// Header for SaifReader.cc to communicate with SaifLex.cc, SaifParse.cc
|
||||||
|
|
||||||
|
// global namespace
|
||||||
|
|
||||||
|
#define YY_INPUT(buf,result,max_size) \
|
||||||
|
sta::saif_reader->getChars(buf, result, max_size)
|
||||||
|
int
|
||||||
|
SaifParse_error(const char *msg);
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
class Sta;
|
||||||
|
class Power;
|
||||||
|
|
||||||
|
using std::vector;
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
enum class SaifState { T0, T1, TX, TZ, TB, TC, IG };
|
||||||
|
|
||||||
|
typedef std::array<uint64_t, static_cast<int>(SaifState::IG)+1> SaifStateDurations;
|
||||||
|
|
||||||
|
class SaifReader : public StaState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SaifReader(const char *filename,
|
||||||
|
const char *scope,
|
||||||
|
Sta *sta);
|
||||||
|
~SaifReader();
|
||||||
|
bool read();
|
||||||
|
|
||||||
|
void setDivider(char divider);
|
||||||
|
void setTimescale(uint64_t multiplier,
|
||||||
|
const char *units);
|
||||||
|
void setDuration(uint64_t duration);
|
||||||
|
void instancePush(const char *instance_name);
|
||||||
|
void instancePop();
|
||||||
|
void setNetDurations(const char *net_name,
|
||||||
|
SaifStateDurations &durations);
|
||||||
|
|
||||||
|
// flex YY_INPUT yy_n_chars arg changed definition from int to size_t,
|
||||||
|
// so provide both forms.
|
||||||
|
void getChars(char *buf,
|
||||||
|
size_t &result,
|
||||||
|
size_t max_size);
|
||||||
|
void getChars(char *buf,
|
||||||
|
int &result,
|
||||||
|
size_t max_size);
|
||||||
|
void incrLine();
|
||||||
|
const char *filename() { return filename_; }
|
||||||
|
int line() { return line_; }
|
||||||
|
void saifWarn(int id,
|
||||||
|
const char *fmt, ...);
|
||||||
|
void saifError(int id,
|
||||||
|
const char *fmt,
|
||||||
|
...);
|
||||||
|
void notSupported(const char *feature);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char *unescaped(const char *token);
|
||||||
|
|
||||||
|
const char *filename_;
|
||||||
|
const char *scope_; // Divider delimited scope to begin annotation.
|
||||||
|
|
||||||
|
gzFile stream_;
|
||||||
|
int line_;
|
||||||
|
char divider_;
|
||||||
|
char escape_;
|
||||||
|
double timescale_;
|
||||||
|
int64_t duration_;
|
||||||
|
double clk_period_;
|
||||||
|
|
||||||
|
vector<string> saif_scope_; // Scope during parsing.
|
||||||
|
size_t in_scope_level_;
|
||||||
|
vector<Instance*> path_; // Path within scope.
|
||||||
|
std::set<const Pin*> annotated_pins_;
|
||||||
|
Power *power_;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern SaifReader *saif_reader;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
@ -16,14 +16,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SdcClass.hh"
|
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
class Report;
|
class MinMaxAll;
|
||||||
class MinMax;
|
|
||||||
class Network;
|
|
||||||
class Graph;
|
|
||||||
class Corner;
|
class Corner;
|
||||||
class StaState;
|
class StaState;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
#include "SdcClass.hh"
|
#include "SdcClass.hh"
|
||||||
#include "StaState.hh"
|
#include "StaState.hh"
|
||||||
|
|
||||||
// Header for ReadSdf.cc to communicate with SdfLex.cc, SdfParse.cc
|
// Header for SdfReader.cc to communicate with SdfLex.cc, SdfParse.cc
|
||||||
|
|
||||||
// global namespace
|
// global namespace
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue