read_vcd_activities
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
commit
cecb8cda7e
|
|
@ -173,7 +173,6 @@ set(STA_SOURCE
|
||||||
search/PathRef.cc
|
search/PathRef.cc
|
||||||
search/PathVertex.cc
|
search/PathVertex.cc
|
||||||
search/PathVertexRep.cc
|
search/PathVertexRep.cc
|
||||||
search/Power.cc
|
|
||||||
search/Property.cc
|
search/Property.cc
|
||||||
search/ReportPath.cc
|
search/ReportPath.cc
|
||||||
search/Search.cc
|
search/Search.cc
|
||||||
|
|
@ -189,6 +188,11 @@ set(STA_SOURCE
|
||||||
search/WorstSlack.cc
|
search/WorstSlack.cc
|
||||||
search/WritePathSpice.cc
|
search/WritePathSpice.cc
|
||||||
|
|
||||||
|
power/Power.cc
|
||||||
|
power/ReadVcdActivities.cc
|
||||||
|
power/Vcd.cc
|
||||||
|
power/VcdReader.cc
|
||||||
|
|
||||||
util/Debug.cc
|
util/Debug.cc
|
||||||
util/DispatchQueue.cc
|
util/DispatchQueue.cc
|
||||||
util/Error.cc
|
util/Error.cc
|
||||||
|
|
@ -227,10 +231,10 @@ set(STA_TCL_FILES
|
||||||
tcl/Cmds.tcl
|
tcl/Cmds.tcl
|
||||||
tcl/Variables.tcl
|
tcl/Variables.tcl
|
||||||
tcl/Sta.tcl
|
tcl/Sta.tcl
|
||||||
tcl/Power.tcl
|
|
||||||
tcl/Splash.tcl
|
tcl/Splash.tcl
|
||||||
dcalc/DelayCalc.tcl
|
dcalc/DelayCalc.tcl
|
||||||
parasitics/Parasitics.tcl
|
parasitics/Parasitics.tcl
|
||||||
|
power/Power.tcl
|
||||||
sdf/Sdf.tcl
|
sdf/Sdf.tcl
|
||||||
verilog/Verilog.tcl
|
verilog/Verilog.tcl
|
||||||
)
|
)
|
||||||
|
|
@ -313,18 +317,20 @@ set_property(SOURCE ${STA_SWIG_FILE}
|
||||||
-I${STA_HOME}/sdf
|
-I${STA_HOME}/sdf
|
||||||
-I${STA_HOME}/dcalc
|
-I${STA_HOME}/dcalc
|
||||||
-I${STA_HOME}/parasitics
|
-I${STA_HOME}/parasitics
|
||||||
|
-I${STA_HOME}/power
|
||||||
-I${STA_HOME}/verilog
|
-I${STA_HOME}/verilog
|
||||||
)
|
)
|
||||||
|
|
||||||
set_property(SOURCE ${STA_SWIG_FILE}
|
set_property(SOURCE ${STA_SWIG_FILE}
|
||||||
PROPERTY DEPENDS
|
PROPERTY DEPENDS
|
||||||
|
${STA_HOME}/dcalc/DelayCalc.i
|
||||||
|
${STA_HOME}/parasitics/Parasitics.i
|
||||||
|
${STA_HOME}/power/Power.i
|
||||||
|
${STA_HOME}/sdf/Sdf.i
|
||||||
${STA_HOME}/tcl/Exception.i
|
${STA_HOME}/tcl/Exception.i
|
||||||
${STA_HOME}/tcl/StaTcl.i
|
${STA_HOME}/tcl/StaTcl.i
|
||||||
${STA_HOME}/verilog/Verilog.i
|
|
||||||
${STA_HOME}/tcl/NetworkEdit.i
|
${STA_HOME}/tcl/NetworkEdit.i
|
||||||
${STA_HOME}/sdf/Sdf.i
|
${STA_HOME}/verilog/Verilog.i
|
||||||
${STA_HOME}/parasitics/Parasitics.i
|
|
||||||
${STA_HOME}/dcalc/DelayCalc.i
|
|
||||||
)
|
)
|
||||||
|
|
||||||
swig_add_library(sta_swig
|
swig_add_library(sta_swig
|
||||||
|
|
|
||||||
|
|
@ -23,3 +23,4 @@
|
||||||
%include "Sdf.i"
|
%include "Sdf.i"
|
||||||
%include "DelayCalc.i"
|
%include "DelayCalc.i"
|
||||||
%include "Parasitics.i"
|
%include "Parasitics.i"
|
||||||
|
%include "Power.i"
|
||||||
|
|
|
||||||
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -41,8 +41,8 @@
|
||||||
#include "GraphDelayCalc.hh"
|
#include "GraphDelayCalc.hh"
|
||||||
#include "Corner.hh"
|
#include "Corner.hh"
|
||||||
#include "PathVertex.hh"
|
#include "PathVertex.hh"
|
||||||
#include "Levelize.hh"
|
#include "search/Levelize.hh"
|
||||||
#include "Sim.hh"
|
#include "search/Sim.hh"
|
||||||
#include "Search.hh"
|
#include "Search.hh"
|
||||||
#include "Bfs.hh"
|
#include "Bfs.hh"
|
||||||
#include "ClkNetwork.hh"
|
#include "ClkNetwork.hh"
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
%module power
|
||||||
|
|
||||||
|
%{
|
||||||
|
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2022, 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 "Sta.hh"
|
||||||
|
#include "power/Power.hh"
|
||||||
|
#include "power/VcdReader.hh"
|
||||||
|
#include "power/ReadVcdActivities.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
typedef FloatSeq TmpFloatSeq;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
using namespace sta;
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%typemap(out) TmpFloatSeq* {
|
||||||
|
FloatSeq *floats = $1;
|
||||||
|
Tcl_Obj *list = Tcl_NewListObj(0, nullptr);
|
||||||
|
if (floats) {
|
||||||
|
for (unsigned i = 0; i < floats->size(); i++) {
|
||||||
|
Tcl_Obj *obj = Tcl_NewDoubleObj((*floats)[i]);
|
||||||
|
Tcl_ListObjAppendElement(interp, list, obj);
|
||||||
|
}
|
||||||
|
delete floats;
|
||||||
|
}
|
||||||
|
Tcl_SetObjResult(interp, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
|
||||||
|
TmpFloatSeq *
|
||||||
|
design_power(const Corner *corner)
|
||||||
|
{
|
||||||
|
cmdLinkedNetwork();
|
||||||
|
PowerResult total, sequential, combinational, macro, pad;
|
||||||
|
Sta::sta()->power(corner, total, sequential, combinational, macro, pad);
|
||||||
|
FloatSeq *floats = new FloatSeq;
|
||||||
|
pushPowerResultFloats(total, floats);
|
||||||
|
pushPowerResultFloats(sequential, floats);
|
||||||
|
pushPowerResultFloats(combinational, floats);
|
||||||
|
pushPowerResultFloats(macro, floats);
|
||||||
|
pushPowerResultFloats(pad, floats);
|
||||||
|
return floats;
|
||||||
|
}
|
||||||
|
|
||||||
|
TmpFloatSeq *
|
||||||
|
instance_power(Instance *inst,
|
||||||
|
const Corner *corner)
|
||||||
|
{
|
||||||
|
cmdLinkedNetwork();
|
||||||
|
PowerResult power;
|
||||||
|
Sta::sta()->power(inst, corner, power);
|
||||||
|
FloatSeq *floats = new FloatSeq;
|
||||||
|
floats->push_back(power.internal());
|
||||||
|
floats->push_back(power.switching());
|
||||||
|
floats->push_back(power.leakage());
|
||||||
|
floats->push_back(power.total());
|
||||||
|
return floats;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_power_global_activity(float activity,
|
||||||
|
float duty)
|
||||||
|
{
|
||||||
|
Sta::sta()->power()->setGlobalActivity(activity, duty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_power_input_activity(float activity,
|
||||||
|
float duty)
|
||||||
|
{
|
||||||
|
return Sta::sta()->power()->setInputActivity(activity, duty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_power_input_port_activity(const Port *input_port,
|
||||||
|
float activity,
|
||||||
|
float duty)
|
||||||
|
{
|
||||||
|
return Sta::sta()->power()->setInputPortActivity(input_port, activity, duty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_power_pin_activity(const Pin *pin,
|
||||||
|
float activity,
|
||||||
|
float duty)
|
||||||
|
{
|
||||||
|
return Sta::sta()->power()->setUserActivity(pin, activity, duty,
|
||||||
|
PwrActivityOrigin::user);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
read_vcd_activities(const char *filename)
|
||||||
|
{
|
||||||
|
readVcdActivities(filename, Sta::sta());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
report_vcd_waveforms(const char *filename)
|
||||||
|
{
|
||||||
|
reportVcdWaveforms(filename, Sta::sta());
|
||||||
|
}
|
||||||
|
|
||||||
|
%} // inline
|
||||||
|
|
@ -246,6 +246,11 @@ proc set_power_activity { args } {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
################################################################
|
||||||
|
|
||||||
|
# Defined in StaTcl.i
|
||||||
|
define_cmd_args "read_vcd_activities" { filename }
|
||||||
|
|
||||||
proc power_find_nan { } {
|
proc power_find_nan { } {
|
||||||
set corner [cmd_corner]
|
set corner [cmd_corner]
|
||||||
foreach inst [network_leaf_instances] {
|
foreach inst [network_leaf_instances] {
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2022, 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 "ReadVcdActivities.hh"
|
||||||
|
|
||||||
|
#include "VcdReader.hh"
|
||||||
|
#include "Debug.hh"
|
||||||
|
#include "Network.hh"
|
||||||
|
#include "VerilogNamespace.hh"
|
||||||
|
#include "ParseBus.hh"
|
||||||
|
#include "Sdc.hh"
|
||||||
|
#include "Power.hh"
|
||||||
|
#include "Sta.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
using std::min;
|
||||||
|
using std::swap;
|
||||||
|
using std::to_string;
|
||||||
|
|
||||||
|
static void
|
||||||
|
setVcdActivities(Vcd &vcd,
|
||||||
|
Sta *sta);
|
||||||
|
static void
|
||||||
|
setPinActivity(const char *pin_name,
|
||||||
|
int transition_count,
|
||||||
|
float activity,
|
||||||
|
float duty,
|
||||||
|
Debug *debug,
|
||||||
|
Network *network,
|
||||||
|
Power *power);
|
||||||
|
void
|
||||||
|
readVcdActivities(const char *filename,
|
||||||
|
Sta *sta)
|
||||||
|
{
|
||||||
|
Vcd vcd = readVcdFile(filename, sta);
|
||||||
|
setVcdActivities(vcd, sta);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setVcdActivities(Vcd &vcd,
|
||||||
|
Sta *sta)
|
||||||
|
{
|
||||||
|
Debug *debug = sta->debug();
|
||||||
|
Network *network = sta->network();
|
||||||
|
Power *power = sta->power();
|
||||||
|
|
||||||
|
float clk_period = 0.0;
|
||||||
|
for (Clock *clk : *sta->sdc()->clocks())
|
||||||
|
clk_period = min(clk->period(), clk_period);
|
||||||
|
|
||||||
|
VarTime time_max = vcd.timeMax();
|
||||||
|
for (VcdVar &var : vcd.vars()) {
|
||||||
|
const VcdValues &var_values = vcd.values(var);
|
||||||
|
if (!var_values.empty()) {
|
||||||
|
int transition_count = 0;
|
||||||
|
char prev_value = var_values[0].value();
|
||||||
|
VarTime prev_time = var_values[0].time();
|
||||||
|
VarTime high_time = 0;
|
||||||
|
for (const VcdValue &var_value : var_values) {
|
||||||
|
VarTime time = var_value.time();
|
||||||
|
char value = var_value.value();
|
||||||
|
if (prev_value == '1')
|
||||||
|
high_time += time - prev_time;
|
||||||
|
transition_count++;
|
||||||
|
prev_time = time;
|
||||||
|
prev_value = value;
|
||||||
|
}
|
||||||
|
if (prev_value == '1')
|
||||||
|
high_time += time_max - prev_time;
|
||||||
|
float duty = static_cast<float>(high_time) / time_max;
|
||||||
|
float activity = transition_count
|
||||||
|
/ (time_max * vcd.timeUnitScale() / clk_period);
|
||||||
|
|
||||||
|
string var_name = var.name();
|
||||||
|
if (var_name[0] == '\\')
|
||||||
|
var_name += ' ';
|
||||||
|
const char *sta_name = verilogToSta(var_name.c_str());
|
||||||
|
if (var.width() == 1) {
|
||||||
|
setPinActivity(sta_name, transition_count, activity, duty,
|
||||||
|
debug, network, power);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
char *bus_name;
|
||||||
|
int from, to;
|
||||||
|
parseBusRange(sta_name, '[', ']', '\\',
|
||||||
|
bus_name, from, to);
|
||||||
|
if (from > to)
|
||||||
|
swap(from, to);
|
||||||
|
for (int bit = from; bit <= to; bit++) {
|
||||||
|
string name = bus_name;
|
||||||
|
name += '[';
|
||||||
|
name += to_string(bit);
|
||||||
|
name += ']';
|
||||||
|
setPinActivity(name.c_str(), transition_count, activity, duty,
|
||||||
|
debug, network, power);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setPinActivity(const char *pin_name,
|
||||||
|
int transition_count,
|
||||||
|
float activity,
|
||||||
|
float duty,
|
||||||
|
Debug *debug,
|
||||||
|
Network *network,
|
||||||
|
Power *power)
|
||||||
|
{
|
||||||
|
Pin *pin = network->findPin(pin_name);
|
||||||
|
if (pin) {
|
||||||
|
debugPrint(debug, "vcd_activities", 1,
|
||||||
|
"%s transitions %d activity %.2f duty %.2f",
|
||||||
|
pin_name,
|
||||||
|
transition_count,
|
||||||
|
activity,
|
||||||
|
duty);
|
||||||
|
power->setUserActivity(pin, activity, duty,
|
||||||
|
PwrActivityOrigin::user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2022, 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;
|
||||||
|
|
||||||
|
void
|
||||||
|
readVcdActivities(const char *filename,
|
||||||
|
Sta *sta);
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
@ -0,0 +1,151 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2022, 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 "Vcd.hh"
|
||||||
|
|
||||||
|
#include "Report.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
Vcd::Vcd(StaState *sta) :
|
||||||
|
StaState(sta),
|
||||||
|
time_unit_scale_(0.0),
|
||||||
|
max_var_name_length_(0),
|
||||||
|
max_var_width_(0),
|
||||||
|
time_max_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void
|
||||||
|
Vcd::setTimeUnit(const string &time_unit,
|
||||||
|
double time_unit_scale)
|
||||||
|
{
|
||||||
|
time_unit_ = time_unit;
|
||||||
|
time_unit_scale_ = time_unit_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Vcd::setDate(const string &date)
|
||||||
|
{
|
||||||
|
date_ = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Vcd::setComment(const string &comment)
|
||||||
|
{
|
||||||
|
comment_ = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Vcd::setVersion(const string &version)
|
||||||
|
{
|
||||||
|
version_ = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Vcd::setTimeScale(double time_scale)
|
||||||
|
{
|
||||||
|
time_scale_ = time_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Vcd::setMinDeltaTime(VarTime min_delta_time)
|
||||||
|
{
|
||||||
|
min_delta_time_ = min_delta_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Vcd::setTimeMax(VarTime time_max)
|
||||||
|
{
|
||||||
|
time_max_ = time_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Vcd::makeVar(string &name,
|
||||||
|
VcdVarType type,
|
||||||
|
int width,
|
||||||
|
string &id)
|
||||||
|
{
|
||||||
|
vars_.push_back(VcdVar(name, type, width, id));
|
||||||
|
max_var_name_length_ = std::max(max_var_name_length_, name.size());
|
||||||
|
max_var_width_ = std::max(max_var_width_, width);
|
||||||
|
// Make entry for var ID.
|
||||||
|
id_values_map_[id].clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Vcd::varIdValid(string &id)
|
||||||
|
{
|
||||||
|
return id_values_map_.find(id) != id_values_map_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Vcd::varAppendValue(string &id,
|
||||||
|
VarTime time,
|
||||||
|
char value)
|
||||||
|
{
|
||||||
|
VcdValues &values = id_values_map_[id];
|
||||||
|
values.push_back(VcdValue(time, value, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Vcd::varAppendBusValue(string &id,
|
||||||
|
VarTime time,
|
||||||
|
int64_t bus_value)
|
||||||
|
{
|
||||||
|
VcdValues &values = id_values_map_[id];
|
||||||
|
values.push_back(VcdValue(time, '\0', bus_value));
|
||||||
|
}
|
||||||
|
|
||||||
|
VcdValues &
|
||||||
|
Vcd::values(VcdVar &var)
|
||||||
|
{
|
||||||
|
if (id_values_map_.find(var.id()) == id_values_map_.end()) {
|
||||||
|
report_->error(805, "Unknown variable %s ID %s",
|
||||||
|
var.name().c_str(),
|
||||||
|
var.id().c_str());
|
||||||
|
static VcdValues empty;
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return id_values_map_[var.id()];
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
VcdVar::VcdVar(string name,
|
||||||
|
VcdVarType type,
|
||||||
|
int width,
|
||||||
|
string id) :
|
||||||
|
name_(name),
|
||||||
|
type_(type),
|
||||||
|
width_(width),
|
||||||
|
id_(id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VcdValue::VcdValue(VarTime time,
|
||||||
|
char value,
|
||||||
|
uint64_t bus_value) :
|
||||||
|
time_(time),
|
||||||
|
value_(value),
|
||||||
|
bus_value_(bus_value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2022, 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 <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "StaState.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
using std::map;
|
||||||
|
using std::max;
|
||||||
|
using std::min;
|
||||||
|
|
||||||
|
class VcdVar;
|
||||||
|
class VcdValue;
|
||||||
|
typedef vector<VcdValue> VcdValues;
|
||||||
|
typedef int64_t VarTime;
|
||||||
|
typedef vector<string> VcdScope;
|
||||||
|
|
||||||
|
enum class VcdVarType { wire, reg, parameter, real };
|
||||||
|
|
||||||
|
class Vcd : public StaState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Vcd(StaState *sta);
|
||||||
|
VcdValues &values(VcdVar &var);
|
||||||
|
|
||||||
|
const string &date() const { return date_; }
|
||||||
|
void setDate(const string &date);
|
||||||
|
const string &comment() const { return comment_; }
|
||||||
|
void setComment(const string &comment);
|
||||||
|
const string &version() const { return version_; }
|
||||||
|
void setVersion(const string &version);
|
||||||
|
double timeScale() const { return time_scale_; }
|
||||||
|
void setTimeScale(double time_scale);
|
||||||
|
const string &timeUnit() const { return time_unit_; }
|
||||||
|
double timeUnitScale() const { return time_unit_scale_; }
|
||||||
|
void setTimeUnit(const string &time_unit,
|
||||||
|
double time_unit_scale);
|
||||||
|
VarTime timeMax() const { return time_max_; }
|
||||||
|
void setTimeMax(VarTime time_max);
|
||||||
|
VarTime minDeltaTime() const { return min_delta_time_; }
|
||||||
|
void setMinDeltaTime(VarTime min_delta_time);
|
||||||
|
vector<VcdVar> vars() { return vars_; }
|
||||||
|
void makeVar(string &name,
|
||||||
|
VcdVarType type,
|
||||||
|
int width,
|
||||||
|
string &id);
|
||||||
|
int maxVarWidth() const { return max_var_width_; }
|
||||||
|
int maxVarNameLength() const { return max_var_name_length_; }
|
||||||
|
bool varIdValid(string &id);
|
||||||
|
void varAppendValue(string &id,
|
||||||
|
VarTime time,
|
||||||
|
char value);
|
||||||
|
void varAppendBusValue(string &id,
|
||||||
|
VarTime time,
|
||||||
|
int64_t bus_value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
string date_;
|
||||||
|
string comment_;
|
||||||
|
string version_;
|
||||||
|
double time_scale_;
|
||||||
|
string time_unit_;
|
||||||
|
double time_unit_scale_;
|
||||||
|
|
||||||
|
vector<VcdVar> vars_;
|
||||||
|
size_t max_var_name_length_;
|
||||||
|
int max_var_width_;
|
||||||
|
map<string, VcdValues> id_values_map_;
|
||||||
|
VarTime min_delta_time_;
|
||||||
|
VarTime time_max_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VcdVar
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VcdVar(string name,
|
||||||
|
VcdVarType type,
|
||||||
|
int width,
|
||||||
|
string id);
|
||||||
|
const string& name() const { return name_; }
|
||||||
|
VcdVarType type() const { return type_; }
|
||||||
|
int width() const { return width_; }
|
||||||
|
const string& id() const { return id_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
string name_;
|
||||||
|
VcdVarType type_;
|
||||||
|
int width_;
|
||||||
|
string id_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class VcdValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VcdValue(VarTime time,
|
||||||
|
char value,
|
||||||
|
uint64_t bus_value);
|
||||||
|
VarTime time() const { return time_; }
|
||||||
|
char value() const { return value_; }
|
||||||
|
uint64_t busValue() const { return bus_value_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
VarTime time_;
|
||||||
|
// 01XUZ or '\0' when width > 1 to use bus_value_.
|
||||||
|
char value_;
|
||||||
|
uint64_t bus_value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
@ -0,0 +1,411 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2022, 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 "VcdReader.hh"
|
||||||
|
|
||||||
|
#include "Zlib.hh"
|
||||||
|
#include "Report.hh"
|
||||||
|
#include "StringUtil.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
using std::isspace;
|
||||||
|
|
||||||
|
// Very imprecise syntax definition
|
||||||
|
// https://en.wikipedia.org/wiki/Value_change_dump#Structure.2FSyntax
|
||||||
|
// Much better syntax definition
|
||||||
|
// https://web.archive.org/web/20120323132708/http://www.beyondttl.com/vcd.php
|
||||||
|
|
||||||
|
class VcdReader : public StaState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VcdReader(StaState *sta);
|
||||||
|
Vcd read(const char *filename);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void parseTimescale();
|
||||||
|
void setTimeUnit(const string &time_unit);
|
||||||
|
void parseVar();
|
||||||
|
void parseScope();
|
||||||
|
void parseUpscope();
|
||||||
|
void parseVarValues();
|
||||||
|
string getToken();
|
||||||
|
string readStmtString();
|
||||||
|
vector<string> readStmtTokens();
|
||||||
|
|
||||||
|
gzFile stream_;
|
||||||
|
string token_;
|
||||||
|
const char *filename_;
|
||||||
|
int file_line_;
|
||||||
|
int stmt_line_;
|
||||||
|
|
||||||
|
Vcd *vcd_;
|
||||||
|
VarTime time_;
|
||||||
|
VarTime prev_time_;
|
||||||
|
VcdScope scope_;
|
||||||
|
};
|
||||||
|
|
||||||
|
Vcd
|
||||||
|
readVcdFile(const char *filename,
|
||||||
|
StaState *sta)
|
||||||
|
|
||||||
|
{
|
||||||
|
VcdReader reader(sta);
|
||||||
|
return reader.read(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
Vcd
|
||||||
|
VcdReader::read(const char *filename)
|
||||||
|
{
|
||||||
|
Vcd vcd(this);
|
||||||
|
vcd_ = &vcd;
|
||||||
|
stream_ = gzopen(filename, "r");
|
||||||
|
if (stream_) {
|
||||||
|
filename_ = filename;
|
||||||
|
file_line_ = 1;
|
||||||
|
stmt_line_ = 1;
|
||||||
|
string token = getToken();
|
||||||
|
while (!token.empty()) {
|
||||||
|
if (token == "$date")
|
||||||
|
vcd_->setDate(readStmtString());
|
||||||
|
else if (token == "$comment")
|
||||||
|
vcd_->setComment(readStmtString());
|
||||||
|
else if (token == "$version")
|
||||||
|
vcd_->setVersion(readStmtString());
|
||||||
|
else if (token == "$timescale")
|
||||||
|
parseTimescale();
|
||||||
|
else if (token == "$var")
|
||||||
|
parseVar();
|
||||||
|
else if (token == "$scope")
|
||||||
|
parseScope();
|
||||||
|
else if (token == "$upscope")
|
||||||
|
parseUpscope();
|
||||||
|
else if (token == "$enddefinitions")
|
||||||
|
// empty body
|
||||||
|
readStmtString();
|
||||||
|
else if (token == "$dumpall")
|
||||||
|
parseVarValues();
|
||||||
|
else if (token == "$dumpvars")
|
||||||
|
// Initial values.
|
||||||
|
parseVarValues();
|
||||||
|
else if (token[0] == '$')
|
||||||
|
report_->fileError(800, filename_, stmt_line_, "unhandled vcd command.");
|
||||||
|
else
|
||||||
|
parseVarValues();
|
||||||
|
token = getToken();
|
||||||
|
}
|
||||||
|
gzclose(stream_);
|
||||||
|
}
|
||||||
|
return vcd;
|
||||||
|
}
|
||||||
|
|
||||||
|
VcdReader::VcdReader(StaState *sta) :
|
||||||
|
StaState(sta),
|
||||||
|
stmt_line_(0),
|
||||||
|
vcd_(nullptr),
|
||||||
|
time_(0),
|
||||||
|
prev_time_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VcdReader::parseTimescale()
|
||||||
|
{
|
||||||
|
vector<string> tokens = readStmtTokens();
|
||||||
|
if (tokens.size() == 1) {
|
||||||
|
size_t last;
|
||||||
|
vcd_->setTimeScale(std::stod(tokens[0], &last));
|
||||||
|
setTimeUnit(tokens[0].substr(last));
|
||||||
|
}
|
||||||
|
else if (tokens.size() == 2) {
|
||||||
|
vcd_->setTimeScale(std::stod(tokens[0]));
|
||||||
|
setTimeUnit(tokens[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
report_->fileError(800, filename_, stmt_line_, "timescale syntax error.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VcdReader::setTimeUnit(const string &time_unit)
|
||||||
|
{
|
||||||
|
double time_unit_scale = 1.0;
|
||||||
|
if (time_unit == "fs")
|
||||||
|
time_unit_scale = 1e-15;
|
||||||
|
else if (time_unit == "ps")
|
||||||
|
time_unit_scale = 1e-12;
|
||||||
|
else if (time_unit == "ns")
|
||||||
|
time_unit_scale = 1e-9;
|
||||||
|
else
|
||||||
|
report_->fileError(801, filename_, stmt_line_, "Unknown timescale unit.");
|
||||||
|
vcd_->setTimeUnit(time_unit, time_unit_scale);;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VcdReader::parseVar()
|
||||||
|
{
|
||||||
|
vector<string> tokens = readStmtTokens();
|
||||||
|
if (tokens.size() == 4
|
||||||
|
|| tokens.size() == 5) {
|
||||||
|
string type_name = tokens[0];
|
||||||
|
VcdVarType type = VcdVarType::wire;
|
||||||
|
if (type_name == "wire")
|
||||||
|
type = VcdVarType::wire;
|
||||||
|
else if (type_name == "reg")
|
||||||
|
type = VcdVarType::reg;
|
||||||
|
else if (type_name == "parameter")
|
||||||
|
type = VcdVarType::parameter;
|
||||||
|
else if (type_name == "real")
|
||||||
|
type = VcdVarType::real;
|
||||||
|
else
|
||||||
|
report_->fileError(803, filename_, stmt_line_,
|
||||||
|
"Unknown variable type %s.",
|
||||||
|
type_name.c_str());
|
||||||
|
|
||||||
|
int width = stoi(tokens[1]);
|
||||||
|
string id = tokens[2];
|
||||||
|
string name;
|
||||||
|
|
||||||
|
int level = 0;
|
||||||
|
for (string &context : scope_) {
|
||||||
|
// Skip the first 2 levels of scope.
|
||||||
|
// -test bench module
|
||||||
|
// -design instance
|
||||||
|
if (level > 1) {
|
||||||
|
name += context;
|
||||||
|
name += '/';
|
||||||
|
}
|
||||||
|
level++;
|
||||||
|
}
|
||||||
|
name += tokens[3];
|
||||||
|
// iverilog separates bus base name from bit range.
|
||||||
|
if (tokens.size() == 5)
|
||||||
|
name += tokens[4];
|
||||||
|
|
||||||
|
vcd_->makeVar(name, type, width, id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
report_->fileError(802, filename_, stmt_line_, "Variable syntax error.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VcdReader::parseScope()
|
||||||
|
{
|
||||||
|
vector<string> tokens = readStmtTokens();
|
||||||
|
string &scope = tokens[1];
|
||||||
|
scope_.push_back(scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VcdReader::parseUpscope()
|
||||||
|
{
|
||||||
|
readStmtTokens();
|
||||||
|
scope_.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
VcdReader::parseVarValues()
|
||||||
|
{
|
||||||
|
string token = getToken();
|
||||||
|
while (!token.empty()) {
|
||||||
|
char char0 = toupper(token[0]);
|
||||||
|
if (char0 == '#') {
|
||||||
|
prev_time_ = time_;
|
||||||
|
time_ = stoll(token.substr(1));
|
||||||
|
if (time_ > prev_time_)
|
||||||
|
vcd_->setMinDeltaTime(min(time_ - prev_time_, vcd_->minDeltaTime()));
|
||||||
|
}
|
||||||
|
else if (char0 == '0'
|
||||||
|
|| char0 == '1'
|
||||||
|
|| char0 == 'X'
|
||||||
|
|| char0 == 'U'
|
||||||
|
|| char0 == 'Z') {
|
||||||
|
string id = token.substr(1);
|
||||||
|
if (!vcd_->varIdValid(id))
|
||||||
|
report_->fileError(804, filename_, stmt_line_,
|
||||||
|
"unknown variable %s", id.c_str());
|
||||||
|
vcd_->varAppendValue(id, time_, char0);
|
||||||
|
}
|
||||||
|
else if (char0 == 'B') {
|
||||||
|
char char1 = toupper(token[1]);
|
||||||
|
if (char1 == 'X'
|
||||||
|
|| char1 == 'U'
|
||||||
|
|| char1 == 'Z') {
|
||||||
|
string id = getToken();
|
||||||
|
if (!vcd_->varIdValid(id))
|
||||||
|
report_->fileError(804, filename_, stmt_line_,
|
||||||
|
"unknown variable %s", id.c_str());
|
||||||
|
// Bus mixed 0/1/X/U not supported.
|
||||||
|
vcd_->varAppendValue(id, time_, char1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
string bin = token.substr(1);
|
||||||
|
char *end;
|
||||||
|
int64_t bus_value = strtol(bin.c_str(), &end, 2);
|
||||||
|
string id = getToken();
|
||||||
|
if (!vcd_->varIdValid(id))
|
||||||
|
report_->fileError(804, filename_, stmt_line_,
|
||||||
|
"unknown variable %s", id.c_str());
|
||||||
|
else
|
||||||
|
vcd_->varAppendBusValue(id, time_, bus_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
token = getToken();
|
||||||
|
}
|
||||||
|
vcd_->setTimeMax(time_);
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
VcdReader::readStmtString()
|
||||||
|
{
|
||||||
|
stmt_line_ = file_line_;
|
||||||
|
string line;
|
||||||
|
string token = getToken();
|
||||||
|
while (!token.empty() && token != "$end") {
|
||||||
|
if (!line.empty())
|
||||||
|
line += " ";
|
||||||
|
line += token;
|
||||||
|
token = getToken();
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string>
|
||||||
|
VcdReader::readStmtTokens()
|
||||||
|
{
|
||||||
|
stmt_line_ = file_line_;
|
||||||
|
vector<string> tokens;
|
||||||
|
string token = getToken();
|
||||||
|
while (!token.empty() && token != "$end") {
|
||||||
|
tokens.push_back(token);
|
||||||
|
token = getToken();
|
||||||
|
}
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
VcdReader::getToken()
|
||||||
|
{
|
||||||
|
string token;
|
||||||
|
int ch = gzgetc(stream_);
|
||||||
|
if (ch == '\n')
|
||||||
|
file_line_++;
|
||||||
|
// skip whitespace
|
||||||
|
while (ch != EOF && isspace(ch)) {
|
||||||
|
ch = gzgetc(stream_);
|
||||||
|
if (ch == '\n')
|
||||||
|
file_line_++;
|
||||||
|
}
|
||||||
|
while (ch != EOF && !isspace(ch)) {
|
||||||
|
token.push_back(ch);
|
||||||
|
ch = gzgetc(stream_);
|
||||||
|
if (ch == '\n')
|
||||||
|
file_line_++;
|
||||||
|
}
|
||||||
|
if (ch == EOF)
|
||||||
|
return "";
|
||||||
|
else
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
static void
|
||||||
|
reportWaveforms(Vcd &vcd,
|
||||||
|
Report *report);
|
||||||
|
|
||||||
|
void
|
||||||
|
reportVcdWaveforms(const char *filename,
|
||||||
|
StaState *sta)
|
||||||
|
|
||||||
|
{
|
||||||
|
Vcd vcd = readVcdFile(filename, sta);
|
||||||
|
reportWaveforms(vcd, sta->report());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reportWaveforms(Vcd &vcd,
|
||||||
|
Report *report)
|
||||||
|
{
|
||||||
|
report->reportLine("Date: %s", vcd.date().c_str());
|
||||||
|
report->reportLine("Timescale: %.2f%s", vcd.timeScale(), vcd.timeUnit().c_str());
|
||||||
|
// Characters per time sample.
|
||||||
|
int zoom = (vcd.maxVarWidth() + 7) / 4;
|
||||||
|
int time_delta = vcd.minDeltaTime();
|
||||||
|
|
||||||
|
int max_var_name_length = vcd.maxVarNameLength();
|
||||||
|
for (VcdVar &var : vcd.vars()) {
|
||||||
|
string line;
|
||||||
|
stringPrint(line, " %-*s",
|
||||||
|
static_cast<int>(max_var_name_length),
|
||||||
|
var.name().c_str());
|
||||||
|
const VcdValues &var_values = vcd.values(var);
|
||||||
|
if (!var_values.empty()) {
|
||||||
|
size_t value_index = 0;
|
||||||
|
VcdValue var_value = var_values[value_index];
|
||||||
|
VcdValue prev_var_value = var_values[value_index];
|
||||||
|
VarTime next_value_time = var_values[value_index + 1].time();
|
||||||
|
for (double time = 0.0; time < vcd.timeMax(); time += time_delta) {
|
||||||
|
if (time >= next_value_time) {
|
||||||
|
if (value_index < var_values.size() - 1)
|
||||||
|
value_index++;
|
||||||
|
var_value = var_values[value_index];
|
||||||
|
if (value_index < var_values.size())
|
||||||
|
next_value_time = var_values[value_index + 1].time();
|
||||||
|
}
|
||||||
|
if (var_value.value()) {
|
||||||
|
// 01UZX
|
||||||
|
char value = var_value.value();
|
||||||
|
char prev_value = prev_var_value.value();
|
||||||
|
if (var.width() == 1) {
|
||||||
|
if (value == '0' || value == '1') {
|
||||||
|
for (int z = 0; z < zoom; z++) {
|
||||||
|
if (z == 0
|
||||||
|
&& value != prev_value
|
||||||
|
&& (prev_value == '0'
|
||||||
|
|| prev_value == '1'))
|
||||||
|
line += (prev_value == '1') ? "╲" : "╱";
|
||||||
|
else
|
||||||
|
line += (value == '1') ? "▔" : "▁";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
string field;
|
||||||
|
stringPrint(field, "%-*c", zoom, value);
|
||||||
|
line += field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
string field;
|
||||||
|
stringPrint(field, "%-*c", zoom, value);
|
||||||
|
line += field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// bus
|
||||||
|
string field;
|
||||||
|
stringPrint(field, "%-*llX", zoom, var_value.busValue());
|
||||||
|
line += field;
|
||||||
|
}
|
||||||
|
prev_var_value = var_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
report->reportLineString(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
// OpenSTA, Static Timing Analyzer
|
||||||
|
// Copyright (c) 2022, 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 "Vcd.hh"
|
||||||
|
|
||||||
|
namespace sta {
|
||||||
|
|
||||||
|
class StaState;
|
||||||
|
|
||||||
|
Vcd
|
||||||
|
readVcdFile(const char *filename,
|
||||||
|
StaState *sta);
|
||||||
|
|
||||||
|
void
|
||||||
|
reportVcdWaveforms(const char *filename,
|
||||||
|
StaState *sta);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
#include "PathEnd.hh"
|
#include "PathEnd.hh"
|
||||||
#include "PathExpanded.hh"
|
#include "PathExpanded.hh"
|
||||||
#include "PathRef.hh"
|
#include "PathRef.hh"
|
||||||
#include "Power.hh"
|
#include "power/Power.hh"
|
||||||
#include "Sta.hh"
|
#include "Sta.hh"
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@
|
||||||
#include "VisitPathGroupVertices.hh"
|
#include "VisitPathGroupVertices.hh"
|
||||||
#include "Genclks.hh"
|
#include "Genclks.hh"
|
||||||
#include "ClkNetwork.hh"
|
#include "ClkNetwork.hh"
|
||||||
#include "Power.hh"
|
#include "power/Power.hh"
|
||||||
#include "VisitPathEnds.hh"
|
#include "VisitPathEnds.hh"
|
||||||
#include "PathExpanded.hh"
|
#include "PathExpanded.hh"
|
||||||
#include "MakeTimingModel.hh"
|
#include "MakeTimingModel.hh"
|
||||||
|
|
|
||||||
64
tcl/StaTcl.i
64
tcl/StaTcl.i
|
|
@ -79,7 +79,6 @@
|
||||||
#include "search/CheckMinPulseWidths.hh"
|
#include "search/CheckMinPulseWidths.hh"
|
||||||
#include "search/Levelize.hh"
|
#include "search/Levelize.hh"
|
||||||
#include "search/ReportPath.hh"
|
#include "search/ReportPath.hh"
|
||||||
#include "search/Power.hh"
|
|
||||||
|
|
||||||
namespace sta {
|
namespace sta {
|
||||||
|
|
||||||
|
|
@ -4946,69 +4945,6 @@ report_capacitance_limit_verbose(Pin *pin,
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TmpFloatSeq *
|
|
||||||
design_power(const Corner *corner)
|
|
||||||
{
|
|
||||||
cmdLinkedNetwork();
|
|
||||||
PowerResult total, sequential, combinational, macro, pad;
|
|
||||||
Sta::sta()->power(corner, total, sequential, combinational, macro, pad);
|
|
||||||
FloatSeq *floats = new FloatSeq;
|
|
||||||
pushPowerResultFloats(total, floats);
|
|
||||||
pushPowerResultFloats(sequential, floats);
|
|
||||||
pushPowerResultFloats(combinational, floats);
|
|
||||||
pushPowerResultFloats(macro, floats);
|
|
||||||
pushPowerResultFloats(pad, floats);
|
|
||||||
return floats;
|
|
||||||
}
|
|
||||||
|
|
||||||
TmpFloatSeq *
|
|
||||||
instance_power(Instance *inst,
|
|
||||||
const Corner *corner)
|
|
||||||
{
|
|
||||||
cmdLinkedNetwork();
|
|
||||||
PowerResult power;
|
|
||||||
Sta::sta()->power(inst, corner, power);
|
|
||||||
FloatSeq *floats = new FloatSeq;
|
|
||||||
floats->push_back(power.internal());
|
|
||||||
floats->push_back(power.switching());
|
|
||||||
floats->push_back(power.leakage());
|
|
||||||
floats->push_back(power.total());
|
|
||||||
return floats;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
set_power_global_activity(float activity,
|
|
||||||
float duty)
|
|
||||||
{
|
|
||||||
Sta::sta()->power()->setGlobalActivity(activity, duty);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
set_power_input_activity(float activity,
|
|
||||||
float duty)
|
|
||||||
{
|
|
||||||
return Sta::sta()->power()->setInputActivity(activity, duty);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
set_power_input_port_activity(const Port *input_port,
|
|
||||||
float activity,
|
|
||||||
float duty)
|
|
||||||
{
|
|
||||||
return Sta::sta()->power()->setInputPortActivity(input_port, activity, duty);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
set_power_pin_activity(const Pin *pin,
|
|
||||||
float activity,
|
|
||||||
float duty)
|
|
||||||
{
|
|
||||||
return Sta::sta()->power()->setUserActivity(pin, activity, duty,
|
|
||||||
PwrActivityOrigin::user);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
EdgeSeq *
|
EdgeSeq *
|
||||||
disabled_edges_sorted()
|
disabled_edges_sorted()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue